跟我一起学Makefile——重点总结

《跟我一起学Makefile》文章里,个人认为比较重要的知识点总结

  1. **反斜杠(\)**是换行符的意思。这样比较便于 Makefile 的易读

  2. make 会比较目标文件依赖文件的修改日期,如果 依赖文件的日期要比目标文件的日期要新,或者 依赖文件不存在的话,那么,make 就会执行后续定义的命令。

  3. 如果冒号后什么也没有,那么,make 就不会自动去找文件的依赖性,例如clean:,也就不会自动执行其后所定义的命令。但是如果一个文件在最开头,是例外,不管有没有依赖,都会被当成默认目标执行。(第一个目标文件就是默认文件)

  4. 为了 makefile 的易维护,在 makefile 中我们可以使用变量。makefile 的变量也就是一个字符串,可以理解成 C 语言中的宏。变量在声明时需要给予初值,而在使用时,需要给在变量名前加上“$”符号。如果你要使用真实的“$”字符,那么你需要用“$$”来表示。

  5. 定义伪目标更为稳健的做法是:

    .PHONY : clean
    clean :
    	-rm edit $(objects)
    

    .PHONY 意思表示 clean 是一个“伪目标”。不成文的规矩是——“clean 从来都是放在文件的最后”
    一个示例就是,如果你的 Makefile 需要一口气生成若干个可执行文件,但你只想简单地敲一个 make 完事,并且,所有的目标文件都写在一个 Makefile 中,那么你可以使用“伪目标”这个特性:(伪目标放在最前面,是默认目标,相当于指定了,所以也一定会执行)

    all : prog1 prog2 prog3
    .PHONY : all
    prog1 : prog1.o utils.o
    	cc -o prog1 prog1.o utils.o
    prog2 : prog2.o
    	cc -o prog2 prog2.o
    prog3 : prog3.o sort.o utils.o
    	cc -o prog3 prog3.o sort.o utils.o
    
  6. 注释是用“#”字符

  7. 在 Makefile 使用 include 关键字可以把别的Makefile 包含进来,include 的语法是:include <filename>,include绝不能是[Tab]键开始。include<filename>可以用一个或多个空格隔开

    include foo.make *.mk $(bar)
    等价于:
    include foo.make a.mk b.mk c.mk e.mk f.mk
    
  8. 规则包含两个部分,一个是依赖关系,一个是生成目标的方法。Makefile 中只应该有一个最终目标,第一条规则中的目标将被确立为最终的目标

  9. 如果我们的文件名中有通配符,如:“*”,那么可以用转义字符“\”,如“\*"来表示真实的“*”字符,而不是任意长度的字符串

  10. objects = *.o
    上面这个例子,表示了,通符同样可以用在变量中。 但[*.o]不会展开,objects的值就是“*.o”。Makefile 中的变量其实就是 C/C++中的宏。如果你要让通配符在变量中展开,也就是让 objects 的值是所有[.o]的文件名的集合,那么,你可以这样:objects := $(wildcard *.o)

  11. 当 make 需要去找寻文件的依赖关系时,你可以在文件前加上路径

  12. 静态模式

    <targets ...>: <target-pattern>: <prereq-patterns ...>
    <commands>
    

    $(objects): %.o: %.c 表示objects中的.o文件的依赖是.c   其中 .o文件是属于objects里面定义的

  13. make 会把其要执行的命令行在命令执行前输出到屏幕上。当我们用“@”字符在命令行前,那么,这个命令将不被 make 显示出来。如:@echo 正在编译 XXX 模块......
    当 make 执行时,会输出“正在编译 XXX 模块......”字串,但不会输出命令,如果没有“@”,那么,make 将输出:echo 正在编译 XXX 模块......正在编译 XXX 模块......

  14. make 参数“-n”,那么其只是显示命令,但不会执行命令。可以查看makefile有没有写错

  15. make 参数“-s”则是静默输出 。make -s 禁止显示命令,但是命令执行了,这样方便修改err和warning

  16. -d 相当于debug  -f 指定需要的makefile  -i忽略所有的错误 VPATH指定依赖文件路径  -I指定头文件所在的目录  -v输出make的版本

  17. 定义命令包(多行变量)。定义这种命令序列的语法以“define”开始,以“endef”结束,如:

    	define run-yacc
    		yacc $(firstword $^)
    		mv y.tab.c $@
    	endef
    

    可以这么使用

    foo.c : foo.y
    $(run-yacc)
    
  18. 注意=  :=   ?=  这三种等号的区别

  19. 如果我们要定义一个变量,其值是一个空格,那么我们可以这样来:

    nullstring :=
    space := $(nullstring)  # end of the line
    

    nullstring 是一个 Empty 变量,其中什么也没有,而我们的 space 的值是一个空格。先用一个 Empty 变量来标明变量的值开始了,而后面采用“#”注释符来表示变量定义的终止。如果直接用space := # 将不会有空格。必须前面要先从一个变量算起,再用#,才会有空格因此这里需要定义一个空变量。另外,dir := /foo/bar  # 只要#符号离末尾距离大于1(2345678等等),都只会空一个空格。

  20. 变量的高级用法:第一种是变量值的替换

    foo := a.o b.o c.o
    bar := $(foo:.o=.c)
    

    另外一种变量替换的技术是以“静态模式”(参见前面章节)定义的,如:

    foo := a.o b.o c.o
    bar := $(foo:%.o=%.c)
    

    第二种高级用法是——“把变量的值再当成变量”

    x = variable1
    variable2 := Hello
    y = $(subst 1,2,$(x))
    z = y
    a := $($($(z)))
    
    first_second = Hello
    a = first
    d
    all = $($a_$b)
    
  21. 追加变量值
    我们可以使用“+=”操作符给变量追加值,如:

    objects = main.o foo.o bar.o utils.o
    	objects += another.o
    
  22. 使用条件判断:ifeq ifneq ifdef ifndef
    ifeq格式:

    <conditional-directive>
    <text-if-true>
    else
    <text-if-false>
    endif
    

    <conditional-directive>这一行上,多余的空格是被允许的,但是不能以[Tab]键做
    为开始(不然就被认为是命令)。包括定义变量时,不能有tab,但是可以有空格,因为tab后代表命令

    示例:

    ifeq ($(CC),gcc)
    	libs=$(libs_for_gcc)
    else
    	libs=$(normal_libs)
    endif
    
    ifneq (<arg1>, <arg2>)
    

    ifdef格式:
    ifdef <variable-name>如果变量<variable-name>的值非空,那到表达式为真。否则,表达式为假。

    示例:

    foo =
    ifdef foo
    frobozz = yes
    else
    frobozz = no
    endif
    

    特别注意的是,make 是在读取 Makefile 时就计算条件表达式的值,并根据条件表达式
    的值来选择语句,所以,你最好不要把自动化变量(如“$@”等)放入条件表达式中

  23. 函数的调用语法
    函数调用,很像变量的使用,也是以“$”来标识的,其语法如下:

    $(<function> <arguments>)   
    

    <function>就是函数名,<arguments>是函数的参数,参数间以逗号“,”分隔,而函数名和参数之间以“空格”分隔

  24. 字符串处理函数 subst
    $(subst <from>,<to>,<text>)
    名称:字符串替换函数——subst。
    功能:把字串<text>中的<from>字符串替换成<to>。
    返回:函数返回被替换过后的字符串。
    $(subst ee,EE,feet on the street),
    把“feet on the street”中的“ee”替换成“EE”,返回结果是“fEEt on the strEEt”。

  25. 模式字符串替换函数——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”
    “$(objects:.o=.c)”和“$(patsubst %.o,%.c,$(objects))”是一样的。

  26. 取目录函数——dir。
    $(dir <names…>)
    功能:从文件名序列<names>中取出目录部分。目录部分是指最后一个反斜杠(“/”)之前
    的部分。如果没有反斜杠,那么返回“./”。
    返回:返回文件名序列<names>的目录部分。
    示例: $(dir src/foo.c hacks)返回值是“src/ ./”。

  27. 取文件函数——notdir。
    $(notdir <names…>)  .  
    功能:从文件名序列<names>中取出非目录部分。非目录部分是指最后一个反斜杠(“ /”)
    之后的部分。
    返回:返回文件名序列<names>的非目录部分。
    示例: $(notdir src/foo.c hacks)返回值是“foo.c hacks”。

  28. foreach 函数 用来做循环用的
    $(foreach <var>,<list>,<text>) 把参数<list>中的单词逐一取出放到参数<var>所指定的变量中,然后再执行<text>所包含的表达式
    <var>最好是一个变量名,<list>可以是一个表达式,而<text>中一般会使用<var>
    这个参数来依次枚举<list>中的单词。举个例子:

    names := a b c d
    files := $(foreach n,$(names),$(n).o)
    一般我们可以使用“$(wildcard *.c)”来获取工作目录下的所有的.c文件列表
    

    foreach 中的<var>参数是一个临时的局部变量,foreach 函数执行完后,参数
    <var>的变量将不在作用,其作用域只在 foreach 函数当中

  29. 函数 wildcard
    通配符“%”只能用在规则中,只有在规则中它才会展开,如果在变量定义和函数使用时,通配符不会自动展开,这个时候就要用到函数 wildcard

  30. 我们可以给 make 命令指定一个特殊名字的 Makefile。要使用 make 的“-f”参数。

    make –f hchen.mk
    
  31. 有一点需要注意的是,"%“的展开发生在变量和函数的展开之后,变量和函数的展开发
    生在 make 载入 Makefile 时,而模式规则中的”%"则发生在运行时。

  32. $@  规则中的目标集合

  33. $<  依赖文件集合的第一个文件,是符合规则的一系列依赖文件的集合

  34. $^  规则中所有的依赖文件集合

  35. gcc 命令的时候加上-o 来指定生成的可执行文件名字

  36. -c: 只编译不链接为可执行文件,编译器将输入的.c 文件编译为.o 的目标文件。
    -o: <输出文件名>用来指定编译结束以后的输出文件名,如果使用这个选项的话 GCC 默认编译出来的可执行文件名字为 a.out。
    -O: 对程序进行优化编译

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Makefile 在 Unix 上写程式的人大概都碰过 Makefile,尤其是用 C 来开发程式的 人。用 make 来开发和编译程式的确很方便,可是要写出一个 Makefile 就不简单了。偏偏介绍 Makefile 的文件不多,GNU Make 那份印出来要几 百页的文件,光看完 Overview 就快阵亡了,难怪许多人闻 Unix 色变。 本文将介绍如何利用 GNU Autoconf 及 Automake 这两套软体来协助我们 『自动』产生 Makefile 档,并且让开发出来的软体可以像 Apache, MySQL 和常见的 GNU 软体一样,只要会 ``./configure'', ``make'', ``make install'' 就可以把程式安装到系统中。如果您有心开发 Open Source 的软体,或只是想在 Unix 系统下写写程式。希望这份介绍文件能 帮助您轻松地进入 Unix Programming 的殿堂。 1. 简介 Makefile 基本上就是『目标』(target), 『关连』(dependencies) 和 『动作』三者所组成的一连串规则。而 make 就会根据 Makefile 的规则 来决定如何编译 (compile) 和连结 (link) 程式。实际上,make 可做的 不只是编译和连结程式,例如 FreeBSD 的 port collection 中, Makefile 还可以做到自动下载原始程式套件,解压缩 (extract) ,修补 (patch),设定,然後编译,安装至系统中。 Makefile 基本构造虽然简单,但是妥善运用这些规则就也可以变出许多不 同的花招。却也因此,许多刚开始习写 Makefile 时会感到没有规范可 循,每个人写出来的 Makefile 长得都不太一样,不知道从何下手,而且 常常会受限於自己的开发环境,只要环境变数不同或路径改一下,可能 Makefile 就得跟着修改。虽然有 GNU Makefile Conventions (GNU Makefile 惯例) 订出一些使用 GNU 程式设计时撰写 Makefile 的一些标 准和规范,但是内容很长而且很复杂, 并且经常做些调整,为了减轻程式 设计师维护 Makefile 的负担,因此有了 Automake。 程式设计师只需写一些预先定义好的巨集 (macro),交给 Automake 处理 後会产生一个可供 Autoconf 使用的 Makefile.in 档。再配合利用 Autoconf 产生的自动设定档 configure 即可产生一份符合 GNU Makefile 惯例的 Makeifle 了。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值