写在前面的话:
关于Makefile学习笔记系列的文章,是我正在学习的正点原子的阿尔法开发板的内容,所有例程源码均来自正点原子的例程,写这个文章的目的是为了学习Makefile。
Makefile代码摘自【正点原子】I.MX6U嵌入式Linux驱动开发指南
Makefile代码
objs := start.o main.o
ledc.bin:$(objs)
arm-linux-gnueabihf-ld -Timx6ul.lds -o ledc.elf $^
arm-linux-gnueabihf-objcopy -O binary -S ledc.elf $@
arm-linux-gnueabihf-objdump -D -m arm ledc.elf > ledc.dis
%.o:%.s
arm-linux-gnueabihf-gcc -Wall -nostdlib -c -O2 -o $@ $<
%.o:%.S
arm-linux-gnueabihf-gcc -Wall -nostdlib -c -O2 -o $@ $<
%.o:%.c
arm-linux-gnueabihf-gcc -Wall -nostdlib -c -O2 -o $@ $<
clean:
rm -rf *.o ledc.bin ledc.elf ledc.dis
objs := start.o main.o 变量的使用,Makefile中的变量都是字符串!
作为ledc.bin的依赖文件
makefile中几种给变量赋值的方法
1、赋值符“=” 变量的真实值取决于它所引用的变量在 整个文件中
的最后一次有效值。
1 name = zzk
2 curname = $(name)
3 name = zuozhongkai
4 print:
5 @echo curname: $(curname)
输出值
curname: zuozhongkai
即是name最后一次的赋值作为有效值。
2、赋值符“:=” 使用 当前变量位置
之前定义的变量值
1 name = zzk
2 curname := $(name)
3 name = zuozhongkai
4 print:
6 @echo curname: $(curname)
输出值
curname: zzk
3、赋值符“?=”
curname ?= zuozhongkai
上述代码的意思就是,如果变量 curname 前面没有被赋值,那么此变量就是“zuozhongkai”,如果前面已经赋过值了,那么就使用前面赋的值。
4、变量追加 “+=”
Makefile 中的变量是字符串,有时候我们需要给前面已经定义好的变量添加一些字符串进去,此时就要使用到符号“+=”,比如如下所示代码:
objects = main.o inpiut.o
objects += calcu.o
一开始变量 objects 的值为“main.o input.o”,后面我们给他追加了一个“calcu.o”,因此变量 objects 变成了“main.o input.o calcu.o”,这个就是变量的追加。
两个依赖文件 start.o main.o 靠下面几行代码产生
%.o:%.s
arm-linux-gnueabihf-gcc -Wall -nostdlib -c -O2 -o $@ $<
%.o:%.S
arm-linux-gnueabihf-gcc -Wall -nostdlib -c -O2 -o $@ $<
%.o:%.s
arm-linux-gnueabihf-gcc -Wall -nostdlib -c -O2 -o $@ $<
%类似于通配符 * ,匹配长度任意的非空字符串,%.o:%.s ,%.o:%.c 即是把所有的.s文件和所有的.c文件转换成.o文件
arm-linux-gnueabihf-gcc 交叉编译工具
-Wall 表示显示编译的时候所有警告
-nostdlib表示不链接系统标准启动文件和库文件,否则编译可能出错
-O2表示优化等级,和MDK上的设置含义一样。
剩下的两个符号$@ $<看下表
再回到目标文件下的三句话:
arm-linux-gnueabihf-ld -Timx6ul.lds -o ledc.elf $^
arm-linux-gnueabihf-objcopy -O binary -S ledc.elf $@
arm-linux-gnueabihf-objdump -D -m arm ledc.elf > ledc.dis
arm-linux-gnueabihf-ld用来将众多的.o文件链接到一个指定的链接位置
-Timx6ul.lds 替换了原来的 -Ttext 0X87800000
imx6ul.lds是一个链接脚本文件,内容如下
SECTIONS{
. = 0X87800000;
.text :
{
start.o
main.o
*(.text)
}
.rodata ALIGN(4) : {*(.rodata*)}
.data ALIGN(4) : { *(.data) }
__bss_start = .;
.bss ALIGN(4) : { *(.bss) *(COMMON) }
__bss_end = .;
}
“SECTIONS”:用来描述输出文件的内存布局
“.”:定位计数器
“.rodata”:只读数据段
“.data”:数据段
“.bss”:定义了但是没有初始化的变量,需要用两个标号记录这段内存空间的起始和结尾地址也就是__bss_start和__bss_end
$^:是所有依赖文件的集合,也就是start.o main.o
arm-linux-gnueabihf-objcopy -O binary -S ledc.elf $@
arm-linux-gnueabihf-objcopy格式转换工具
-O binary 指定二进制格式输出
-S 表示不复制源文件中的重定位信息和符号信息
$@:目标文件集合,即ledc.bin
arm-linux-gnueabihf-objdump -D -m arm ledc.elf > ledc.dis
arm-linux-gnueabihf-objdump 反汇编工具
-D 表示反汇编所有段
-m arm 暂时没查到什么意思
led.dis 反汇编文件