zoukankan      html  css  js  c++  java
  • Makefile

    https://blog.atime.me/note/makefile.html

    总结GNU Make的一些基础知识和技巧,以下内容均基于Ubuntu 14.04 x86_64平台的GNU Make 3.81。

    变量

    变量类型

    make支持两种风格的变量定义方式:

    1. 递归扩展变量(recursively expanded variables)
      • 使用=或define指令定义
      • CFLAGS = $(CFLAGS) -O会导致无限递归
      • 变量每次被展开的时候,所使用的函数都会重新被执行,会降低make的效率,更严重的是,wildcard等函数会返回预料之外的结果。
    2. 简单扩展变量(simply expanded varialbes)
      • 使用:=::=定义
      • 在变量定义的时候展开一次

    shell变量

    shell变量应使用@转义,比如变量${var}要改为$${var}

    自动变量

    下面是一些常用的自动变量

    • $<: 第一个依赖
    • $@: 目标
    • $?: 修改时间在目标之后的依赖
    • $^: 所有的依赖
    • $|: 所有的order-only依赖

    预定义变量

    Makefile中预定义了一些变量,通常用于Implicit Rules中,详细列表见Implicit Variables。其中常用的有:

    • CC: C编译器,默认是cc
    • CXX: C++编译器,默认是g++
    • CFLAGS: 传递给C编译器的编译参数
    • CXXFLAGS: 传递给C++编译器的编译参数
    • LDFLAGS: 传递给编译器的链接参数

    函数和指令

    wildcard

    wildcard函数和直接使用通配符*的区别在于,wildcard函数可以在变量定义的时候立即展开(即搜索相应的匹配项),而*只有在规则中才会被展开。1

    subst

    sust函数用于替换字符串,格式是$(subst from,to,text),其中from是要被替换的子串,to是要替换成的子串,text是需要被替换的字符串。注意from和to之间的逗号左右不要随意添加空格,否则也会被视为需要替换的内容。

    patsubst

    patsubst函数可以匹配并保留第一个没被转义的%字符,然后在替换成的字符串里使用,比如$(patsubst %.css,%.min.css,hello.css)替换的结果就是hello.min.css,同样的,逗号左右不要随意添加空白字符。类似的功能还可以用Substitution References实现,语法更简洁一些。

    filter

    filter函数可以按一定的规则过滤目标,然后返回符合规则的数据。

    规则

    order-only依赖

    a: b | c
        command
    

    上面的例子中,a是目标,b是常规依赖,c是order-only依赖。当a存在时,即便c的修改时间晚于a,该规则也不会更新a。

    order-only依赖定义于规则的右侧,与常规依赖用|隔开。当目标存在时,不管其是否因order-only依赖而过期,均不更新目标。

    static pattern rules

    当有大量类似的目标时,static pattern rules会很有用,格式如下

    targets ...: target-pattern: prereq-patterns ...
        recipe
        ...
    

    用下面的一个简单例子说明

    a.o b.o c.o: %.o: %.c
        gcc -c -o $@ $<
    

    这里targets是a.o b.o c.o,target pattern是%.o,prereq-patterns(只有一个)是%.c。target pattern首先从targets里匹配出一个个的目标,然后按照类似于patsubst的方式替换prereq-patterns中的%字符,生成相应的依赖。在规则的命令中,可以像普通的规则一样使用$<(第一个依赖)和$@(目标)等自动变量

    上面的规则可以拆成几条简单的规则:

    a.o:a.c
        gcc -c -o $@ $<
    
    b.o:b.c
        gcc -c -o $@ $<
    
    c.o:c.c
        gcc -c -o $@ $<
    

    或者使用字符串替换,更方便一些

    source = ${wildcard *.c}
    objects = ${source:%.c=%.o}
    
    all: ${objects}
    
    ${objects}: %.o: %.c
        gcc -c -o $@ $<
    

    其它

    特殊的符号

    • @: 用于规则中的命令之前,可以在make时只显示命令的输出而不显示命令的内容,比如

      all:
          @echo hello
      

      只输出hello,不会输出echo hello这条命令的内容。

    传递变量

    可以在命令行里设置Makefile的变量值,对如下的makefile

    TARGET=test
    create:
        mkdir -p ${TARGET}
    

    可以通过如下的命令修改TARGET的值:

    make create TARGET=another
    

    .PHONY伪目标

    尽可能使用.PHONY标示所有的伪目标,以避免潜在的问题。

    常见的一例问题如下:

    debug:
        mkdir -p debug
        cd debug && make -f ../Makefile
    

    使用make debug命令时可能会提示Nothing to be done for debug,即debug目标已是最新。然而debug是伪目标,理论上每次执行都应该运行才对。问题出在debug目标的名称和本地的debug文件夹同名,使用.PHONY标识debug为伪目标即可解决此问题。

    .PHONY: debug
    

    不要滥用空白字符

    1. objects = a.o b.o # object files,这里${objects}变量的值是`a.o b.o '(包含后面的一个空格)。
    2. str = ${subst abc, 123,abcde},这里${str}变量的值是` 123de'(包含开头的一个空格)。
    3. str = ${subst abc ,123,abcde},这里${str}变量的值还是abcde,因为要替换的子串abc(包含最后的空格)没有找到。

    例子

    假设有以下的场景,在src目录下有许多css文件,我们需要用yui-compressor将其压缩并输出到output目录,压缩后css的文件名不变,文件名后缀由.css改为.min.css,可以如下定义makefile

    # 查找所有的css源文件
    CSS_SOURCE_FILES = ${wildcard src/*.css}
    # 构建目标名
    CSS_OUTPUT_FILES = ${subst src/,output/,${patsubst %.css,%.min.css,${CSS_SOURCE_FILES}}}
    
    all: ${CSS_OUTPUT_FILES}
    
    ${CSS_OUTPUT_FILES}: output/%.min.css: src/%.css
        @[ -d output ] || mkdir -p output
        yui-compressor -o $@ $<
    
    clean:
        rm -rf output
    
    .PHONY: all clean
    

    阅读资料

    脚注

    1.  

      GNU Make Manual: The Function wildcard,引用于2014-05-12。 

  • 相关阅读:
    基于session做的权限控制
    spring有关jar包的作用
    Failed to apply plugin [id 'com.android.application'] 和 Could not find com.android.tools.build:gradle:2.XX的最正确的解决方法
    Android Handler机制(四)---Handler源码解析
    System.currentTimeMillis()与SystemClock.uptimeMillis()
    【转】博客美化(6)为你的博文自动添加目录
    Android Handler机制(三)----Looper源码解析
    Android Handler机制(二)---MessageQueue源码解析
    Android Handler机制(一)---Message源码分析
    关于Android Force Close 出现的原因 以及解决方法
  • 原文地址:https://www.cnblogs.com/zengkefu/p/5618047.html
Copyright © 2011-2022 走看看