顶层Makefile
CROSS_COMPILE= #arm-linux- 指定交叉编译器
AS = $(CROSS_COMPILE)as #汇编器 .s>.o
LD = $(CROSS_COMPILE)ld #链接器 》.elf
CC = $(CROSS_COMPILE)gcc
CPP = $(CC) -E #编译器只进行编译,而不做汇编和链接
AR = $(CROSS_COMPILE)ar #静态库
NM = $(CROSS_COMPILE)nm #生成elf文件中的符号
STRIP = $(CROSS_COMPILE)strip #去掉elf文件中不需要的信息和代码
OBJCOPY = $(CROSS_COMPILE)objcopy #.elf>.bin
OBJDUMP = $(CROSS_COMPILE)objdump #反汇编 .o>.asm
#export导出,供底层目录引用
export AS LD CC CPP AR NM STRIP OBJCOPY OBJDUMP
#打印警告信息 二级优化 调试信息
CFLAGS := -Wall -O2 -g
#-I指定头文件目录
CFLAGS += -I $(shell pwd)/include -I /usr/include/freetype2
#链接库
LDFLAGS := -lm -lfreetype -lvga -lvgagl
export CFLAGS LDFLAGS
TOPDIR := $(shell pwd) #顶层目录
export TOPDIR
TARGET := show_file
obj-y += main.o
obj-y += display/
obj-y += draw/
obj-y += encoding/
obj-y += fonts/
#$(TARGET)依赖于当前目录下的built-in.o
all :
#执行顶层目录的makefile,进入./目录下,用Makefile.build编译
make -C ./ -f $(TOPDIR)/Makefile.build
$(CC) $(LDFLAGS) -o $(TARGET) built-in.o
clean:
rm -f $(shell find -name "*.o")
rm -f $(TARGET)
distclean:
rm -f $(shell find -name "*.o")
rm -f $(shell find -name "*.d")
rm -f $(TARGET)
顶层makefile.build
PHONY := __build #目标
__build:
obj-y :=
subdir-y :=
#当前目录下的makefile
include Makefile
# 举例a.o b.o /c /d
# $(filter %/, $(obj-y)) :得到 c/ d/
# __subdir-y :将c/ d/替换为 c d
# subdir-y :取出子目录 c d
__subdir-y := $(patsubst %/,%,$(filter %/, $(obj-y)))
subdir-y += $(__subdir-y)
# 子目录下的built-in.o
subdir_objs := $(foreach f,$(subdir-y),$(f)/built-in.o)
cur_objs := $(filter-out %/, $(obj-y)) #得到 *.o
dep_files := $(foreach f,$(cur_objs),.$(f).d) #得到*.o的依赖文件*.o.d
dep_files := $(wildcard $(dep_files)) #判断依赖文件是否存在
#依赖文件非空,则包含
ifneq ($(dep_files),)
include $(dep_files)
endif
PHONY += $(subdir-y)
#__build依赖子目录 和当前目录下的 built-in.o
__build : $(subdir-y) built-in.o
#进入子目录,再使用Makefile.build编译
$(subdir-y):
make -C $@ -f $(TOPDIR)/Makefile.build
# 当前目录下的built-in.o 依赖当前目录下的*.o和子目录下的built-in.o
#将当前目录下的*.o和子目录下的built-in.o链接为一个buillt-in.o
built-in.o : $(cur_objs) $(subdir_objs)
$(LD) -r -o $@ $^
dep_file = [email protected] #所有的依赖文件*.o.d
#将*.c编译为*.o
%.o : %.c
$(CC) $(CFLAGS) -Wp,-MD,$(dep_file) -c -o $@ $<
.PHONY : $(PHONY)
一、各级子目录的Makefile:
obj-y += file.o
obj-y += subdir/
"obj-y += file.o"表示把当前目录下的file.c编进程序里,
"obj-y += subdir/"表示要进入subdir这个子目录下去寻找文件来编进程序里,是哪些文件由subdir目录下的Makefile决定。
二、顶层目录的Makefile:
它除了定义obj-y来指定根目录下要编进程序去的文件、子目录外,主要是定义工具链、编译参数、链接参数──就是文件中用export导出的各变量。
三、顶层目录的Makefile.build:
这是最复杂的部分,它的功能就是把某个目录及它的所有子目录中、需要编进程序去的文件都编译出来,打包为built-in.o
.PHONY是一个伪目标,可以防止在Makefile中定义的只执行命令的目标和工作目录下的实际文件出现名字冲突,另一种是提交执行makefile时的效率。
基础知识
= 延时变量,变量的值将会是整个makefile中最后被指定的值
:= 立即变量,覆盖之前的值,变量的值决定于它在makefile中的位置
?= 是如果没有被赋值过就赋予等号后面的值
+= 是添加等号后面的值
$< 第一个依赖文件的名称
$? 所有的依赖文件,以空格分开,这些依赖文件的修改日期比目 标的创建日期晚
$@ 目标的完整名称
$^ 所有的依赖文件,以空格分开,不包含重复的依赖文件。
GNU Make 使用手册https://blog.csdn.net/xiewenhao12/article/details/69388725