GCC编译
-
不同的编译架构,gcc编译器是不同的,ubuntu自带的gcc编译器针对的是x86架构,想要编译在 ARM 上运行的程序就需要针对 ARM 架构的 GCC 编译器,也就是交叉编译器。
-
GCC 编译器的编译流程是:预处理、汇编、编译和链接。
-
预处理就是对程序中的宏定义等 相关的内容先进行前期的处理。
-
汇编是先将 C 文件转换为汇编文件。
-
当 C 文件转换为汇编文件 以后就是文件编译了,编译过程就是将 C 源文件编译成.o 结尾的目标文件。
-
编译生成的.o 文 件不能直接执行,而是需要最后的链接,如果你的工程有很多个 c 源文件的话最终就会有很 多.o 文件,将这些.o 文件链接在一起形成完整的一个可执行文件。
-
Makefile
Makefile:描述哪些文件需要编译、如何编译等编译规则的文件.
创建的文件名一定叫做Makefile;文件中所有代码行首空出来的地方一定要使用TAB键,不能用空格。
Makefile编写完成后,直接在命令行输入make命令,即可按照定义的方式编译整个工程。
Makefile规则
规则用来描述在什么情况下、使用什么命令来构建一个特定的文件, 这个文件就是规则的“目标”。
目标…… : 依赖文件集合……
命令 1
命令 2
……
更新:执行一遍规则中的命令列表
如果要更新目标,就必须要先更新它的所有依赖文件,如果依赖文件中的任何一个有更新,那么目标也必须更新。
如果没有依赖文件,会默认所有依赖文件都是最新的,对应的命令不会执行。
第一条规则中的第一个目标成为终极目标,只要该目标更新了,那么 Makefile 的工作就完成了。
除了终极目标所在规则外,其它规则的顺序没有意义。
Make执行过程
- make 命令会在当前目录下查找以 Makefile(makefile 其实也可以)命名的文件。
- 当找到 Makefile 文件以后就会按照 Makefile 中定义的规则去编译生成最终的目标文件。
- 当发现目标文件不存在,或者目标所依赖的文件比目标文件新(也就是最后修改时间比 目标文件晚)的话就会执行后面的命令来更新目标。
make 工具就是在 Makefile 中一层一层的查找依赖关系,并执行相应的命令,编译出最终的可执行文件。
Makefile变量
Makefile中的变量都是字符串。
注释开头要用符号#
。
Makefile中变量的引用方法是$(变量名)
。
在命令前面加上@
的话就不会输出命令执行过程.
在 Makefile 要输出一串字符的话使用echo
赋值符:
=
:可以使用后面定义的变量,变量的真实值取决于它所引用的变量的最后一次有效值。
:=
:不会使用后边定义的变量。
?=
:如果前面没有赋值,使用后面的值;如果前面已经赋过值,则使用前面赋的值。
+=
:给定义好的变量添加一些字符串。
#"=":curname=r
#":="curname=z
name = z
curname := $(name)
#curname = $(name)
name = r
print:
@echo curname: $(name)
Makefile模式规则和自动化变量
目标中的%
表示对文件名的匹配,a.%.c 就表示以 a.开头,以.c 结束的所有文件。
自动化变量就是这种变量会把模式中所定义的一系列的文件自动的挨个取出,直至所有的符合模式的文件都取完,自动化变量只应该出现在规则的命令中。
自动化变量的应用范围仅限于当前命令行对应的目标依赖关系,下一个目标会再智能转换。
objects = main.o input.o calcu.o
main: $(objects)
gcc -o main $(objects)
%.o : %.c
gcc -c $<
Makefile伪目标
伪目标不代表真正的目标名,使用伪目标的主要是为了避免 Makefile 中定义的只执行命令的目标和工作目录下的实际文件出现名字冲突。
声明方式:.PHONY : clean
声明 clean 为伪目标以后,不管当前目录下是否存在名为“clean”的文件,输入make clean
的话规则后面的 rm 命令都会执行。
clean:
rm *.o
rm main
Makefile条件判断
1.<条件关键字>
<条件为真时执行的语句>
endif
2.<条件关键字>
<条件为真时执行的语句>
else
<条件为假时执行的语句>
endif
条件关键字:ifeq、ifneq、ifdef 和 ifndef
#ifeq、ifneq:判断是否相等
#ifdef:变量名的值非空,表达式为真,否则为假
ifndef <变量名>
ifeq (<参数 1>, <参数 2>)
ifeq ‘<参数 1 >’,‘ <参数 2>’
ifeq “<参数 1>”, “<参数 2>”
ifeq “<参数 1>”, ‘<参数 2>’
ifeq ‘<参数 1>’, “<参数 2>”
Makefile函数
1.$(函数名 参数集合)
2.${函数名 参数集合}
参数集合是函数的多个参数,参数之间以逗号“,”隔开,函数名和参数之间以“空格”分隔开,函数的调用以“$”开头。
Makefile常用函数:
-
subst:
$(subst <from>,<to>,<text>)
$(subst zzk,ZZK,my name is zzk)
将字符串text中的from内容替换为to,函数返回被替换以后的字符串.
-
patsubst:
$(patsubst <pattern>,<replacement>,<text>)
$(patsubst %.c,%.o,a.c b.c c.c)
查找字符串text中的单词是否符合模式pattern,如果匹配就用replacement来替换掉,可以使用通配符“%”表示任意长度的字符串,函数返回值就是替换后的字符串。
-
dir:
$(dir <names...>)
$(dir <src/a.c>)
从文件名序列names中提取出目录部分。
-
notdir:
$(notdir <names...>)
$(dir <src/a.c>)
与从文件名序列names中提取出文件名非目录部分
-
foreach:
$(foreach <var>, <list> , <text>)
此函数的意思就是把参数list中的单词逐一取出来放到参数var中,然后再执行text所包含的表达式。每次text都会返回一个字符串,循环的过程中,text中所包含的每个字符串会以空格隔开,最后当整个循环结束时,text所返回的每个字符串所组成的整个字符串将会是 foreach函数 的返回值。
-
wildcard:
$(wildcard PATTERN…)
获取当前目录下所有PATTERN模式的文件
的单词逐一取出来放到参数var中,然后再执行text所包含的表达式。每次text都会返回一个字符串,循环的过程中,text中所包含的每个字符串会以空格隔开,最后当整个循环结束时,text所返回的每个字符串所组成的整个字符串将会是 foreach函数 的返回值。 -
wildcard:
$(wildcard PATTERN…)
获取当前目录下所有PATTERN模式的文件。