跟我一起学Makefile读书笔记

一   .PHONY: 伪目标 
二  % 
三.静态模式
    目标:目标模式:依赖模式
    $< 表示依赖目标集 $@ 表示目标集
四. @命令 显示命令
 make [-n|--just-print] 只显示命令,调试makefile
    -s --silent 全面禁止命令显示
五. shell 命令用; 隔开才起作用
    "-" 忽略命令出错 如-rm -f *.o
    make -i --ignore-errors 全局忽略出错
    以 .IGNORE 为目标的
    -k --keep-going 若规则出错,终止该规则,继续其他规则
六.嵌套执行
    export 变量
    -w 参数显示目录信息
七.定义命令包
    define 名字
    (Tab)   command
    endef
八.变量
    变量的命名字可以包含字符、数字,下划线(可以是数字开头),但不应该含有“:”,“#”,“=”或是空字
    符(空格、回车等)
    变量的变量 最好用":="定义, 因为"="可以使用后面定义的变量 "+="追加变量值 "?="未定义变量就赋值
    使用 #的方法来定义一个空格变量
    变量替换: ${var:a=b}
    把变量的值再当变量 可以用在操作符的左右两边 
九.override 
    如果有变量是通常 make 的命令行参数设置的,那么 Makefile 中对这个变量的赋值会被忽略。如果
    你想在 Makefile 中设置这类参数的值,那么,你可以使用“override”指示符。
十.目标变量

十一.函数
    ${<function> <arguments>} 参数间以逗号“,”分隔,而函数名和参数之间以“空格”分隔
    1) subst
        $(subst <from>,<to>,<text>) 把字串<text>中的<from>字符串替换成<to>。
    2) patsubst
        $(patsubst <pattern>,<replacement>,<text>) 
        $(patsubst %.c,%.o,x.c.c bar.c)
        把字串“x.c.c bar.c”符合模式[%.c]的单词替换成[%.o],返回结果是“x.c.o bar.o”
    3) strip
       $(strip <string>) 去掉<string>字串中开头和结尾的空字符。
    4) findstring
       $(findstring <find>,<in>) 功能:在字串<in>中查找<find>字串。
                     返回:如果找到,那么返回<find>,否则返回空字符串。
    5) filter
       $(filter <pattern...>,<text>) 以<pattern>模式过滤<text>字符串中的单词,
                    保留符合模式<pattern>的单词。可以有多个模式。
    6) filter-out
       $(filter-out <pattern...>,<text>) 以<pattern>模式过滤<text>字符串中的单词,
                    去除符合模式<pattern>的单词。可以有多个模式
    7) sort
       $(sort <list>) 给字符串<list>中的单词排序(升序)。备注:sort 函数会去掉<list>中相同的单词。
    8) word
       $(word <n>,<text>) 取字符串<text>中第<n>个单词。(从一开始)
    9) wordlist
       $(wordlist <s>,<e>,<text>) 从字符串<text>中取从<s>开始到<e>的单词串。<s>和<e>是一个数字。
    10) words
       $(words <text>) 统计<text>中字符串中的单词个数。备注:如果我们要取<text>中最后的一个单
            词,我们可以这样:$(word $(words <text>),<text>)。
    11) firstword
       $(firstword <text>) 取字符串<text>中的第一个单词。
    override CFLAGS += $(patsubst %,-I%,$(subst :, ,$(VPATH)))
    如 果 我 们 的 “$(VPATH)” 值 是 “src:../headers” , 那 么 
    “$(patsubst%,-I%,$(subst :, ,$(VPATH)))”将返回“-Isrc -I../headers”,
    这正是 cc 或 gcc 搜索头文件路径的参数。
    文件名操作函数
    1. dir
       $(dir <names...>) 从文件名序列<names>中取出目录部分。
    2. notdir
       $(notdir <names...>) 从文件名序列<names>中取出非目录部分。就是文件名
    3. suffix
       $(suffix <names...>) 从文件名序列<names>中取出各个文件名的后缀。
    4. basename
       $(basename <names...>) 从文件名序列<names>中取出各个文件名的后缀。
    5. addsuffix
       $(addsuffix <suffix>,<names...>) 把后缀<suffix>加到<names>中的每个单词后面。
    6. addprefix
       $(addprefix <prefix>,<names...>) 把前缀<prefix>加到<names>中的每个单词后面。
    7. join
       $(join <list1>,<list2>) 把<list2>中的单词对应地加到<list1>的单词后面。如果<list1>的单
       词个数要比<list2>的多,那么,<list1>中的多出来的单词将保持原样。如果<list2>的单个数要比
       <list1>多,那么,<list2>多出来的单词将被复制到<list2>中。
    8. foreach 函数
       $(foreach <var>,<list>,<text>) 
       names := a b c d
       files := $(foreach n,$(names),$(n).o)
       上面的例子中,$(name)中的单词会被挨个取出,并存到变量“n”中,“$(n).o”每次
       根据“$(n)”计算出一个值,这些值以空格分隔,最后作为 foreach 函数的返回,所以,
       $(files)的值是“a.o b.o c.o d.o”。
    9. if
       $(if <condition>,<then-part>) $(if <condition>,<then-part>,<else-part>)
       如果<condition>为真(非空字符串),那个<then-part>会是整个函数的返回值,如果<condition>为
       假(空字符串),那么<else-part>会是整个函数的返回值,此时如果<else-part>没有被定义,那么,
       整个函数返回空字串。
    10. call
      $(call <expression>,<parm1>,<parm2>,<parm3>...) 
      如:
        reverse = $(2) $(1)
        foo = $(call reverse,a,b) 此时的 foo 的值就是“b a”。
    11. origin
       $(origin <variable>) 
       返回值:undefined, default, file, command line, override, automatic
    12. shell
    13. error and warning
十二.make 的运行
    1. make 的退出码
     0 - succeed
      1 - failed
      2 - make -q 且一些目标不需要更新
    2. make -f 指定makefile
    3. 指定目标
     MAKECMDGOALS  是命令行指定的目标
     all clean install print(list changed files) tar dist TAGS check/test 
    4. 检查规则
     -n --just-print 只打印命令
     -t --touch 更新目标文件的时间
     -q --question 若目标存在,什么也不输出,若不存在,打印错误信息
     -W <file> 可和-n参数一起使用,查看依赖文件的规则命令
    5.make 参数
     -b -m 忽略和其他版本的兼容性
     -B --always-make 重编译
     -C <dir> --directory=<dir> 指定读取makefile的目录
     --debug[=<option>] 输出make调试信息
        a   all,输出所有信息
        b   basic,简单信息
        v   verbose,在b选项之上,输出信息包括哪个makefile被解析等
        i   implicit,隐含规则
        j   jobs,命令的详细信息,如命令的PID,返回码等
        m   makefile,输出make读取makefile,更新makefile,执行makefile信息
      -d --debug=a
      -e --environment-overrides 指明环境变量的值覆盖makefile中定义的值
     -f <file> --file=<file> --makefile=<file>
      -h --help 显示帮助
     -i --ignore-errors 在执行是忽略所有错误
     -I <dir> --include-dir=<dir> 指定makefile的搜索目录,可多个
     -j [<jobsnum>] --jogs[=<jobsnum>] 指定同时运行的命令个数,若没有,则make 能运行多少就运行多少
     -k --keep-going 出错也不停止
     -l <load> 指定make运行的负载
     -o <file> --old-file=<file> --assume-old=<file>不重新生成指定的file
      -p --print-data-base 输出所有数据包括行号,文件名,调试makefile
      -r --no-builtin-rules 禁止make使用隐含规则
     -R --no-builtin-variabes 禁止make使用任何作用于变量上的隐含规则
     -s --silent --quiet 在命令运行是不输出命令输出
     -S --stop 取消-k选项的作用
     -w --print-directory 输出运行makefile之前和之后的信息,用于跟踪嵌套调用make
      --no-print-directory 禁止-w选项
十三.隐含规则
    1. C++ n.o 自动推导为n.cc 或n.C 最好用.cc
    2. 隐含规则使用的变量
     1) 命令相关的变量
        AR 函数库打包程序,ar
        AS 汇编编译,as
        CC C语言,cc
        CXX C++语言,g++
        CPP C程序的预处理器,$(CC) -E
        LEX Lex方法分析器程序,lex
        YACC Yacc文法分析器(     LEX Lex方法分析器程序,lex
        YACC Yacc文法分析器(C),yacc
        RM 删除文件命令,rm -f
      2) 命令参数相关的变量
        ARFLAGS AR的参数,默认为rv
        ASFLAGS AS
        CFLAGS
        CXXFLAGS 
        CPPFLAGS C预处理器参数
        LDFLAGS 链接器参数 ld
        LFLAGS YFLAGS
    3. 隐含规则链
     第一个不同是除非中间的目标不存在,才会引发中间规则。
     第二个不同的是,只要目标成功产生,那么,产生最终目标过程中,所产生的中间目标文件会被以“rm -f”删除。
     .INTERMEDIATE: 显示指定中间目标
     .SECONDARY: 阻止make自动删除中间目标
    4. 定义模式规则
     在目标定义中有"%"字符。"%"展开发生在变量和函数展开之后,发生在运行时
     目标中的模式的"%"决定了依赖目标中"%"的样子
    5. 自动化变量
     $@ 表示规则中的目标文件集。在模式规则中,如果有多个目标,那么,"$@"就是匹配于目标中模式定义的集合。
      $% 仅当目标是函数库文件时,表示规则中的目标成员名。
     $< 依赖目标中的第一个目标名字。如果依赖目标是以模式(即"%")定义的,
        那么"$<"将是符合模式的一系列的文件集。注意,其是一个一个取出来的。
      $? 所有比目标新的依赖目标的集合。以空格分隔。
      $^ 所有的依赖目标的集合。以空格分隔。如果在依赖目标中有多个重复的,
        那个这个变量会去除重复的依赖目标,只保留一份。
      $+ 这个变量很像"$^",也是所有依赖目标的集合。只是它不去除重复的依赖目标。
      $* 这个变量表示目标模式中"%"及其之前的部分。
      当你希望只对更新过的依赖文件进行操作时,"$?"在显式规则中很有用,例如,假设有
    一个函数库文件叫"lib",其由其它几个 object 文件更新。那么把 object 文件打包的比较
    有效率的 Makefile 规则是:
        lib : foo.o bar.o lose.o win.o
            ar r lib $?        
      $@$<$%$*)在扩展时只会有一个文件,另三个则是文件列表。D和F 函数dir和notdir
十四.make 跟新库函数文件
    1. archive(member)
        ar cr archive member
    2. make foo.a(bar.o) 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章