makefile
交叉编译
- 交叉编译器:arm-linux-gnueabihf
arm:编译arm架构的代码
linux:运行在Linux环境下
gnueabihf:嵌入式二进制接口 - 交叉编译器安装位置
/usr/local/arm - 修改环境变量
1)打开profie:sudo vim /etc/profie
2) 最后一行添加
export PATH=$PATH:/usr/local/arm/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf/bin - 安装库
sudo apt-get install lsb-core lib32stdc++6
编译链接
- 编译:源文件 -> 目标文件( .c .h -> .o)
编译器只关心语法是否正确,只要函数与变量声明正确就可以生成目标文件。编译时,不关心函数是否有具体实现。 - 链接:目标文件 -> 可执行文件(.o -> .bin)
链接器主要链接函数与全局变量,连接器并不关心源文件的位置,只管函数的中间目标文件,因此可以将多个中间目标文件整合成一个组合,该组合为库文件(.a)。
在链接时,链接器回去找函数的具体实现。
makefile简介
- make作用
当工程中有多个源文件时,分别编译工作量大,容易出错。 - make编译规则
1)工程没有被编译时,编译链接所有源文件
2)有.c文件被修改时,编译被修改过的文件,并链接目标程序
3)有.h文件被修改时,编译引用这几个头文件的c文件,并链接目标程序
语法规则
核心规则
目标:依赖文件集合······
命令1
命令2
······
makefile变量
- 变量名引用方法:$(变量名)
- 赋值符
2.1 “=”
在使用“=”给变量赋值的时候,不一定要用已经定义好的值,也可以使用后面定义的值。
示例代码:
name = qaz
curname = $(name)
name = wsx
print:
@echo curname:$(curname)
执行结果:
user@user:~/桌面/makefile_test$ make print
curname:wsx
print中不加‘@’的执行结果:
user@user:~/桌面/makefile_test$ make print
echo curname:wsx
curname:wsx
2.2 “:=”
:= 不会使用后面定义的变量,只是用前面定义好的
示例代码:
name := qaz
curname = $(name)
name = wsx
print:
@echo curname:$(curname)
执行结果:
user@user:~/桌面/makefile_test$ make print
curname:qaz
2.3 “?=”
如果变量前面没有被赋值,则给变量赋值,如果前面已经赋值过了,则使用前面的值。
示例代码:
name = qaz
name ?= wsx
curname := $(name)
print:
@echo curname:$(curname)
执行结果:
user@user:~/桌面/makefile_test$ make print
curname:qaz
2.4 “+=”
变量追加
objects = main.o
objects += input.o
makefile 模式规则
目标中的“%”表示对文件名的匹配,表示任意长度的非空字符串。当“%”出现在目标中的时候,目标中“%”所代表的的值决定了依赖中的“%”值。
使用方法:
%.o : %.c
命令
自动化变量
- $@:目标集合
- $<:①依赖文件集合中的第一个
②依赖文件以“%”定义时,表示符合模式的一系列文件集合 - $^:所有依赖文件集合,依赖集合中的文件使用空格分开,如果依赖文件中有重复文件,则去除重复文件
- $+:和$^类似,不同点为 $+不去除重复文件
- $?:所有比目标新的依赖目标集合,用空格分开
- $*:目标模式中“%”及其之前的部分
如果目标是test/a.test.c,目标模式为a.%.c,则 $*就是test/a.test - $%:目标是函数库的时候表示规则中的目标成员名,目标不是函数库时,其值为空
伪目标
伪目标并不是一个文件,只是一个标签,因此make无法生成它的依赖关系和决定它是否要执行。只有通过显示的指明这个“目标”才能让其生效。伪目标名不能和文件名重名,为了避免和文件名重名这种情况,可以显示的指明一个目标是伪目标,
显示声明伪目标用:.PHONY
例如:. PHONY : clean
条件编译
Makefile函数使用
Makefile支持使用已定义好的函数,不支持使用自定义的函数。函数使用方法如下:
$( 函数名 参数集合 )
或者:
${ 函数名 参数集合 }
参数集合是函数的多个参数,参数之间使用逗号“,”隔开。
1 subst函数
- 功能:字符串替换
- 调用形式
$(subst <from>, <to>, <text>)
将字符串<text>中的<from>内容替换为<to>,函数返回被替换后的字符串
2 patsubst函数
- 功能:模式字符串替换
- 调用形式
$(patsubst <pattern>, <replacement>, <text>)
查找字符串 中的单词是否符合模式,如果匹配就用来替换掉,<pattern>可以使用通配符“%”,函数返回值是替换后的字符串。如果<replacement>中也包含“%”,那么中的“%”将是<pattern>中的那个“%”所代表的字符串。
dir函数
- 功能:获取目录
- 使用方法:
$(dir <names···>)
此函数用于从文件名序列中提取出目录部分,返回值是文件的目录部分
3. 示例
path = $(dir </src/a.c>)
提取文件"/src/a.c" 的目录部分,则path的值为/src
notdir函数
- 功能:去除文件中的目录部分,提取文件名
- 使用方法:
$(notdir <names···>)
- 示例
file_name = $(notdir </src/a.c>)
提取文件“/src/a.c”中的非目录部分,则file_name的值为a.c
foreach函数
- 功能:循环
- 使用方法:
$(foreach <var>,<list>,<text>)
此函数的意思是把参数<list>中的单词逐一取出来放到参数中,然后再执行<text>所包含的表达式。每次<text>都会返回一个字符串,循环过程中,<text>中所包含的每个字符串会以空格隔开,最后当整个循环结束时,<text>所返回的每个字符串所组成的整个字符串为foreach函数的返回值
3. 示例:
wildcard函数
- 功能:使用通配符查找
- 使用方法:
$(wildcard PATTERN···)
- 示例
$(wildcard *.c)
获取当前目录下得所有.c文件