一个makefile解析

PROG=led
BIN=$(PROG).bin
OBJS=led.o gpio.o
CC=arm-linux-gcc
LD=arm-linux-ld
OBJCOPY=arm-linux-objcopy
CFLAG=-march=armv5te -nostdlib
LDFLAG=-nostdlib -nostartfiles -Ttext=0x20008000 -entry=led_main
$(BIN):$(PROG)
	$(OBJCOPY) -O binary $< $@
	cp $@ /tftpboot
$(PROG):$(OBJS)
	$(LD) $(LDFLAG) -o $@ $(OBJS)
%.o:%.c
	$(CC) $(CFLAG) -c -o $@ $<
clean:
	rm -rf $(OBJS) $(PROJ) $(BIN)



项目有两个源文件和两个头文件  分别是led.c   led.h gpio.c gpio.h

分析makefile:

1到8行:定义自动化变量以及编译连接的规则

8到15行:makefile的核心,目标文件,依赖文件以及规则

16到17:伪指令

1:项目名字led用一个自动化变量PROG来表示,之后的$(PROG)就等于led,这样一旦以后项目的名字变化,只需要在第一行将led变化就可以,否则,在以下的所有涉及到项目名字的地方都要修改。

2.$(PROG).bin等于led.bin,这是我们最终要生成的一个目标文件,用自动化变量BIN来表示。

3.项目两个源文件对应两个中间目标文件,led.o和gpio.o,用一个自动化变量OBJS表示。

4,5:编译器和连接器的名字

6:格式转换文件 ,可以把ELF格式程序转换成纯二进制文件。

7:编译器的编译规则:

-march=armv5te:

arm-linux-gcc编译器交叉编译时可以通过在CFLAGS中加入-march选项来选择编译出的汇编指令是针对arm处理器的哪个体系结构。如:ARM7TDMI处理器加入-march=armv4t表示支持V4T的指令集,从而解决了没有加入-march选项时编译器将半字或字的strh和str操作自动编译成了2个strb或4个strb指令,我们的处理器是要生成v5te指令集

-nostdlib:

-nostdlib不连接系统标准启动文件和标准库文件,只把指定的文件传递给连接器。这个选项常用于编译内核、bootloader等程序,它们不需要启动文件,标准库文件,C语言程序执行的第一条指令。并不是main函数。生成一个C程序的可执行文件时编译器通常会在我们的代码上加上几个被称为启动文件的代crt1.o,crti.o,crtend.o,crtn.o等,他们是标准库文件。这些代码设置C程序的堆栈等,然后调用main函数。他们依赖于操作系统,在裸板上无法执行

8.链接器的链接规则:

 -Ttext=0x20008000

汇编程序会经过二次遍历,有些符号引用会被标记为可重定位,在编译好后他们的偏移值是其在代码内部的偏移值,即LC计数器的值,当载入内存运行时,由于起始加载地址会不确定,所以会在加载后把代码段所在的内存起始地址加到符号引用原有的偏移上,这就叫重定位。比如一个jmpabc会跳到代码段内部偏移10的地方,是代码被加载到内存偏移1000,所以实际上那个abc标号偏移10的地方在实际的内存里面偏移是1010,所以再继续往abc(偏移10)跳会出问题,故而给abc的偏移10加上加载处起始地址1000,得出1010,这样jmp 1010就执行正确了,达到重定位的目的。程序之后会下载到开发板20008000处执行,因此这里把代码段也定位到20008000

9-11:$(BIN)即led.bin是最重要得出的目标文件,它的依赖文件是led,如果此时这个led还不存在或者更新时间比目标文件迟,则会先执行12行以后的内容,得到最新的led之

后,按照10,11行的规则生成led.bin。 $<是依赖文件的第一项,即led,$@是要生成的目标文件即led.bin,cp $@ /tftpboot指最后将生成的目标文件拷贝到/tftpboot目录下。

12-13:此时的目标文件是led,依赖文件是所有的.o文件,,如果此时所有的.o文件还不存在或者更新时间比目标文件迟,则会先执行14行以后的内容,执行规则在13行,通过arm-linux-ld链接器,按照LDFLAG里的规则进行链接。

14-15:%.o表示所有的.o文件即“led.ogpio.o”,依赖文件%.c表示将目标文件%之后的去掉即“led gpio”并加上.c即“led.c gpio.c”,5行是依赖规则,因此这两行展开相当于:

led.o : led.c

$(CC) -c $(CFLAGS) led.c -o led.o

gpio.o :gpio.c

$(CC) -c $(CFLAGS)gpio.c -o gpio.o

16-17:是伪指令,因为clean:之后什么也没有,make一下是不会执行的,只有当手动敲make clean的时候才会执行,它的目的是一次性清除所有生成可执行文件过程中生成的所有中间文件,之后要make的话所有的中间文件都是重新生成的,而不会是当检测到更新时间早于目标文件就不会执行。


  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值