数码相框——4、 编写通用的Makefile

makefile的介绍和规则在博客 《由浅入深写一个makefile文件》里
from:https://www.cnblogs.com/lidabo/p/4521123.html

1、子目录里的makefile
在这里插入图片描述
在这里插入图片描述
在每个子目录文件夹里都写一个makefile

以encoding文件夹里的makfile为例:

obj-y += ascii.o
obj-y += encoding_manager.o
obj-y += utf-16be.o
obj-y += utf-16le.o
obj-y += utf-8.o

如果子目录encoding里还有个文件夹 比如test
则加一行:

obj-y += test/

小技巧 在UltraEdit里改成列模式,obj-y += 就可以只输入一次了

2、顶层目录的makefile

export 是用来提供该子目录makefile(sub make)中访问的,同一级的另外一个makefile中,是无法访问/得到的。

#----------------------------------------------指定编译工具链---------------------------------------------------
CROSS_COMPILE = arm-linux-  #交叉编译工具 没有就不填
AS		= $(CROSS_COMPILE)as
LD		= $(CROSS_COMPILE)ld		#链接工具(地址连接)https://blog.csdn.net/xungjhj/article/details/70847214
CC		= $(CROSS_COMPILE)gcc
CPP		= $(CC) -E
AR		= $(CROSS_COMPILE)ar		#打包工具
NM		= $(CROSS_COMPILE)nm

STRIP		= $(CROSS_COMPILE)strip	#优化工具
OBJCOPY		= $(CROSS_COMPILE)objcopy
OBJDUMP		= $(CROSS_COMPILE)objdump

export AS LD CC CPP AR NM
export STRIP OBJCOPY OBJDUMP

CFLAGS := -Wall -O2 -g #编译器参数
CFLAGS += -I $(shell pwd)/include 		#指定编译器头文件(根据实际项目手动修改)
										#shell pwd的意思是执行shell的pwd命令

LDFLAGS := -lm -lfreetype 				#指定编译器链接库(根据实际项目手动修改)

export CFLAGS LDFLAGS #将定义的变量导出来,方便其他makefile使用

TOPDIR := $(shell pwd)	#获得当前程序的顶层目录
export TOPDIR			#输出顶层目录

TARGET := show_file  #编译后的程序名(根据实际项目手动修改)

#-------------------------顶层要生成的.o文件以及顶层文件夹(根据实际项目手动修改)------------------
obj-y += main.o
obj-y += display/ 
obj-y += draw/
obj-y += encoding/
obj-y += fonts/

#--------------------------------------------顶层的第一个规则(默认规则)-----------------------------------------
all : 
	make -C ./ -f $(TOPDIR)/Makefile.build #-C 生成.o文件 -f进入当前目录,使用顶层的makefile.build进行编译
	$(CC) $(LDFLAGS) -o $(TARGET) built-in.o #将编译好的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)
	

在这里插入图片描述
优先进入最底层的test

3、顶层目录的makefile.build


$(filter PATTERN…,TEXT)
函数名称:过滤函数—filter。
函数功能:过滤掉字串“TEXT”中所有不符合模式“PATTERN”的单词,保留所
有符合此模式的单词。

filter-out ---->不匹配


NEW = $(patsubst “%.c”, “%.s”, ${SRC})
函数功能:字符串替换
https://blog.csdn.net/myxmu/article/details/8588147


$(foreach < var >, < list > ,< text >)

这个函数的意思是,把参数< list >;中的单词逐一取出放到参数< var >;所指定的变量中,然后再执行< text>;所包含的表达式。每一次< text >;会返回一个字符串,循环过程中,< text >;的所返回的每个字符串会以空格分隔,最后当整个循环结束时,< text >;所返回的每个字符串所组成的整个字符串(以空格分隔)将会是foreach函数的返回值。

所以,< var >;最好是一个变量名,< list >;可以是一个表达式,而< text >;中一般会使用< var >;这个参数来依次枚举;中的单词。举个例子:

    names := a b c d
    files := $(foreach n,$(names),$(n).o)

PHONY := __build		 #定义一个PHONY变量
__build:				 #开头说明__build伪目标,使其成为Makefile.build的第一个目标


obj-y :=				 #定义当前目录的目标变量,初始值为空
subdir-y :=				#定义当前目录的子目录变量,初始值为空

include Makefile		 #将当前目录的Makefile包含进来,初始化obj-y


# 假设obj-y := a.o b.o c/ d/ 那如何取出c/ d/
# ↓↓↓↓↓↓↓↓↓↓↓↓↓↓
# $(filter %/, $(obj-y))   : c/ d/ --> c d
# __subdir-y  : c d
# subdir-y    : c d
__subdir-y	:= $(patsubst %/,%,$(filter %/, $(obj-y)))#筛选出当前目录的目标变量中的子目录,然后将%/ 替换成%
subdir-y	+= $(__subdir-y)

# subdir_objs: c/built-in.o d/built-in.o
subdir_objs := $(foreach f,$(subdir-y),$(f)/built-in.o) #对于subdir-y里面的每一个值(目录),增加一个相应的目录/built-in.o的变量值

# cur_objs: a.o b.o
cur_objs := $(filter-out %/, $(obj-y)) #过滤到%/的文件,得到obj-y中的.o文件
dep_files := $(foreach f,$(cur_objs),.$(f).d) #取出依赖文件,赋值给dep_file #dep_files: .a.d .b.d
dep_files := $(wildcard $(dep_files)) #判断依赖文件是否存在

ifneq ($(dep_files),)  #根据依赖文件名,判断依赖文件是否存在,存在就包含就来
  include $(dep_files)
endif


PHONY += $(subdir-y)  #将$(subdir-y)也加入到变量PHONY中

--------------------------------------------Makefile. build的第一个规则--------------------------------------------------------------

__build : $(subdir-y) built-in.o #第一个规则

$(subdir-y):   #第一个规则的第一个依赖规则
	make -C $@ -f $(TOPDIR)/Makefile.build #依次进入该子目录变量里面存储的值,使用的Makefile.build进行编译

built-in.o : $(cur_objs) $(subdir_objs)  #第一个规则的第二个依赖规则
	$(LD) -r -o $@ $^    #该规则的命令:将该目录下的.o和$(subdir_obj)打包成built-in.o文件

dep_file = .$@.d

%.o : %.c
	$(CC) $(CFLAGS) -Wp,-MD,$(dep_file) -c -o $@ $<  #用于将目录下所有的.c文件编译成.o文件
	
.PHONY : $(PHONY) #将PHONY声明为伪目标

4、总结

本程序的Makefile分为3类:

  1. 顶层目录的Makefile
  2. 顶层目录的Makefile.build
  3. 各级子目录的Makefile

一、各级子目录的Makefile:
它最简单,形式如下:
obj-y += file.o
obj-y += subdir/

"obj-y += file.o"表示把当前目录下的file.c编进程序里,
"obj-y += subdir/"表示要进入subdir这个子目录下去寻找文件来编进程序里,是哪些文件由subdir目录下的Makefile决定。

注意: "subdir/“中的斜杠”/"不可省略

二、顶层目录的Makefile:
它除了定义obj-y来指定根目录下要编进程序去的文件、子目录外,主要是定义工具链、编译参数、链接参数──就是文件中用export导出的各变量。

三、顶层目录的Makefile.build:
这是最复杂的部分,它的功能就是把某个目录及它的所有子目录中、需要编进程序去的文件都编译出来,打包为built-in.o
详细的讲解请看视频。

四、怎么使用这套Makefile:
1.把顶层Makefile, Makefile.build放入程序的顶层目录
2.修改顶层Makefile
2.1 修改工具链
2.2 修改编译选项、链接选项
2.3 修改obj-y决定顶层目录下哪些文件、哪些子目录被编进程序
2.4 修改TARGET,这是用来指定编译出来的程序的名字

  1. 在各一个子目录下都建一个Makefile,形式为:
    obj-y += file1.o
    obj-y += file2.o
    obj-y += subdir1/
    obj-y += subdir2/

  2. 执行"make"来编译,执行"make clean"来清除,执行"make distclean"来彻底清除

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值