Makefile教程

来源:互联网 发布:正则表达式 手机号js码 编辑:程序博客网 时间:2024/06/08 02:57

arm裸板程序编译过程:

    arm-linux-gnueabihf-gcc test.c -c -o test.o    arm-linux-gnueabihf-gcc abc.c -c -o abc.o    arm-linux-gnueabihf-ld test.o abc.o -o test    arm-linux-gnueabihf-objcopy -O binary test test.bin

这个编译过程比较麻烦, 文件越多越麻烦. 但用Mafile来管理编译会方便很多.

1).    如当前目录下有:   main.S,  a.c , b.c    写Makefile来管理, 先记住Mafile是倒序来写的.    像我们最终目标是test.bin, 但test.bin由test生成, test又是由main.o、a.o 、b.o组成.    main.o是由main.S, *.o 由 *.c生成.    Makefile里的写法:    test.bin  :  test    //test.bin表示目标, test表示依赖. 也就是test.bin由test生成        arm-linux-gnueabihf-objcopy -O binary test test.bin   //接着的这行写当有test之后怎样生成test.bin的语句. 注意执行语句前面不能有空格    test : main.o  a.o b.o        arm-linux-gnueabihf-ld main.o a.o b.o -o test    main.o : main.S        arm-linux-gnueabihf-gcc main.S -c -o main.o    a.o  : a.c        arm-linux-gnueabihf-gcc a.c -c -o a.o    b.o  : b.c        arm-linux-gnueabihf-gcc b.c -c -o b.o
2). Makefile里的符号    "$@" 表示目标,   "$<"表示第一个依赖,   "$^"表示所有的依赖    所以上例又可以改造成:    test.bin  :  test            arm-linux-gnueabihf-objcopy -O binary $< $@       test : main.o  a.o b.o        arm-linux-gnueabihf-ld $^ -o $@    main.o : main.S        arm-linux-gnueabihf-gcc $< -c -o $@    a.o  : a.c        arm-linux-gnueabihf-gcc $< -c -o $@    b.o  : b.c        arm-linux-gnueabihf-gcc $< -c -o $@  
3). Makefile里的通配符"%"    test.bin : test        arm-linux-gnueabihf-objcopy -O binary $<  $@    test : main.o a.o b.o          arm-linux-gnueabihf-ld $^ -o $@    %.o : %.S       arm-linux-gnueabihf-gcc $< -c -o $@    %.o : %.c             arm-linux-gnueabihf-gcc $< -c -o $@ 
4). Makefile里应用变量, 如CROSS_COMPILE变量用于指定交叉编译器的前缀. OBJS变量指定编译目标. TARGET指定生成程序镜像名. $(变量)就是取变量的值. 而且在执行Makefile时可以指定变量的值: "make CROSS_COMPILE=arm-linux-"    CROSS_COMPILE ?= arm-linux-gnueabihf-    OBJS += main.o    OBJS += a.o     OBJS += b.o     TARGET ?= test    $(TARGET).bin : $(TARGET)        $(CROSS_COMPILE)objcopy -O binary $<  $@    $(TARGET) : $(OBJS)        $(CROSS_COMPILE)ld $^ -o $@    %.o : %.S         $(CROSS_COMPILE)gcc $< -c -o $@    %.o : %.c         $(CROSS_COMPILE)gcc $< -c -o $@
5). wildcard函数用于获取指定扩展名的所有文件名.    patsubst函数可用于替换指定扩展名. 用法$(patsubst  %.c, %.o, a.c b.c)) //把"a.c b.c"转换成"a.o b.o"   如实现获取当前目录所有源文件,并把文件名转换成对应的.o    CFILES = $(wildcard *.c)  //先获取当前目录下的所有.c文件名. 每个文件名空格隔开    SFILES = $(wildcard *.S)      COBJS = $(patsubst %.c, %.o, $(CFILES)) //把文件名改成.o名字    SOBJS = $(patsubst %.S, %.o, $(SFILES))    OBJS += $(COBJS)    OBJS += $(SOBJS)    all:        echo $(OBJS)
6). 执行Makefile时,如不指定目标,则默认执行第1个目标.    如"make uboot"表示只执行Makefile里的uboot目标    Makefile里的"PHONY"修饰目标时,可防止目录里有文件名与目标名一致时的冲突.    .PHONY : clean    clean:    rm *.o -rf
7). 多个源码目录的Makefile编写.    "make -C 目录路径"执行指定目录里的Makefile    如当前目录下有两个子目录cpu, drivers    cpu目录里有start.S  a.c  main.c    drivers目录里有a.c  b.c  c.c    可以先把子目录里的所有编译生成的.o文件打包成一个.o文件,最后再一起链接成可执行文件.    cpu目录里的Makefile:    CFILES = $(wildcard *.c)    SFILES = $(wildcard *.S)      COBJS = $(patsubst %.c, %.o, $(CFILES))    SOBJS = $(patsubst %.S, %.o, $(SFILES))    OBJS += $(COBJS)    OBJS += $(SOBJS)    libcpu.o : $(OBJS)         arm-linux-gnueabihf-ld -r $^ -o $@    %.o : %.S        arm-linux-gnueabihf-gcc $< -c -o $@    %.o : %.c        arm-linux-gnueabihf-gcc $< -c -o $@    .PHONY : clean    clean:        rm $(OBJS) libcpu.o -rf    drivers目录里的Makefile与cpu目录里的差不多,只是目标名为"libdrivers.o"    当前目录里的Makefile:    test.bin : test        arm-linux-gnueabihf-objcopy -O binary test test.bin    test : mkcpu  mkdrivers        arm-linux-gnueabihf-ld cpu/libcpu.o drivers/libdrivers.o -o test    mkcpu:        make -C cpu/    mkdrivers:        make -C drivers/    .PHONY : clean    clean:        make -C cpu/ clean        make -C drivers clean   
8). 上例子目录里的Makefile内容大多重复,可以进一步精简下.     把重复做的内容放到一个文件里,如:    config.mk:        CFILES = $(wildcard *.c)        SFILES = $(wildcard *.S)          COBJS = $(patsubst %.c, %.o, $(CFILES))        SOBJS = $(patsubst %.S, %.o, $(SFILES))        OBJS += $(COBJS)        OBJS += $(SOBJS)       config2.mk:        %.o : %.S            $(CROSS_COMPILE)gcc $< -c -o $@  $(CFLAGS)        %.o : %.c            $(CROSS_COMPILE)gcc $< -c -o $@  $(CFLAGS)        .PHONY : clean        clean:            rm *.o -rf      当前目录的Makefile:        #子目录里的Makefile使用此环境变量,需要加"export"成为全局环境变量才可以    export CROSS_COMPILE ?= arm-linux-gnueabihf-    export CFLAGS =     test.bin : test        $(CROSS_COMPILE)objcopy -O binary test test.bin    test : mkcpu  mkdrivers        $(CROSS_COMPILE)ld cpu/libcpu.o drivers/libdrivers.o -o test    mkcpu:        make -C cpu/    mkdrivers:        make -C drivers/    .PHONY : clean    clean:        make -C cpu/ clean        make -C drivers clean       cpu子目录里的Makefile:        include ../config.mk        libcpu.o : $(OBJS)             $(CROSS_COMPILE)ld -r $^ -o $@        include ../config2.mk    drivers子目录里的Makefile:        include ../config.mk        libdrivers.o : $(OBJS)             $(CROSS_COMPILE)ld -r $^ -o $@        include ../config2.mk       

////////////////////////////////////////
还有更多的扩展方法可以在uboot, linux内核里的Makefile进行参考

原创粉丝点击