转自: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研究(二)—— 完整可移植性模板的更多相关文章

  1. Fiddler实战深入研究(二)

    Fiddler实战深入研究(二) 阅读目录 Fiddler不能捕获chrome的session的设置 理解数据包统计 请求重定向(AutoResponder) Composer选项卡 Filters选 ...

  2. thinkphp二维数组模板输出方法

    thinkphp二维数组模板输出方法 先写个记录,有空再整理发上来

  3. (转载)Fiddler实战深入研究(二)

    原文来源于:http://www.cnblogs.com/tugenhua0707/p/4637771.html,作者:涂根华 !个人觉得文章写的特别好,故收藏于此,感谢原作者的分享 Fiddler实 ...

  4. Fiddler实战深入研究(二)[转载]

    Fiddler实战深入研究(二) 阅读目录 Fiddler不能捕获chrome的session的设置 理解数据包统计 请求重定向(AutoResponder) Composer选项卡 Filters选 ...

  5. 彻底掌握Makefile(二)

    彻底掌握Makefile(二) 前言 在前面的文章彻底掌握Makefile(一)当中,我们简要的介绍了一些常见的makefile使用方法,在本篇文章当中我们将继续介绍一些makefile当中的常见用法 ...

  6. Makefile研究 (一)—— 必备语法

    摘自:http://blog.csdn.net/jundic/article/details/17535445 参考文档:http://blog.csdn.net/wrx1721267632/arti ...

  7. 二、T4模板

    上文带大家见识了下T4,这里呢开始介绍T4模板有关的内容.关于T4模板介绍和使用网上一搜一箩筐,想深入研究的可以自行去找些资料,这里只介绍接下来我们需要使用的一些知识,不会面面俱到的讲T4模板所有的知 ...

  8. C++的开源跨平台日志库glog学习研究(二)--宏的使用

    上一篇从整个工程上简单分析了glog,请看C++的开源跨平台日志库glog学习研究(一),这一篇对glog的实现代码入手,比如在其源码中以宏的使用最为广泛,接下来就先对各种宏的使用做一简单分析. 1. ...

  9. makefile编写---单个子目录编译模板

    经过这次地库项目之后,虽然时间不久,跟团队在一起,虽然队员不一定在技术上有过人之处,但是来自大公司的员工,在工具使用和代码规范方面还是有点可鉴之处,在搭建主控模块是,就得面临makefile编写,因为 ...

随机推荐

  1. MongoDB资料汇总专题(转)

    原文地址:http://blog.nosqlfan.com/html/3548.html 1.MongoDB是什么 MongoDB介绍PPT分享 MongoDB GridFS介绍PPT两则 初识 Mo ...

  2. sap保存时小写字母自己主动转大写字母的解决方法

    在实际应用中.ABAP保存数据到后台数据库表中时.会自己主动把前台输入的小写字母自己主动转换为大写字母来保存.有时候客户可能不须要转换,就须要用到以下的方法:       1.找到相应字段的Data ...

  3. 在mac下搭建Apacheserver

    Apache作为最流行的Webserver端软件之中的一个.它的长处与地位不言而喻.以下介绍下在mac下搭建Apacheserver的步骤: (1)"前往" –>" ...

  4. HttpURLConnection访问网络

    HttpURLConnection是一个抽象类,获取HttpURLConnection对象HttpURLConnection urlConnection=new URL(http://www.baid ...

  5. ORA-02298: 无法验证 (PNET.POST_CLOB_FK) - 未找到父项关键字

    在运行以下语句的时候,报错如下: ALTER TABLE PN_POST ADD CONSTRAINT POST_CLOB_FK FOREIGN KEY (POST_BODY_ID) REFERENC ...

  6. Masonry库的使用

    Github 简要 自动布局最重要的是约束:UI元素间关系的数学表达式.约束包括尺寸.由优先级和阈值管理的相对位置.它们是添加剂,可能导致约束冲突 .约束不足造成布局无法确定 .这两种情况都会产生异常 ...

  7. Oracle Meger into 函数

    Oracle 在 9i 引入了 merge 命令, 通过这个 merge 能够在一个SQL 语句中对一个表同时执行 inserts 和 updates 操作.Merge into 可以实现用 B 表来 ...

  8. SPOJ7258

    传送门 这题可以参考平衡树求第k大的过程,需要预处理一下从当前节点往下走能走出多少个子串. 原本准备存个图用反向的topsort,发现极为麻烦,看了别人的代码后发现,他们按step大小用了基排,省了很 ...

  9. 理解数学公式与numpy矩阵运算

    1.矩阵的初始化 (1)创建一个 3*5的全0矩阵和全1矩阵 import numpy as np myzero = np.zeros([3,5]) print myzero myones = np. ...

  10. js 分享代码--完整示例代码

    <div class="bdsharebuttonbox" data-tag="share_1"> <a class="bds_ms ...