两个个makefile例子的分析

来源:互联网 发布:js字符串拼接加换行符 编辑:程序博客网 时间:2024/06/05 15:39
在韦东山的mmu试验中的makefile是这样写的:看的不知其所以然,花了一天时间查明白是干什么的了:

objs := head.o init.o leds.o
mmu.bin : $(objs)
arm-linux-ld   -T   mmu.lds -o mmu_elf $^
arm-linux-objcopy -O binary -S mmu_elf $@
arm-linux-objdump -D -m arm mmu_elf > mmu.dis

%.o:%.c
arm-linux-gcc -Wall -O2 -c -o $@ $<


%.o:%.S
arm-linux-gcc -Wall -O2 -c -o $@ $<


clean:
rm -f mmu.bin mmu_elf mmu.dis *.o

其中连接脚本mmu.lds是如下:
SECTIONS { 
  firtst    0x00000000 : { head.o init.o }
  second    0xB0004000 : AT(2048) { leds.o }

 
下面进行分析:
1  objs := head.o init.o leds.o
objs是makefile中的一个变量,类似C中的宏定义#define ,是为了省去在后面写 head.o init.o leds.o,可以直接用$(objs)代替。
2  mmu.bin : $(objs),mmu.bin是目标文件,$(objs)是依赖关系。

arm-linux-ld 是连接器,它把一些目标和归档文件结合在一起,重定位数据,并连接符号引用。通常,建立一个新编译程序的最后一步就是调用ld。arm-linux-objcopy 把一种目标文件中的内容复制到另一种类型的目标文件中.rm-linux-objdump 显示一个或者更多目标文件的信息。使用选项来控制其显示的信息,它所显示的信息通常只有编写编译工具的人才感兴趣.
其实   gcc是编译器,负责对c代码的编译, ld是连接器 负责将多个*.o的目标文件链接成elf可执行文件。elf可执行文件是unix常用的可执行文件类型,就像windows的exe文件。elf文件中有很多信息包括段信息还有头信息,这些信息对硬件是没有意义的,所以有的时候我们通过objcopy将elf转化成bin 文件加载到内存中运行,bin文件就是一个纯二进制文件,并且你可以通过objdump将elf文件来反汇编。

rm-linux-gcc
arm-linux-gcc -Wall -O2 -c -o $@ $<
 
-o 只激活预处理,编译,和汇编,也就是他只把程序做成obj文件也就是.o的目标文件
 
-Wall 指定产生全部的警告信息
 
-O2 编译器对程序提供的编译优化选项,在编译的时候使用该选项,可以使生成的执行文件的执行效率提高,O后面还可以附带其他的数值,表示提供不同的优化策略。
 
-c 表示只要求编译器进行编译,而不要进行链接,生成以源文件的文件名命名但把其后缀由 .c 或 .cc 变成 .o 的目标文件
 
-S 只激活预处理和编译,就是指把文件编译成为汇编代码也就是.s文件

$@和$<在makefile中其实是自动化变量,“$<”表示所有的依赖目标集(也就是“.c ”),“$@”表示所有目标集(“.o”)
 
arm-linux-ld
 
直接指定代码段,数据段,BSS段的起始地址
-Ttext startaddr
-Tdata startaddr
-Tbss startaddr
 
示例:
arm-linux-ld –Ttext 0x0000000 –g led.o –o led_elf
 
使用连接脚本设置地址:
arm-linux-ld –Ttimer.lds –o timer_elf  $^
 
其中timer.lds 为连接脚本
 
完整的连接脚本格式:
SECTIONS{
Secname start ALING(aling) (NOLOAD):AT(ldaddr)
{contents} > region:phdr=fill
…..
}
 arm-linux-objcopy
被用来复制一个目标文件的内容到另一个文件中,可用于不同源文件的之间的格式转换
示例:
arm-linux-objcopy –O binary –S elf_file bin_file
 
常用的选项:

        1.input-file , outfile

         输入和输出文件,如果没有outfile,则输出文件名为输入文件名

        2.-I bfdname或—input-target=bfdname
  用来指明源文件的格式,bfdname是BFD库中描述的标准格式名,如果没指明,则arm-linux-objcopy自己分析
 3.-O bfdname 或--output-target=bfdname 输出的格式
 4.-F bfdname 同时指明源文件,目的文件的格式,将源文件和输出文件的格式都设置为bfdname
 5.-R sectionname 从输出文件中删除掉所有名为sectionname的段
 6.-S 不从源文件中复制重定位信息和符号信息到目标文件中
 7.-g 不从源文件中复制调试符号到目标文件中

arm-linux-objdump
  查看目标文件(.o文件)和库文件(.a文件)信息
arm-linux-objdump -D -m arm led_elf > led.dis
 
-D 显示文件中所有汇编信息
-m machine
    指定反汇编目标文件时使用的架构,当待反汇编文件本身没有描述架构信息的时候(比如S-records),这个选项很有用。可以用-i选项列出这里能够指定的架构



第二个例子

File :Makefile
01 CC      = arm-linux-gcc    (编译工具)
02 LD      = arm-linux-ld(连接工具)
03 AR      = arm-linux-ar(将多个.o文件合并成一个.O或者静态库文件(.a文件))
04 OBJCOPY = arm-linux-objcopy(复制一个目标的内容到另一个文件中,将elf转化成bin文件加载到内存中运行用此工具)
05 OBJDUMP = arm-linux-objdump(用于显示二进制文件信息,将elf文件反汇编)


06 INCLUDEDIR := $(shell pwd)/include                            (shell函数,本句是在当前目录下的include文件夹下)
07 CFLAGS := -Wall -O2                                                (CFLAGS为C语言编译器参数,-wall打开警告和优化级别为O2)
08 CPPFLAGS   := -nostdinc -I$(INCLUDEDIR)      
CPPFALGS 为c语言预处理参数,这里-nostdinc的意思是:Do not search the standard system directories for header files。-I 指定只对#include “file”有效的头文件搜集目录)
LDFLASG         := -L $(shell dirname `$(CC) $(CFLAGS) -print-libgcc-file-name`) -lgcc      (LDFLAGS为链接器参数-print-libgcc-file-name:示编译器伴随库的名称)


09 export CC LD OBJCOPY OBJDUMP INCLUDEDIR CFLAGS CPPFLAGS AR  (用export声明这些变量使得他们可以被子目录的Makefile使用


10 objs := head.o init.o nand.o interrupt.o adc_ts.o serial.o main.o lib/libc.a    objs 为变量,代替后面.o程序。lib/libc.a为连接库文件


11 adc_ts.bin: $(objs)
12 ${LD} -Tadc_ts.lds -o adc_ts_elf $^ ${LDFLASG}   (-T后面链接脚本adc_ts.lds ,$^为自动化变量,表示所有依赖目标的集合)


13 ${OBJCOPY} -O binary -S adc_ts_elf $@ ($@表示规则中的目标文件集,本句将elf文件可执行文件转换成二进制)
14 ${OBJDUMP} -D -m arm adc_ts_elf > adc_ts.dis('-m' 后面跟的是cpu构架 arm就表示是arm构架的cpu '>' 表示将这个程序的反汇编程序写入到led.dis这个文件中,在终端中不显示出来.当你打开led.dis这个文件时就会看到上面命令的输出的反汇编程序了



15 .PHONY : lib/libc.a      (,PHONY用来声明一个伪目标)
16 lib/libc.a:
17 cd lib; make; cd ..

18 %.o:%.c
19 ${CC} $(CPPFLAGS) $(CFLAGS) -c -o $@ $<          (将所有的[.C]文件都编译成[.O]文件)


20 %.o:%.S
21 ${CC} $(CPPFLAGS) $(CFLAGS) -c -o $@ $<         (将所有的[.s]文件都编译成[.O]文件


22 clean:(删除文件)
23 make  clean -C lib
24 rm -f adc_ts.bin adc_ts_elf adc_ts.dis *.o 





0 0
原创粉丝点击