通用makefile是如何炼成的(VIII)
来源:互联网 发布:js 小于或等于 编辑:程序博客网 时间:2024/06/06 00:51
停在这里不敢走下去, 让悲伤无法上演
下一页你亲手写上的离别, 由不得我拒绝
这条路我们走得太匆忙, 拥抱着并不真实的欲望, 来不及等不及回头欣赏
“
(摘自《步步惊心 》片尾曲 《三寸天堂》)
走到这里,实际上我们的makefile框架已经是搭得差不多了。这一路小跑过来,感觉一切都很美好,实际上我想,我们只是太匆忙,来不及细细回想。
如果真的回首详观,各种琐碎细节会让你崩溃。
无论如何,该面对的终是要面对的
第一个工作是,让我们的module.mk更像是一个模块mk,为此引入MODULE_NAME, MODULE_PATH. 这两项结合起来,以后也可以作为module的唯一标识。
hello模块的module.mk
# module.mk#MODULE_PATH:= $(call current_path)MODULE_NAME:= hello
获取模块路径时,我用了一个小小的技巧。很多书上都有提到,原理是利用了makefile的环境变量MAKEFILE_LIST.
这里简单贴一下实现代码
define current_path
$(patsubst %/,%, \
$(dir $(word $(words $(MAKEFILE_LIST)), $(MAKEFILE_LIST))))
endef
D第二个我们要做的琐事是调整一些路径。现在的makefile,编译生成的中间文件还是和源文件混杂在一起的,为了美观和方便版本控制,我们把它们集中到INTERMEDIATE_OBJ_PATH,对其他的一些自动生成的文件,也是类似处理。
做这项工作时注意要”步步惊心“, 还好我们是从一开始就知道故事结局的,就是要正确编译得到可执行文件。
另外,不同的人,可以对路径的处理不同。例如,为了区分不同产品,不同平台,有些同学喜欢为各个产品、各个平台分别建立文件夹,构成深目录层次, 有些同学喜欢采用 <product>--<platform>这样的浅层次的目录结构。
这里选择了浅目录形式,因为大部分情况下我们是不需要多平台的。
这里为了方便测试,特意引入了产品信息TEST, 平台信息X86
所有的路径信息,统一集中在paths/path.mk。这里引入两个重要概念TARGET_PRODUCT, TARGET_PLATFORM,这是由make命令行参数传入的。这里为了测试方便,直接在脚本中写入了。
# path.mk## 目前的路径策略,根目录下建立out,bin,lib,src,build五大目录,out目录下可以再建立bin.lib,obj目录PROJECT_OUT_PATH := outPROJECT_BIN_PATH := binPROJECT_LIB_PATH := libTARGET_PRODUCT := TESTTARGET_PLATFORM:= X86ifneq "$(TARGET_PRODUCT)" "" PRODUCT_SUFFIX := $(TARGET_PRODUCT)else PRODUCT_SUFFIX := endififneq "$(TARGET_PLATFORM)" "" PRODUCT_SUFFIX := $(PRODUCT_SUFFIX)-$(TARGET_PLATFORM)endif## 产品和平台附加的路径后缀不为空,就以此建立子目录ifneq "$(PRODUCT_SUFFIX)" ""PRODUCT_OUT_PATH := $(PROJECT_OUT_PATH)/$(PRODUCT_SUFFIX)PRODUCT_BIN_PATH := $(PROJECT_BIN_PATH)/$(PRODUCT_SUFFIX)PRODUCT_LIB_PATH := $(PROJECT_LIB_PATH)/$(PRODUCT_SUFFIX)elsePRODUCT_OUT_PATH := $(PROJECT_OUT_PATH)PRODUCT_BIN_PATH := $(PROJECT_BIN_PATH)PRODUCT_LIB_PATH := $(PROJECT_LIB_PATH)endifINSTALL_PATH := $(PRODUCT_BIN_PATH)INTERMEDIATE_PATH := $(PRODUCT_OUT_PATH)INTERMEDIATE_OBJS_PATH:=$(INTERMEDIATE_PATH)/objINTERMEDIATE_LIB_PATH:=$(INTERMEDIATE_PATH)/libINTERMEDIATE_BIN_PATH:=$(INTERMEDIATE_PATH)/bin$(info INSTALL_PATH=$(INSTALL_PATH))$(info INTERMEDIATE_PATH=$(INTERMEDIATE_PATH))
配置后,注意同步调整targets目录下的mk文件,利用object.mk
# object.mk## 从源文件列表中分别提取出C文件和C++文件C_OBJS := $(patsubst %.c, $(INTERMEDIATE_OBJS_PATH)/%.o, $(filter %.c, $(SRC_FILES)))CPP_OBJS:= $(patsubst %.cpp, $(INTERMEDIATE_OBJS_PATH)/%.o, $(filter %.cpp, $(SRC_FILES)))OBJS := $(C_OBJS) $(CPP_OBJS)DEPS := $(OBJS:.o=.d)## -MMD 可以用于自动生成头文件依赖关系$(INTERMEDIATE_OBJS_PATH)/%.o : %.cpp$(hide)$(MAKEDIR) $(dir $@)$(CXX) $(CPPFLAGS) $(CXXFLAGS) -MMD -MP -MF"$(@:%.o=%.d)" -MT"$@" -MT"$(@:%.o=%.d)" -c "$<" -o "$@" $(INTERMEDIATE_OBJS_PATH)/%.o : %.c$(hide)$(MAKEDIR) $(dir $@)$(CC) $(CPPFLAGS) $(CFLAGS) -MMD -MP -MF"$(@:%.o=%.d)" -MT"$@" -MT"$(@:%.o=%.d)" -c "$<" -o "$@" ....
# executable.mk### 编译生成obj文件的通用规则include build/targets/object.mk## 如果目标未定义,则默认是out/bin/<module-name>ifeq "$(TARGET)" "" TARGET := $(INTERMEDIATE_BIN_PATH)/$(MODULE_NAME)endif。。。。
今天的工作到此为止。主要是琐事缠身
- 通用makefile是如何炼成的(VIII)
- 通用makefile是如何炼成的(II)
- 通用makefile是如何炼成的(III)
- 通用makefile是如何炼成的(IV)
- 通用makefile是如何炼成的(V)
- 通用makefile是如何炼成的(VI)
- 通用makefile是如何炼成的(VII)
- 通用makefile是如何炼成的(I)
- 通用makefile是如何炼成的(XI)--最后的完结篇,envsetup.sh
- 通用makefile是如何炼成的(Ⅸ)整体框架
- 通用makefile是如何炼成的(X)—— 导入单元测试
- vmlinux是如何炼成的--kernel makefile
- vmlinux是如何炼成的--kernel makefile
- makefile 必知必会以及Makefile是怎样炼成的
- 好口才是如何炼成的!
- DBA是如何炼成的
- 一个APK是如何炼成的
- 好论文是如何炼成的
- 小鑫の日常系列故事(七)——小纸条
- 集群监控工具ganglia
- 程序猿找工作必练内功:排序算法大总结(三)——堆排序算法
- C#学习4
- 进程的控制
- 通用makefile是如何炼成的(VIII)
- ego 代码所学
- 使用wscript.exe实现kill某个进程,用户无任何感知,不会弹出任何命令的执行窗口
- Android - 文件读写操作 总结
- newInstance() 的参数版本与无参数版本详解
- java.lang.Class.getConstructor(Class[] parameterTypes)
- java实现文件上传下载
- 为什么VC经常输出烫烫烫烫烫烫烫烫(内存在不同状态下默认填充的字符)
- Text编码格式