①Makefile教程

转载自jklinux博主
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里的通配符”%”
Makefile中的 % 标记和系统通配符 * 是有区别,在这里就不详细介绍了。
test.bin : test
arm-linux-gnueabihf-objcopy -O binary < < <script type="math/tex" id="MathJax-Element-18">< </script>@

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= ( w i l d c a r d ∗ . c ) / / 先 获 取 当 前 目 录 下 的 所 有 . c 文 件 名 . 每 个 文 件 名 空 格 隔 开 S F I L E S = (wildcard *.S)
COBJS = (patsubst ( p a t s u b s t (CFILES)) //把文件名改成.o名字
SOBJS = (patsubst ( p a t s u b s t (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  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值