makefile

交叉编译

  1. 交叉编译器:arm-linux-gnueabihf
    arm:编译arm架构的代码
    linux:运行在Linux环境下
    gnueabihf:嵌入式二进制接口
  2. 交叉编译器安装位置
    /usr/local/arm
  3. 修改环境变量
    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
  4. 安装库
    sudo apt-get install lsb-core lib32stdc++6

编译链接

  1. 编译:源文件 -> 目标文件( .c .h -> .o)
    编译器只关心语法是否正确,只要函数与变量声明正确就可以生成目标文件。编译时,不关心函数是否有具体实现。
  2. 链接:目标文件 -> 可执行文件(.o -> .bin)
    链接器主要链接函数与全局变量,连接器并不关心源文件的位置,只管函数的中间目标文件,因此可以将多个中间目标文件整合成一个组合,该组合为库文件(.a)。
    在链接时,链接器回去找函数的具体实现。

makefile简介

  1. make作用
    当工程中有多个源文件时,分别编译工作量大,容易出错。
  2. make编译规则
    1)工程没有被编译时,编译链接所有源文件
    2)有.c文件被修改时,编译被修改过的文件,并链接目标程序
    3)有.h文件被修改时,编译引用这几个头文件的c文件,并链接目标程序

语法规则

核心规则

目标:依赖文件集合······
	命令1
	命令2
	······

makefile变量

  1. 变量名引用方法:$(变量名)
  2. 赋值符
    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函数

  1. 功能:字符串替换
  2. 调用形式
$(subst  <from>, <to>, <text>)

将字符串<text>中的<from>内容替换为<to>,函数返回被替换后的字符串

2 patsubst函数

  1. 功能:模式字符串替换
  2. 调用形式
$(patsubst   <pattern>, <replacement>, <text>)

查找字符串 中的单词是否符合模式,如果匹配就用来替换掉,<pattern>可以使用通配符“%”,函数返回值是替换后的字符串。如果<replacement>中也包含“%”,那么中的“%”将是<pattern>中的那个“%”所代表的字符串。

dir函数

  1. 功能:获取目录
  2. 使用方法:
$(dir <names···>)

此函数用于从文件名序列中提取出目录部分,返回值是文件的目录部分
3. 示例

path = $(dir </src/a.c>)
提取文件"/src/a.c" 的目录部分,则path的值为/src

notdir函数

  1. 功能:去除文件中的目录部分,提取文件名
  2. 使用方法:
$(notdir  <names···>)
  1. 示例
file_name = $(notdir </src/a.c>)
提取文件“/src/a.c”中的非目录部分,则file_name的值为a.c

foreach函数

  1. 功能:循环
  2. 使用方法:
$(foreach  <var>,<list>,<text>)

此函数的意思是把参数<list>中的单词逐一取出来放到参数中,然后再执行<text>所包含的表达式。每次<text>都会返回一个字符串,循环过程中,<text>中所包含的每个字符串会以空格隔开,最后当整个循环结束时,<text>所返回的每个字符串所组成的整个字符串为foreach函数的返回值
3. 示例:

wildcard函数

  1. 功能:使用通配符查找
  2. 使用方法:
$(wildcard  PATTERN···)
  1. 示例
$(wildcard  *.c)
获取当前目录下得所有.c文件