一、Makefile 的作用和意义
(1) 工程项目中 c 文件太多管理不方便,因此用 Makefile 来做项目管理,方便编译链接过程。
(2) uboot 和 linux kernel本质上都是 C 语言的项目,都由很多个文件组成,因此都需要通过 Makefile 来管理。所以要分析 uboot 必须对 Makefile 有所了解。
二、目标、依赖、命令
(1) 目标就是我们要去 make xxx 的那个 xxx,就是我们最终要生成的东西。
(2) 依赖是用来生成目录的原材料。
(3) 命令就是加工方法,所以 make xxx 的过程,其实就是使用命令将依赖加工成目标的过程。
三、通配符 % 和 Makefile 自动推导(规则)
(1) % 是 Makefile 中的通配符,代表一个或几个字母。 也就是说, %.o 就代表所有以 .o 为结尾的文件。
(2) 所谓自动推导,其实就是 Makefile 的规则。当 Makefile 需要某一个目标时,他会把这个目标去套规则说明,一旦套上了某个规则说明,则 Makefile 会试图寻找这个规则中的依赖,如果能找到则会执行这个规则用依赖生成目标。
四、Makefile 中定义和使用变量
(1) Makefile 中定义和使用变量,和 shell 脚本中非常相似。相似是说:都没有变量类型,直接定义使用,引用变量时用 $var。
五、伪目标(.PHONY)
(1) 伪目标,意思是这个目标本身不代表一个文件,执行这个目标不是为了得到某个文件或东西,而是单纯为了执行这个目标下面的命令。
(2) 伪目标一般都没有依赖,因为执行伪目标就是为了执行目标下面的命令。既然一定要执行命令了那就不必加依赖,因为不加依赖意思就是无条件执行。
(3) 伪目标可以直接写,不影响使用;但是有时候为了明确声明这个目标是伪目标,会在伪目标的前面用 .PHONY 来明确声明它是伪目标。
六、Makefile 的文件名
(1) Makefile 的文件名合法的一般有 2 个:Makefile 或者makefile。
七、Makfile 中引用其他 Makefile(include 指令)
(1) 有时候 Makefile 总体比较复杂,因此分成好几个 Makefile 来写。然后在主 Makefile 中引用其他的,用 include 指令来引用。引用的效果也是原地展开,和 C 语言中的头文件包含非常相似。
八、Mafile 补充学习1
1、Makefile 中的注释用
(1) Makefile中注释使用 #,和 shell 一样。
2、命令前面的 @ 用来静默执行
(1) 在 makefile 的命令行中前面的 @ 表示静默执行。
(2) Makefile 中默认情况下在执行一行命令前会先把这行命令给打印出来,然后再执行这行命令。
(3) 如果你不想看到命令本身,只想看到命令执行就静默执行即可。
root@ubuntu:/home/aston/workspace# cat Makefile
all:
echo hello world
root@ubuntu:/home/aston/workspace# make
echo hello world
hello world
root@ubuntu:/home/aston/workspace#
root@ubuntu:/home/aston/workspace#
root@ubuntu:/home/aston/workspace# vim Makefile
root@ubuntu:/home/aston/workspace# cat Makefile
all:
@echo hello world
root@ubuntu:/home/aston/workspace# make
hello world
root@ubuntu:/home/aston/workspace#
3、Makefile 中几种变量赋值运算符
(1) =
最简单的赋值
(2) :=
一般也是赋值
以上这两个大部分情况下效果是一样的,但是有时候不一样。
用 =
赋值的变量,在被解析时他的值取决于最后一次赋值时的值,所以你看变量引用的值时不能只往前面看,还要往后面看。
用 :=
来赋值的,则是就地直接解析,只用往前看即可。
root@ubuntu:/home/aston/workspace# cat Makefile
str1 = ABC
str2 := $(str1)123
str1 = DEF
all:
echo $(str1)
echo $(str2)
root@ubuntu:/home/aston/workspace# make
echo DEF
DEF
echo ABC123
ABC123
root@ubuntu:/home/aston/workspace#
(3) ?=
如果变量前面并没有赋值过则执行这条赋值,如果前面已经赋值过了则本行被忽略。(实验可以看出:所谓的没有赋值过,其实就是这个变量没有被定义过)
root@ubuntu:/home/aston/workspace# cat Makefile
str1 = ABC
str2 := $(str1)123
str1 = DEF
str3 = hello
str3 ?= world
all:
echo $(str1)
echo $(str2)
echo $(str3)
root@ubuntu:/home/aston/workspace# make
echo DEF
DEF
echo ABC123
ABC123
echo hello
hello
root@ubuntu:/home/aston/workspace# vim Makefile
root@ubuntu:/home/aston/workspace# cat Makefile
str1 = ABC
str2 := $(str1)123
str1 = DEF
str3 =
str3 ?= world
all:
echo $(str1)
echo $(str2)
echo $(str3)
root@ubuntu:/home/aston/workspace#
root@ubuntu:/home/aston/workspace# make
echo DEF
DEF
echo ABC123
ABC123
echo
root@ubuntu:/home/aston/workspace#
(4) +=
用来给一个已经赋值的变量接续赋值,意思就是把这次的值加到原来的值的后面,有点类似于 strcat。(在 shell makefile 等文件中,可以认为所有变量都是字符串,+=
就相当于给字符串 strcat 接续内容)(注意一个细节,+=
续接的内容和原来的内容之间会自动加一个空格隔开)
root@ubuntu:/home/aston/workspace# cat Makefile
str1 = ABC
str2 := $(str1)123
str1 = DEF
str3 = hello
str3 ?= world
str3 +="linux"
all:
echo $(str1)
echo $(str2)
echo $(str3)
root@ubuntu:/home/aston/workspace# make
echo DEF
DEF
echo ABC123
ABC123
echo hello "linux"
hello linux
root@ubuntu:/home/aston/workspace#
注意:Makefile 中并不要求赋值运算符两边一定要有空格或者无空格,这一点比 shell 的格式要求要松一些。
4、Makefile 的环境变量
(1) makefile 中用 export
导出的就是环境变量。一般情况下要求环境变量名用大写,普通变量名用小写。
(2) 环境变量和普通变量不同,可以这样理解:环境变量类似于整个工程中所有 Makefile 之间可以共享的全局变量,而普通变量只是当前本 Makefile 中使用的局部变量。所以要注意:定义了一个环境变量会影响到工程中别的 Makefile 文件,因此要小心。
(3) Makefile 中可能有一些环境变量,可能是 makefile 本身自己定义的内部的环境变量,或者是当前的执行环境提供的环境变量(譬如我们在 make 执行时给 makefile 传参。make CC=arm-linux-gcc,其实就是给当前 Makefile 传了一个环境变量 CC,值是 arm-linux-gcc。我们在make 时给 makefile 传的环境变量值优先级最高的,可以覆盖 makefile 中的赋值)。这就好像 C 语言中编译器预定义的宏 _LINE_ 、 _FUNCTION_ 等一样。
九、Makefile补充学习2
1、Makefile 中使用通配符
(1) *
若干个任意字符
(2) ?
1个任意字符
(3) []
将 [ ]
中的字符依次去和外面的结合匹配
还有个 %
,也是通配符,表示任意多个字符,和 *
很相似,但是 %
一般只用于规则描述中,又叫做规则通配符。
关于通配符,Makefile还有一些 wildcard 等比较复杂的通配符用法,具体参考《跟我一起学Makefile》即可。
2、Makefile 的自动变量
(1) 为什么使用自动变量。在有些情况下文件集合中文件非常多,描述的时候很麻烦,所以我们 Makefile 就用一些特殊的符号来替代符合某种条件的文件集,这就形成了自动变量。
(2) 自动变量的含义:预定义的特殊意义的符号。就类似于 C 语言编译器中预制的那些宏__FILE__一样。
(3) 常见自动变量:
$@
规则的目标文件名
$<
规则的依赖文件名
$^
依赖的文件集合
源自朱有鹏老师.