第9课.gcc和arm-linux-gcc和Makefile
1.gcc编译器和arm-linux-gcc编译器
PC上的编译工具:gcc,ld,objcopy,objdump
ARM平台上必须使用交叉编译工具:arm-linux-gcc
A.一个C/C++文件处理过程:
预处理---> 编译 ---> 汇编 ---> 链接
.c/.cpp ----- .i ---- .S ----- .o ----
a.预处理
以"#"开头的命令被称为预处理命令,得到.i文件
b.编译
把.i文件翻译成汇编代码(.S)
c.汇编
将汇编代码(.S)翻译成符合一定格式的机器码(.o)
d.链接
将上步产生的文件和系统库的OBJ文件,库文件连接起来
B.arm-linux-gcc和gcc的一些常用选项
a.总体选项
-E 只预处理,不会编译、汇编、链接
-S 只编译,不会汇编、链接
-c 编译和汇编,不会链接
-o <file> 指定输出文件名为file,这个名称不能跟源文件名同名
-v 查看gcc编译器的版本,显示gcc执行时的详细过程
b.警告选项
-Wall 打开所有需要注意的警告信息
eg:
gcc -Wall -c main.c
C.arm-linux-ld
arm-linux-ld用于将多个目标文件,库文件连接成可执行文件
-T: 用于指定代码段,数据段,bss段的起始位置,也可以用来指定一个链接脚本,在脚本中进行复杂设置
eg:
-Ttext startaddr 指定代码段起始位置
-Tdata startaddr 指定数据段起始位置
-Tbss startaddr 指定bss段起始位置
注:startaddr是一个16进制的数
eg:
arm-linux-ld -Ttext 0x00000000 -g led_on.o -o led_on.elf
解析:代码段的地址为0x00000000,由于没有定义数据段,bss段的起始位置,它们被放在代码段的后面
D.arm-linux-objcopy
arm-linux-objcopy被用来复制一个目标文件的内容到另一个文件中,可以进行格式转换(常用来elf转二进制文件)
-O 使用指定的格式来输出文件
eg:
-O binary 以二进制格式输出
-S 不从源文件中复制重定位信息和符号信息到目标文件中去
E.arm-linux-objdump
arm-linux-objdump用于显示二进制文件信息,常用来查看反汇编代码。
-d/-D 反汇编可执行段/反汇编所有段
F.示例
all:
arm-linux-gcc -c -o led.o led.c
解析:
arm-linux-gcc -c:预处理,编译,汇编。把led.c->.o文件
-o:把产生的结果文件命名为led.o
arm-linux-gcc -c -o start.o start.S
arm-linux-ld -Ttext 0 start.o led.o -o led.elf
解析:
-Ttext 0:指定代码段的起始位置为0(16进制)
把文件链接在一起,并把目标文件命名为led.elf
arm-linux-objcopy -O binary -S led.elf led.bin
解析:
-O binary:转换为二进制文件
-S:不复制重定位信息和符号
把上面产生的文件转换为二进制的机器码
arm-linux-objdump -D led.elf > led.dis
解析:
-D:反汇编所有段
>:新建文件
<:原文件上添加
把连接文件,转换为反汇编代码
2.Makefile
A.Makefile规则
目标:依赖1 依赖2 ...
[TAB]命令
使用规则
make [目标]
a.如果无目标,默认执行第一个目标。
b.依赖文件比目标文件新时才会去执行命令
c.如果没有依赖,则它的命令会被强制执行
B.Makefile的语法
a.通配符:
%.* 所有的.*文件
$@ 表示目标
$< 表示第一个依赖
$^ 表示所有依赖
eg:
%.o: %.c // 所有的.o文件依赖于所有的%.c文件
gcc -c -o $@ $^ // 把所有的依赖预处理,编译,汇编处理为目标文件
b.假想目标:.PHONY
可避免文件已经存在而不能进行目标名操作
eg:
clean:
rm *.o test
.PHONY: clean
解析:此时Makefil外存在一个clean文件,会影响到clean这个目标的使用。这时使用PHONY
c.即使变量,延时变量
即使变量:在定义时它的值就确定了
延时变量:在使用这个变量时才会被确定
:= 即时变量
= 延时变量
?= 延时变量,但这个仅仅在变量还没有定义的情况下有效,如果变量前面已经被定义了,则忽略词条语句
+= 附加,是即时变量还是延时变量,取决于前面的定义
C.Makefile常用函数
a. $(foreach var,list,text)
b. $(filter pattern...,text) # 在text中取出符合patten格式的值
$(filter-out pattern...,text) # 在text中取出不符合patten格式的值
c. $(wildcard pattern) # pattern定义了文件名的格式,
# wildcard取出其中存在的文件
d. $(patsubst pattern,replacement,$(var)) # 从列表中取出每一个值
# 如果符合pattern
# 则替换为replacement