一个通用的Makefile(二)
1、各级子目录的Makefile:
- obj-y += file.o
- obj-y += subdir/
“obj-y += file.o” 表示把当前目录下的file.c编进程序里。
“obj-y += subdir/”表示进入subdir这个子目录下去寻找文件来编进子程序中;
2、顶层目录的Makefile:
CROSS_COMPILE = #如果要交叉编译的话,就是:CROSS_COMPILE = arm-linux-
AS = $(CROSS_COMPILE)as
LD = $(CROSS_COMPILE)ld
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导出来,后面的子目录就能用:
export STRIP OBJCOPY OBJDUMP
CFLAGS := -Wall -O2 -g
CFLAGS += -I $(shell pwd)/include -I 。。。。 # -I 指定到哪个目录去搜索头文件。
LDFLAGS := -lm 。。。。。
export CFLAGS LDFLAGS #把这两个也导出来。
TOPDIR := $(shell pwd) #顶层目录
export TOPDIR
TARGET := show_file #目标
- obj-y += main.o
- obj-y += 目录名如package/
- obj-y += framework/
all :
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)
我们这个工程顶层有:main.c,还有package,framework等子目录
framwork子目录下又有libs、manager、services等子目录;
编译过程:
Makefile是先从子目录下开始执行的:
1> 执行顶层目录的makefile程序时,先进入顶层目录,发现有些文件和目录,将会进入如DSVICICOMSVC/
2> 进入子目录后,又会发现又有子目录的makefile,DSVICICOMSVC、DSVICICOMMGR,执行子目录的makefile;
3> 把test.c编译成test.o,把test目录下的.o文件打包成build_in.o
4> 经过多个子目录后,回到顶层目录.把main.c 编译成main.o ,并与各个子目录的build-in.o打包成最终的build-in.o.
make -C ./ -f Makefile.build
3、顶层目录的Makefile.build:
这是最复杂的部分,它的功能就是把某个目录及它的所有子目录中、需要编进程序去的文件都编译出来,打包为built-in.o;
PHONY := __build #假目标
__build:
obj-y :=
subdir-y :=
include Makefile #包含当前目录的makefile,才知道目标是哪些目标和目录
# obj-y := a.o b.o c/ d/
# $(filter %/, $(obj-y)) : c/ d/
# __subdir-y : c d
# subdir-y : c d
__subdir-y := $(patsubst %/,%,$(filter %/, $(obj-y)))
subdir-y += $(__subdir-y)
# c/built-in.o d/built-in.o
subdir_objs := $(foreach f,$(subdir-y),$(f)/built-in.o)
# a.o b.o
cur_objs := $(filter-out %/, $(obj-y))
dep_files := $(foreach f,$(cur_objs),.$(f).d) #(foreach var,list,text) 结果是由空格隔开的‘text’ 在‘list’中多次扩展的字组成的新的‘list’
dep_files := $(wildcard $(dep_files))
ifneq ($(dep_files),)
include $(dep_files)
endif
PHONY += $(subdir-y)
__build : $(subdir-y) built-in.o
$(subdir-y):
make -C $@ -f $(TOPDIR)/Makefile.build
built-in.o : $(cur_objs) $(subdir_objs)
$(LD) -r -o $@ $^ #打包
dep_file = .$@.d
%.o : %.c
$(CC) $(CFLAGS) -Wp,-MD,$(dep_file) -c -o $@ $<
.PHONY : $(PHONY)
4、怎么使用这套Makefile:
1.把顶层Makefile, Makefile.build放入程序的顶层目录
2.修改顶层Makefile
2.1 修改工具链
2.2 修改编译选项、链接选项
2.3 修改obj-y决定顶层目录下哪些文件、哪些子目录被编进程序
2.4 修改TARGET,这是用来指定编译出来的程序的名字
3. 在各一个子目录下都建一个Makefile,
形式为:
obj-y += file1.o
obj-y += file2.o
obj-y += subdir1/
obj-y += subdir2/
执行"make"来编译,执行"make clean"来清除,执行"make distclean"来彻底清除
相关文章
- PreSTU:一个专门为场景文本理解而设计的简单预训练模型
- 常遇到读多写少,教你用ReadWriteLock实现一个通用的缓存中心
- 基于X86平台的PC机通过网络发送一个int(32位)整数的字节顺序
- 一个程序员水平的高低
- 14 亿身份泄露曝光,一个垃圾邮件帝国的覆灭
- 一个资深数据人对数据挖掘解读
- 一个完整和全面的云服务器安全方案是什么样子的?
- 如何设计并实现一个通用的应用运维管控平台
- Salesforce“一个平台”战略整合Einstein、Quip和IoT
- EF5+MVC4系列(5) 删除的方法 1:系统推荐的先查询后remove删除的方法 2:自己new一个包含主键的类,然后 attach附加 remove删除;3:使用db.Entry 修改状态删除4:EntityState的几种状态
- 在 .NET 中开发基于 Chrome 内核的浏览器-创建一个简单浏览器
- ios怎样在一个UIImageButton的里面加一些自己定义的箭头
- 阿里在职5年,一个女测试工师的坎坷之路
- python logging一个通用的使用模板
- 我的一个PLSQL函数 先查询再插入数据库的函数 动态SQL拼接查询条件、通用游标、记录定义(封装部分查询字段并赋值给游标)、insert select 序列、常量【我】
- 一个简单的通用Makefile实现
- 双缓冲绘图和窗口控件的绘制——ATL ActiveX 窗口控件生成向导绘制代码OnDraw的一个错误 .
- Android 一个绚丽的loading动效分析与实现!
- mysql 5.7多源复制(用于生产库多主库合并到一个查询从库)
- 一个通用的makefile(一)
- 一个简单的通用Makefile实现