目录
自动进行编译的 软件,GNU make(工程管理器 make 在不同环境有很多版本分支,比如 Qt 下的 qmake, Windows 下的 nmake 等,下面提到的 make 指的是 Linux 下的 GNU make)就是这样 的一款软件
而 Makefile,是 make 的配置文件,用来配置运行 make 的时候的一些相关细节,
比如指定编译选项,指定编译环境等等。一般而言,一个工程项目不管是简单还是复杂,每一个源代码子目录都会有一个 Makefile 来管理,然后一般有个所谓的顶层 Makefile 来统一管理所有的子目录 Makefile。
makefile调用方式
make
gcc编译多文件例子
假设我们有一个工程,这个工程总共有4个源文件,姑且叫做 a.c、b.c 以及 x.c 和 y.c 吧,他们最终将会链接生成可执行文件 image:
用来帮我们“自动”执 行编译的工作,此时目标是 image,而其依赖则是四个.o 文件,而 且,这四个.o 文件本身也是目标,他们依赖于其对应的.c 文件
image:a.o b.o x.o y.o
gcc a.o b.o x.o y.o -o image
a.o:a.c
gcc a.c -o a.o -c
b.o:b.c
gcc b.c -o b.o -c
x.o:x.c
gcc x.c -o x.o -c
y.o:y.c
gcc y.c -o y.o -c
这个简单的 Makefile 文件总共有 11 行,5 套规则,其中第 1 行中的 image 是第 1 个目标,冒号后面是这个目标的依赖列表(四个.o 可重定位文件)。第 2 行行首是一个制 表符,后面紧跟着一句 Shell 命令。 下面从第 4 行到第 11 行,也都是这样的目标-依赖对,及其相关的 Shell 命令。但是 这里必须注意一点:虽然这个 Makefile 总共出现了 5 个目标,但是第一个规则的目标(即 image)被称之为终极目标,终极目标指的是当你执行 make 的时候,默认生成的那个文 件。注意:如果第一个规则有多个目标,则只有第一个才是终极目标。另外,以圆点.开头 的目标不在此讨论范围内。
变量详解
跟Shell脚本非常类似,在Makefile中也会使用“弱类型”变量(相对于C语言这种强 类型语言而言),在Makefile中变量就是一个名字(像是C语言中的宏),代表一个文本字 符串(变量的值)。在Makefile的目标、依赖、命令中引用一个变量的地方,变量会被它 的值所取代(与C语言中宏引用的方式相同,因此其他版本的make也把变量称之为“宏”)。
特点
- 变量和函数的展开(除规则的命令行以外),是在make读取Makefile文件时进行 的,这里的变量包括了使用“=”定义和使用指示符“define”定义的变量。
- 变量可以用来代表一个文件名列表、编译选项列表、程序运行的选项参数列表、搜 索源文件的目录列表、编译输出的目录列表和所有我们能够想到的事物。
- 变量名不能包括“:”、“#”、“=”、前置空白和尾空白的任何字符串。需要注意的是, 尽管在GNU make中没有对变量的命名有其它的限制,但定义一个包含除字母、数字和下 划线以外的变量的做法也是不可取的,因为除字母、数字和下划线以外的其它字符可能会在 以后的make版本中被赋予特殊含义,并且这样命名的变量对于一些Shell来说不能作为环 境变量使用。
- 变量名是大小写敏感的。变量“foo”、“Foo”和“FOO”指的是三个不同的变量。 Makefile传统做法是变量名是全采用大写的方式。推荐的做法是在对于内部定义的一般变 量(例如:目标文件列表objects)使用小写方式,而对于一些参数列表(例如:编译选项 CFLAGS)采用大写方式,这并不是要求的。但需要强调一点:对于一个工程,所有Makefile 中的变量命名应保持一种风格,否则会显得你是一个蹩脚的开发者(就像代码的变量命名风 格一样),随时有被鄙视的危险。
- 另外有一些变量名只包含了一个或者很少的几个特殊的字符(符号)。称它们为自 动化变量。像“<”、“@”、“?”、“*”、“@D”、“%F”、“^D”等等,后面会详述之。
- 变量的引用跟Shell脚本类似,使用美元符号和圆括号,比如有个变量叫A,那么对 他的引用则是$(A),有个自动化变量叫@,则对他的引用是$(@),有个系统变量是CC则 对其引用的格式是$(CC)。对于前面两个变量而言,他们都是单字符变量,因此对他们引用 的括号可以省略,写成$A和$@。
例子 自定义变量
A = apple
B = I love China
C = $(A) tree
继续上方编译多个.c
OBJ = a.o b.o x.o y.o
image:$(OBJ)
gcc $(OBJ) -o image
a.o:a.c
gcc a.c -o a.o -c
b.o:b.c
gcc b.c -o b.o -c
x.o:x.c
gcc x.c -o x.o -c
y.o:y.c
gcc y.c -o y.o -c
例子 系统预定义变量
CFLAGS、CC、MAKE、Shell 等等,这些变量已经有了系统预定义好的值,当然我们 可以根据需要重新给他们赋值,例如 CC 的默认值是 gcc,当我们需要使用 c 编译器的时候 可以直接使用他
OBJ = a.o b.o x.o y.o
image:$(OBJ)
$(CC) $(OBJ) -o image
a.o:a.c
$(CC) a.c -o a.o -c
b.o:b.c
$(CC) b.c -o b.o -c
x.o:x.c
$(CC) x.c -o x.o -c
y.o:y.c
$(CC) y.c -o y.o -c
如果是要编译arm,只需修改CC
CC = arm-Linux-gnu-gcc
例子 自动化变量
<、@、?、#等等,这些特殊的变量之所以称为自动化变量,是因为他们的值会“自 动地”发生变化