Makefile基本使用规则
编译&链接
- 一般来说,无论是C、C++、还是pas,首先要把源文件编译成中间代码文件,在Windows下也就是 .obj 文件,linux下是 .o 文件,即 Object File,这个动作叫做编译(compile)。
- 然后再把大量的Object File合成执行文件,这个动作叫作链接(link)。
1. Makefile文件名
- 一般情况下,可以使用makefile和Makefile这两种文件名来写makefile;
- 你还可以使用别的文件名来书写Makefile,比如:“Make.Linux”,“Make.Solaris”,“Make.AIX”等,如果要指定特定的Makefile,你可以使用make的“-f”和“–file”参数,如:make -f Make.Linux或make --file Make.AIX。
2. 变量赋值=,:=,?=,+=的区别
- = 是最基本的赋值,make会将整个makefile展开后,再决定变量的值。也就是说,变量的值将会是整个makefile中最后被指定的值。(会覆盖);
- := 是覆盖之前的值(变量的值取决于它在makefile中的位置);
- ?=是如果没有被赋值过就赋予等号后面的值,如果命令行指定值则使用命令行的值;
- += 是添加等号后面的值,常用于添加可选项options。
3. "$"使用:调用变量
- 可以用$来调用变量
- 若使用真实的“$”字符,那么你需要用“$$”来表示。
4. 命令前的“-”,以include为例
- 使用“include FILENAMES…”,make程序处理时,如果“FILENAMES”列表中的任何一个文件不能正常读取而且不存在一个创建此文件的规则时make程序将会提示错误并退出。
- 使用“-include FILENAMES…”的情况是,当所包含的文件不存在或者不存在一个规则去创建它,make程序会继续执行,只有真正由于不能正确完成终极目标的重建时(某些必需的目标无法在当前已读取的makefile文件内容中找到正确的重建规则),才会提示致命错误并退出。
5. include filename:include可包含多个其他使用makefile规则的文件
- filename可以是当前操作系统Shell的文件模式(可以保含路径和通配符)
- 在include前面可以有一些空字符,但是绝不能是[Tab]键开始。
6. Tab键的空位
- 在Makefile中的命令,必须要以[Tab]键开始,所以target后面的命令必须是一个tab键的空位。
7. 特殊符号:$@,$^, $< , $?, $%,$+,$
-
$@ 表示目标文件
-
$^ 表示所有的依赖文件
-
$< 表示第一个依赖文件
-
$? 表示比目标还要新的依赖文件列表
-
$% 仅当目标是函数库文件中,表示规则中的目标成员名。例如,如果一个目标是“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所不能识别的,那么“$*”就是空值。
8. VPATH使用
功能:指定搜索目录
示例:VPATH = src:…/headers
上面示例定义指定的两个目录,“src”和“…/headers”,make会按照这个顺序进行搜索。目录由“冒号”分隔。(当前目录永远是最高优先搜索的地方)
9. @echo和echo的区别
功能:都是在终端下打印相关信息,@echo可以不打印关于echo这一行的信息。
示例:Makefile中的@echo会打印以下内容,而echo只打印第二行。
echo a b c
a b c
10.使用".PHONY"指明target
-
用法:
all: mkdir hellos .PHONY:all
-
功能:如果你的target名和文件名重复,make命令在执行时会不知道到底target指向什么,所以为了避免冲突,一般情况下makefile中的target都会用,PHONY来指明target就在makefile中。
11. Makefile中的命令包define…endef
-
命令包define…endef有点像函数, 将连续的相同的命令合成一条, 减少 Makefile 中的代码量, 便于以后维护.
-
语法:由关键字、标签以及命令组成。
define <command-name> command ... endef
-
实例:
define run-hello-makefile @echo -n "Hello" # -n选项,不输出换行 @echo " Makefile!" @echo "这里可以执行多条 Shell 命令!" endef all: $(run-hello-makefile) # bash 中运行make $ make Hello Makefile! 这里可以执行多条 Shell 命令!
12. Makefile中使用条件判断ifeq,ifneq,ifdef和ifndef
- 使用条件判断,可以让make根据运行时的不同情况选择不同的执行分支。条件表达式可以是比较变量的值,或是比较变量和常量的值。
PS: make命令参数使用
-
“-n”或“–just-print”,只是显示命令,但不会执行命令,这个功能很有利于我们调试我们的Makefile,看看我们书写的命令是执行起来是什么样子的或是什么顺序的。
-
“-s”或“–slient”是全面禁止命令的显示。一个全局的办法是,给make加上“-i”或是“–ignore-errors”参数,那么,Makefile中所有命令都会忽略错误。而如果一个规则是以“.IGNORE”作为目标的,那么这个规则中的所有命令将会忽略错误。这些是不同级别的防止命令出错的方法,你可以根据你的不同喜欢设置。
-
“-k”或是“–keep-going”,这个参数的意思是,如果某规则中的命令出错了,那么就终目该规则的执行,但继续执行其它规则。