我是靠谱客的博主 顺利哑铃,最近开发中收集的这篇文章主要介绍Makefile教程,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

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进行参考

最后

以上就是顺利哑铃为你收集整理的Makefile教程的全部内容,希望文章能够帮你解决Makefile教程所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(53)

评论列表共有 0 条评论

立即
投稿
返回
顶部