通用应用程序makefile

顶层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

猜你喜欢

转载自blog.csdn.net/weixin_43542305/article/details/86069440
今日推荐