arm-linux-gcc和简单的makefile
@(嵌入式工具环境)
gcc常用选项
gcc 的使用方法: gcc [选项] 文件名
-v:查看gcc编译器的版本,显示gcc执行时的详细过程
-o :指定输出文件名为file,不用与编译文件同名
-E: preprocess only; do not compile, assemble or link(只预处理,不会编译、汇编、链接)
-S:Compile only; do not assemble or link(只编译需要有已经预处理完成的输出文件,不会汇编和链接)
-c:Compile and assemble, but do not link(预处理 编译和汇编,不会链接)
gcc编译文件
gcc hello.c
:直接默认生成一个a.out文件
gcc -o hello hell.out
: 指定生成hello
gcc -E -o hello.i hello.c
: 预处理
gcc -S -o hell0.s hello.i
:编译
gcc -c -o hello.o hello.s
:编译汇编
gcc -o hello hello.o
:链接
小结:
1)输出文件的后缀名和选项共同决定gcc到底执行哪些操作
2)在编译过程中除非使用了-E、-S、—c 选项,或者编译出错阻止了完整的编译过程,否则最后的步骤都是链接
深入链接的过程
链接就是将汇编生成的OBJ文件、系统库的OBJ文件、库文件链接起来,最终生成可以在特定平台运行的可执行程序。
-lc:链接libc库文件
-nostdlib选项常用于裸机、bootloader、linux内核等程序,因为他们不需要启动文件,也不需要标准库文件,一般应用程序才需要系统标准启动文件和库文件。
动态链接使用动态链接库进行链接,生成的程序在执行的时候需要加上动态库才能运行。动态链接生成的程序体积较小,但是必须依赖所需要的动态库,否则无法运行。
静态链接使用静态库进行链接,生成的程序包含程序运行所需要的全部库,可以直接运行,不过静态链接生成的程序体积较大。
Makefile
makefile的引入
组织管理程序
在有多个原文件的情况下,首先要编译会比较麻烦,再者,每次都会对所有的文件都会执行一次预处理、编译、汇编、链接
如何判断哪些文件被修改 – 比较时间
makefile规则
目标文件:依赖1 依赖2 …
(使用TAB键 )命令
当目标文件不存在或者某个依赖文件比目标文件新
则执行命令
简单的makefile
假设有a.c和b.c两个源文件,要生成text
makefile 如下text:a.o b.o gcc -o -text a.o b.o a.o:a.c gcc -c -o a.o a.c b.o:b.c gcc -c -o b.o b.c
分析:第一次执行,a.o b.o都不存在,执行gcc -c -o a.o a.c和gcc -c -o b.o b.c ,之后执行gcc -o -text a.o b.o来生成 a .o b.o;后面用a.o b.o 来执行gcc -o -text a.o b.o来生成text
加入更改了a.c ,则执行make时,因为依赖a.o 和 b.o,先查看a.o,a.o 依赖a.c 改变,执行gcc -c -o a.o a.c,b.o的依赖不变,而后执行gcc -o -text a.o b.o生成目标
makefile语法
使用makefile,用make命令,如果不跟目标,默认第一个目标,
%:通配符
@
∗
∗
:
目
标
文
件
∗
∗
@**:目标文件 **
@∗∗:目标文件∗∗<:第一个依赖
$^:表示所有的依赖
.PHONY:假象目标
clean:
rm *.o
如果同目录下存在clean文件,则执行make clean后,命令并不会被执行,加上.PHONY: clean
后,就可以执行了。
即时变量(简单变量)、延时变量、export
变量的引用使用$(变量名)
A:=XXX #A的值即确定,在定义时就确定
B =XXX #B的值使用到时才确认
?= XXX #如果是第一次定义,才起效,如果前面已经定义,则不起效
+= XXX #附加,他是即时变量还是延时变量,取决于之前的定义
makefile函数
A = a b c
B = $(foreach f, &(A), &(f).o)
all:
echo B=$(B)
gcc -M c.c // 打印出依赖
gcc -M -MF c.d c.c //把依赖写入文件c.d
gcc -c -o c.o c.c -MD -MF c.d //编译c.o,把依赖写入文件c.d