Makefile 笔记

makefile文件

转自//

https://seisman.github.io/how-to-write-makefile/introduction.html#

:= 前面的变量不能使用后面的变量,只能使用前面已定义好了的变量。

+= 操作符给变量追加值

?= ,先看示例:

FOO ?= bar

其含义是,如果FOO没有被定义过,那么变量FOO的值就是“bar”,如果FOO先前被定义过,那么这条语将 什么也不做.

多行变量

define two-lines
echo foo
echo $(bar)
endef

替换变量中的共有的部分,其格式是 $(var:a=b) 或是 ${var:a=b} ,其意思是, 把变量“var”中所有以“a”字串“结尾”的“a”替换成“b”字串。

使用函数

$(subst <from>,<to>,<text>)

将text中的from替换成to

$(patsubst <pattern>,<replacement>,<text>)

将text中的pattern模式的替换成replacement

例子:$(patsubst %.o,%.c, a.c b.c) >a.o b.o

$(strip <string>)

将string前后的空格删除

findstring <find>, <in>

将in 中的find返回

filter <pattern...>,<test>

将test中的pattern模式过滤出来。可以同时过滤多个模式的字符穿。

filterout与filter作用相反,将不符合模式的字符串过滤出来

sort <list>

将list里面的字符串序列按asc排序输出

Word <n>,<test>

将test里的第n个单词返回。如果n大于test单词个数返回null

worldlist <start>,<end>,<test>

将test从start开始到end的函数返回

words <test>

统计test中的单词个数

firstWord <test>

返回test中的第一个单词

文件操作函数

dir <name ...>

将name中的目录部分返回

notdir <name ..>

将文件名返回

suffix <names ...>

将nsuffixames中所有的文件的后缀返回回来。形如.c .c .o .s 如果所有文件都没有后缀,就返回空

basename <names ..>

与suffix相反,返回删除后缀名的字符串

addsuffix <suffix>,<names ...>

给names 添加后缀名

addprefix <prefix>,<names ...>

给names里的每一项添加前缀

join <list1>,<list2>

逐个链接字符串。aaa bbb ,111 222 > aaa111 bbb222.个数不匹配项都添加到末尾。

foreach <var>,<list>,<test>

例子 names := a b c d

files := $(foreach n,$names,$(n).o)

将names里的每一个复制n,将$(n).o拼接成一个新的字符串返回给files

call <expression>,<parm1>,<param2>.....//自定义函数

expression中1,2...与 <parm1>,<param2>.....对应传参数,并返回expression返回值

shell

指明 后面接的是一条shell 命令

控制make 运行的函数

error

warning

make的运行

make的退出码

0 表示成功执行

1 错误

2 -q选项

make指定文件

make -f filename

make指定目标

例如 make clean 就只会执行 clean 伪目标

make all

make install //将编译好的目标文件拷贝到安装目录

make检查规则

-n 将 make执行序列的命令 打印出来。不执行命令 用于调试

-t 将目标的生成时间更新一下。

-q ???

-w <filename>查看filename文件相关的编译情况。 结合-n

make的参数

-b ,-m 忽略兼容性

-b 所有的目标都要重新编译。 相当于 执行了make clean

-c <dir> ,--directory <dir>指定读取makefile 的目录

-debug [ options] -a -b -v -i -j -m 输出调试信息

-e 使用同名环境变量的值 ,放弃makefile中的同名变量

-f 指定makefile

-h  获取help

-i  忽略错误

-I 指定头文件包含目录

-j 没理解

-k 如果一个 目标出错,相关依赖 放弃。继续编译其他的。可以一次性暴露更多编译问题,提高工作效率

-l

-n 见上文

-o <**.o> 不更新*.o

-p 输出所有的makefile中的数据

-q 检查目标是否需要更新。 0 需要。2 不需要更新

-r 不适用隐含规则

-s 将所有执行输出信息 导向/dev/null

-v  查看make 版本信息

隐含规则

1.*.o 的依赖自动推导为 *.c

$(cc) -c $(CPPFLAGS) $(CFLAGS)

2.链接OBJ文件的隐含规则

x : y.o z.o

> cc -c x.c -o x.o

>cc -c y.c -o y.o

>cc -c z.c -o z.o

>cc x.o y.o z.o -o x

命令变量

  • AR : 函数库打包程序。默认命令是 ar
  • AS : 汇编语言编译程序。默认命令是 as
  • CC : C语言编译程序。默认命令是 cc
  • CXX : C++语言编译程序。默认命令是 g++
  • CO : 从 RCS文件中扩展文件程序。默认命令是 co
  • CPP : C程序的预处理器(输出是标准输出设备)。默认命令是 $(CC) –E
  • FC : Fortran 和 Ratfor 的编译器和预处理程序。默认命令是 f77
  • GET : 从SCCS文件中扩展文件的程序。默认命令是 get
  • LEX : Lex方法分析器程序(针对于C或Ratfor)。默认命令是 lex
  • PC : Pascal语言编译程序。默认命令是 pc
  • YACC : Yacc文法分析器(针对于C程序)。默认命令是 yacc
  • YACCR : Yacc文法分析器(针对于Ratfor程序)。默认命令是 yacc –r
  • MAKEINFO : 转换Texinfo源文件(.texi)到Info文件程序。默认命令是 makeinfo
  • TEX : 从TeX源文件创建TeX DVI文件的程序。默认命令是 tex
  • TEXI2DVI : 从Texinfo源文件创建军TeX DVI 文件的程序。默认命令是 texi2dvi
  • WEAVE : 转换Web到TeX的程序。默认命令是 weave
  • CWEAVE : 转换C Web 到 TeX的程序。默认命令是 cweave
  • TANGLE : 转换Web到Pascal语言的程序。默认命令是 tangle
  • CTANGLE : 转换C Web 到 C。默认命令是 ctangle
  • RM : 删除文件命令。默认命令是 rm –f

 

参数变量

  • ARFLAGS : 函数库打包程序AR命令的参数。默认值是 rv
  • ASFLAGS : 汇编语言编译器参数。(当明显地调用 .s.S 文件时)
  • CFLAGS : C语言编译器参数。
  • CXXFLAGS : C++语言编译器参数。
  • COFLAGS : RCS命令参数。
  • CPPFLAGS : C预处理器参数。( C 和 Fortran 编译器也会用到)。
  • FFLAGS : Fortran语言编译器参数。
  • GFLAGS : SCCS “get”程序参数。
  • LDFLAGS : 链接器参数。(如: ld
  • LFLAGS : Lex文法分析器参数。
  • PFLAGS : Pascal语言编译器参数。
  • RFLAGS : Ratfor 程序的Fortran 编译器参数。
  • YFLAGS : Yacc文法分析器参数。

定义模式规则

你可以使用模式规则来定义一个隐含规则。一个模式规则就好像一个一般的规则,只是在规则中,目标的定义 需要有 % 字符。 % 的意思是表示一个或多个任意字符。在依赖目标中同样可以使用 % , 只是依赖目标中的 % 的取值,取决于其目标。

模式规则示例

下面这个例子表示了,把所有的 .c 文件都编译成 .o 文件.

%.o : %.c
    $(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@

其中, $@ 表示所有的目标的挨个值, $< 表示了所有依赖目标的挨个值。这些奇怪的变量我们 叫“自动化变量”,后面会详细讲述。

自动化变量

  • $@ : 表示规则中的目标文件集。在模式规则中,如果有多个目标,那么, $@ 就是匹配于 目标中模式定义的集合。
  • $% : 仅当目标是函数库文件中,表示规则中的目标成员名。例如,如果一个目标是 foo.a(bar.o) , 那么, $% 就是 bar.o$@ 就是 foo.a 。如果目标不是函数库文件 (Unix下是 .a ,Windows下是 .lib ),那么,其值为空。
  • $< : 依赖目标中的第一个目标名字。如果依赖目标是以模式(即 % )定义的,那么 $< 将是符合模式的一系列的文件集。注意,其是一个一个取出来的。
  • $? : 所有比目标新的依赖目标的集合。以空格分隔。
  • $^ : 所有的依赖目标的集合。以空格分隔。如果在依赖目标中有多个重复的,那个这个变量会去除 重复的依赖目标,只保留一份。
  • $+ : 这个变量很像 $^ ,也是所有依赖目标的集合。只是它不去除重复的依赖目标。
  • $* : 这个变量表示目标模式中 % 及其之前的部分。如果目标是 dir/a.foo.b ,并且 目标的模式是 a.%.b ,那么, $* 的值就是 dir/a.foo 。这个变量对于构造有关联的 文件名是比较有较。如果目标中没有模式的定义,那么 $* 也就不能被推导出,但是,如果目标文件的 后缀是make所识别的,那么 $* 就是除了后缀的那一部分。例如:如果目标是 foo.c ,因为 .c 是make所能识别的后缀名,所以, $* 的值就是 foo 。这个特性是GNU make的, 很有可能不兼容于其它版本的make,所以,你应该尽量避免使用 $* ,除非是在隐含规则或是静态 模式中。如果目标中的后缀是make所不能识别的,那么 $* 就是空值。
  • 当你希望只对更新过的依赖文件进行操作时, $? 在显式规则中很有用,例如,假设有一个函数库文件 叫 lib ,其由其它几个object文件更新。那么把object文件打包的比较有效率的Makefile规则是:

    lib : foo.o bar.o lose.o win.o
        ar r lib $?
    

    在上述所列出来的自动量变量中。四个变量( $@$<$%$* )在扩展时 只会有一个文件,而另三个的值是一个文件列表。这七个自动化变量还可以取得文件的目录名或是在当前 目录下的符合模式的文件名,只需要搭配上 DF 字样。这是GNU make中老版本的特性, 在新版本中,我们使用函数 dirnotdir 就可以做到了。 D 的含义就是Directory, 就是目录, F 的含义就是File,就是文件。

    下面是对于上面的七个变量分别加上 D 或是 F 的含义:

    $(@D)

    表示 $@ 的目录部分(不以斜杠作为结尾),如果 $@ 值是 dir/foo.o ,那么 $(@D) 就是 dir ,而如果 $@ 中没有包含斜杠的话,其值就是 . (当前目录)。

    $(@F)

    表示 $@ 的文件部分,如果 $@ 值是 dir/foo.o ,那么 $(@F) 就是 foo.o$(@F) 相当于函数 $(notdir $@)

    $(*D), $(*F)

    和上面所述的同理,也是取文件的目录部分和文件部分。对于上面的那个例子, $(*D) 返回 dir , 而 $(*F) 返回 foo

    $(%D), $(%F)

    分别表示了函数包文件成员的目录部分和文件部分。这对于形同 archive(member) 形式的目标中的 member 中包含了不同的目录很有用。

    $(<D), $(<F)

    分别表示依赖文件的目录部分和文件部分。

    $(^D), $(^F)

    分别表示所有依赖文件的目录部分和文件部分。(无相同的)

    $(+D), $(+F)

    分别表示所有依赖文件的目录部分和文件部分。(可以有相同的)

    $(?D), $(?F)

    分别表示被更新的依赖文件的目录部分和文件部分。

    最后想提醒一下的是,对于 $< ,为了避免产生不必要的麻烦,我们最好给 $ 后面的那个特定 字符都加上圆括号,比如, $(<) 就要比 $< 要好一些。

    还得要注意的是,这些变量只使用在规则的命令中,而且一般都是“显式规则”和“静态模式规则” (参见前面“书写规则”一章)。其在隐含规则中并没有意义。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值