Makefile研究(二)—— 完整可移植性模板
转自:http://blog.csdn.net/jundic/article/details/17676461
一直想写一个很全很好移植的Makefile模板,我觉得一个完整makefile 应该包含如下内容。
1、可以编译成 动态库.a 静态库.so 或者是直接编译成可执行文件。
2、编译可执行文件可以指定宏 ,自有添加头文件,指定链接的各种库
3、要能过自动生成依赖关系,能准确地捕捉到任何依赖文件的改动。
4、如果是嵌入式系统应该还要指定链接脚本(这里暂不考虑)
下面是我写的一个具备上面1-3点的makefile
- # Generic Makefile for C/C++ Program
- # Author:
- # Description:
- # This is an easily customizable makefile template. The purpose is to
- # provide an instant building environment for C/C++ programs.
- #
- # It searches all the C/C++ source files in the specified directories,
- # makes dependencies, compiles and links to form an executable.
- #
- # Besides its default ability to build C/C++ programs which use only
- # standard C/C++ libraries, you can customize the Makefile to build
- # those using other libraries. Once done, without any changes you can
- # then build programs using the same or less libraries, even if source
- # files are renamed, added or removed. Therefore, it is particularly
- # convenient to use it to build codes for experimental or study use.
- #
- # GNU make is expected to use the Makefile. Other versions of makes
- #
- .PHONY : all clean
- # Curstomer build output file directory and filename
- EXES =
- DIR_EXES =
- DIR_OBJS =
- DIR_DEPS =
- DIR_INCS =
- LINK_LIBS =
- LIBS_TYPE = dynamic
- #LIBS_TYPE = static
- DIR_LIBS =
- LIBS =
- # Top directory Makefile
- CURDIR = $(shell pwd)
- # The C program compiler
- COPTION = -O2
- MACRO = -DDEBUGALL
- CFLAGS += -g -werror $(MACRO) $(COPTION)
- CC = gcc
- AR = ar
- ARFLAGES = crv
- # default execute output directory
- ifeq ($(DIR_EXES),)
- DIR_EXES = $(TOPDIR)/build/out
- endif
- # defaulet libaray creat directory
- ifeq ($(DIR_LIBS),)
- DIR_LIBS = $(TOPDIR)/build/libs
- endif
- # directory
- DIRS = $(DIR_OBJS) $(DIR_DEPS) $(DIR_EXES) $(DIR_LIBS)
- # include directory
- ifneq ($(DIR_INCS),"")
- DIR_INCS := $(strip $(DIR_INCS))
- DIR_INCS := $(addprefix -I,$(DIR_INCS))
- endif
- # build execute file
- ifneq ($(EXES),)
- EXES := $(addprefix $(DIR_EXES)/,$(EXES))
- RMS += $(EXES)
- DIR_LIBS := $(strip $(DIR_LIBS))
- DIR_LIBS := $(addprefix -L,$(DIR_LIBS))
- endif
- # build libaray file
- ifneq ($(LIBS),"")
- LIBS := $(addprefix $(DIR_LIBS)/,$(LIBS))
- RMS += $(LIBS)
- endif
- # default source code file directory
- ifeq ($(DIR_SRCS),)
- DIR_SRCS = .
- endif
- # scan source code
- SRCS = $(wildcard $(DIR_SRCS)/*.c)
- OBJS = $(patsubst %.c, %.o,$(notdir $(SRCS)))
- OBJS := $(addprefix $(DIR_OBJS)/,$(OBJS))
- RMS += $(OBJS) $(DIR_OBJS)
- # dependant file
- DEPS = $(patsubst %.c, %.dep,$(notdir $(SRCS)))
- DEPS := $(addprefix $(DIR_DEPS)/,$(DEPS))
- RMS += $(DEPS) $(DIR_DEPS)
- # build execute file
- ifneq ($(EXES),"")
- all : $(EXES)
- endif
- # build library
- ifneq ($(LIBS),"")
- all : $(LIBS)
- endif
- # link libs name
- ifneq ($(LINK_LIBS),"")
- LINK_LIBS := $(strip $(LINK_LIBS))
- LINK_LIBS := $(addprefix -l,$(LINK_LIBS))
- endif
- # include dependent files
- ifneq ($(MAKECMDGOALS), clean)
- -include $(DEPS)
- endif
- $(DIRS):
- mkdir -p $@
- # creat execute file
- $(EXES) : $(DIR_OBJS) $(OBJS) $(DIR_EXES)
- $(CC) $(DIR_INCS) $(CFLAGES) -o $@ $(OBJS) $(DIR_LIBS) $(LINK_LIBS)
- # creat libaray file
- $(LIBS) : $(DIR_LIBS) $(DIR_OBJS) $(OBJS)
- # library type is static
- ifeq ($(LIB_TYPE),static)
- $(AR) $(ARFLAGS) $@ $(OBJS)
- endif
- # library type is dynamic
- ifeq ($(LIB_TYPE),dynamic)
- $(CC) -shared -o $@ $(OBJS)
- endif
- # creat object file
- $(DIR_OBJS)/%.o : $(DIR_SRCS)/%.c
- @echo "source files:" $<
- @echo "object files:" $@
- ifeq ($(LIB_TYPE),static)
- $(CC) $(DIR_INCS) $(CFLAGES) -o $@ -c $<
- else
- $(CC) $(DIR_INCS) $(CFLAGES) -fPIC -o $@ -c $<
- endif
- # creat depandant file
- $(DIR_DEPS)/%.dep : $(DIR_SRCS)/%.c $(DIR_DEPS)
- @echo "creating depend file ..." $@
- @set -e;\
- $(CC) $(DIR_INCS) -MM $< > $@.tmp;\
- sed 's,$∗\.o[ :]*,$(DIR_OBJS)/\1.o $@ : ,g' < $@.tmp > $@
- clean:
- rm -rf $(RMS)
对整个makefle 分析如下:
1、line 23-33
是当我们要将源代码编译成可执行文件还是静态库,还是动态库在这里配置就可以
DIR_OBJS 为目标文件输出目录,DIR_DEPS为依赖文件输出目录,DIR_INC为包含头文件的目录。
LINK_LIBS 为当生成可执行文件如果需要链接外面的库,则在这里指定库的名字。
DIR_LIBS 为库的路径,LIBS 为库的 libXX.so 或 libXX.a 格式的名字。
2、line 38 - 34
为gcc 编译相关
COPTION 为编译优化等选项
MACRO 为编译时定义的宏配置
3、line 44 - 109
这些都是根据前面是生成可执行文件还是库的对应的输出配置,以及目标依赖关系
4、line 19 - 121
生成可执行文件的语句
5、line 123 - 133
生成静动态库的语句
6、line 146 - 150
这可以是整个makefile 的关键所在,这是生成依赖文件的地方,有人会问编译代码不就是将.c --> .o ----> 可执行文件么,表面上是这样。
但实际上很多时候我们编译c但还包含了.h 或者是其他配置文件,当这时候.h和配置文件改变了,但当已经完整make后,但make却没检查到这种改变,导致修改后的文件无法编译进去,这时候只能make clean 才能make 。大工程中这个明显浪费很多时间。其实不能怪make不够只能,那是因将这些配置文件作为依赖关系包含进去。而makefile 只检查目标文件所依赖的文件的更新。
在gcc 中有一个MM 很好地解决这个问题,假如 test.c 除了包含了头文件还包含了test.h test1.h 那么
gcc -MM test.c
结果为 test.o : test.c test.h test1.h
sed 命令应用有点复杂但他的作用加上必要的路径,输出到test.dep文件中,这个方法在uboot 和 android ,Linux 编译系统中使用的。
这样一个比较完整的单目录结果makefile 就写好,我们可以根据自己的需要配置成是生成可执行文件还是库,很方便移植到不是很复杂的应用当中去。
Makefile研究(二)—— 完整可移植性模板的更多相关文章
- Fiddler实战深入研究(二)
Fiddler实战深入研究(二) 阅读目录 Fiddler不能捕获chrome的session的设置 理解数据包统计 请求重定向(AutoResponder) Composer选项卡 Filters选 ...
- thinkphp二维数组模板输出方法
thinkphp二维数组模板输出方法 先写个记录,有空再整理发上来
- (转载)Fiddler实战深入研究(二)
原文来源于:http://www.cnblogs.com/tugenhua0707/p/4637771.html,作者:涂根华 !个人觉得文章写的特别好,故收藏于此,感谢原作者的分享 Fiddler实 ...
- Fiddler实战深入研究(二)[转载]
Fiddler实战深入研究(二) 阅读目录 Fiddler不能捕获chrome的session的设置 理解数据包统计 请求重定向(AutoResponder) Composer选项卡 Filters选 ...
- 彻底掌握Makefile(二)
彻底掌握Makefile(二) 前言 在前面的文章彻底掌握Makefile(一)当中,我们简要的介绍了一些常见的makefile使用方法,在本篇文章当中我们将继续介绍一些makefile当中的常见用法 ...
- Makefile研究 (一)—— 必备语法
摘自:http://blog.csdn.net/jundic/article/details/17535445 参考文档:http://blog.csdn.net/wrx1721267632/arti ...
- 二、T4模板
上文带大家见识了下T4,这里呢开始介绍T4模板有关的内容.关于T4模板介绍和使用网上一搜一箩筐,想深入研究的可以自行去找些资料,这里只介绍接下来我们需要使用的一些知识,不会面面俱到的讲T4模板所有的知 ...
- C++的开源跨平台日志库glog学习研究(二)--宏的使用
上一篇从整个工程上简单分析了glog,请看C++的开源跨平台日志库glog学习研究(一),这一篇对glog的实现代码入手,比如在其源码中以宏的使用最为广泛,接下来就先对各种宏的使用做一简单分析. 1. ...
- makefile编写---单个子目录编译模板
经过这次地库项目之后,虽然时间不久,跟团队在一起,虽然队员不一定在技术上有过人之处,但是来自大公司的员工,在工具使用和代码规范方面还是有点可鉴之处,在搭建主控模块是,就得面临makefile编写,因为 ...
随机推荐
- 【程序猿联盟】官网上线啦!coderunity.com
wx_fmt=jpeg" alt="" style="max-width:100%; height:auto!important"> 内容简单介 ...
- 通过代码实现自动判断是手机端还是PC端跳转
<!-- 2017/09/13 跳转手机页面 start by 小鬼PSer --> <meta name="mobile-agent" content=&quo ...
- final、finally、三个关键字的区别
一 final 如果一个类被声明为final,意味着它不能再派生出新的子类,不能作为父类被继承.因此一个类不能既被声明为 abstract的,又被声明为final的.将变量或方法声明为final,可以 ...
- Android Handle,Looper,Message消息机制
尊重原创,转载请标明出处 http://blog.csdn.net/abcdef314159 我们知道在Android中更新UI都是在主线程中,而操作一些耗时的任务则须要在子线程中.假设存在多个 ...
- java使用ftp局域网内多线程上传图片过慢
多线程ftp上传文件时候,图片上传很慢,调试和查询资料发现主要在:storeFile方法 解决方案如下: FTPClient fc设置setBufferSize 可以根据内存大小适当设置大点的缓冲区: ...
- UIAutomator 2
UIAutomator 2 While the API remains almost the same, the internal implementation has changed and we ...
- MongoDB学习笔记(1):MongoDB的安装和说明
MongoDB学习笔记(1):MongoDB的安装和说明 快速开始 下载地址 官网下载: https://www.mongodb.com/download-center?jmp=nav#communi ...
- Android Weekly Notes Issue #252
Android Weekly Issue #252 April 9th, 2017 Android Weekly Issue #252. 本期内容: 变化的渐变背景实现; Kotlin 1.1特性; ...
- malloc、calloc、realloc和alloca各种的区别
需要先包含头文件 #include"malloc.h" malloc是标准的在堆中开辟新的空间 比如 char *pt=(char *)malloc(10*sizeof(char) ...
- MSP430G2553需要注意的一些参数
转载请注明出处:http://www.cnblogs.com/connorzx/p/3632952.html 把一些具体芯片信息列出来,以便于查看. 1.时钟 (1)MCLK,Master Clock ...