以一个样例開始,文件文件夹结构例如以下

---------(当前文件夹)-----------main.c

                  |

                  |--------add文件夹

                  |               |-------add_int.cpp

                  |               |-------add_float.cpp

                  |

                  |--------sub文件夹

                                 |--------sub_int.cpp

                                 |--------sub_float.cpp



makefile文件例如以下:

#example 

CXX=g++

CXXFLAGS=-Iadd -Isub

OBJSDIR=.objs

VPATH=add:sub:.

OBJS=add_int.o add_float.o sub_int.o sub_float.o \

main.o

TARGET=cacu



$(TARGET):$(OBJSDIR) $(OBJS)

$(CXX) $(OBJSDIR)/*.o $(CXXFLAGS) -o $@

$(OBJS):%.o:%.cpp

$(CXX) $< $(CXXFLAGS) -c -o $(OBJSDIR)/$@

$(OBJSDIR):

mkdir -p ./$@

.PHONY:clean

clean:

-$(RM) $(TARGET)

-$(RM) $(OBJSDIR)/*.o

(一)makefile的规则

规则的基本格式:

TARGET... : DEPENDES...

COMMAND

...

TARGET:规则所定义的目标。能够是Object File。也能够是运行文件。还能够是一个标签(Label)。

DEPENDES:运行此规则所必须的依赖条件。

COMMAND:规则所运行的命令(随意的shell命令)。



1.命令行必须以一个Tab键開始。

2.凝视用“#”字符。

3.用反斜杠(\)能够将较长的行分解为多行。



(二)make是怎样工作的

1.make会在当前文件夹下找名字叫“Makefile”或“makefile”的文件。

2.假设找到。它会找文件里的第一个目标文件。并把这个文件作为终于的目标文件。定义在Makefile中的目标可能会有非常多,可是第一条规则中的目标将被确立为终于的目标。假设第一条规则中的目标有非常多个,那么第一
个目标会成为终于的目标。

3.make会一层又一层地去找文件的依赖关系,直到终于编译出第一个目标文件。

比如

OBJS=add_int.o add_float.o

$(OBJS):%.o:%.cpp

$(CXX) $< -c -o $@

上面makefile仅仅会编译add_int.cpp,假设要编译全部。能够加一个标签。

OBJS=add_int.o add_float.o

all:$(OBJS)

$(OBJS):%.o:%.cpp

$(CXX) $< -c -o $@

(三)搜索路径

指定须要搜索的文件夹后,make会自己主动找到指定文件的文件夹并加入到文件上。有两种指定搜索文件夹的方法.

方法一:

VPATH=path1:path2: ...

比如

VPATH=add:sub:.

add_int.o:%.o:%.cpp

$(CXX) $< -c -o $@

会自己主动扩展成

add_int.o:add/add_int.cpp

g++ add/add_int.cpp -c -o add_int.o

方法二:

vpath <pattern> <directories>

为符合模式<pattern>的文件指定搜索文件夹<directories>。

比如:

vpath %.h ../headers

make会在“../headers”文件夹下搜索全部以“.h”结尾的文件。



(四)伪目标

.PHONY:name

当运行“make name”时一定是运行makefile中的这个伪目标,而无论是否存在一个叫name的文件。



(五)makefile中的部分提前定义变量

 变量名  含义  默认值
 CC C语言编译器的名称  cc
 CXX C++ 语言编译器的名称  g++
 CFLAGS C语言编译器的编译选项  无
 CXXFLAGS C++语言编译器的编译选项  无
 RM  删除文件程序的名称  rm -f

(六)makefile中的自己主动变量

 变量  含义
 $@  目标项中目标文件的名称
 $<  依赖项中第一个依赖文件的名称
 $^  全部不反复的依赖文件
 $*  目标文件的名称,不包括扩展名
 $?

 依赖项中,全部目标文件时间戳晚的依赖文件

(七)静态模式

 < targets ... >: < target-pattern >: < prereq-patterns ... >

<command>

target-parrtern是指明了targets的模式

prereq-parrterns是目标的依赖模式。它对target-parrtern形成的模式再进行一次依赖目标的定义。

样例:

objects = foo.o bar.o

all: $(objects)

$(objects): %.o: %.c

$(CC) -c $(CFLAGS) $<  -o $@

<target-parrtern>定义成“%.o”。意思是我们的<target>集合中都是以“.o”结尾的,而假设我们的<prereq-parrterns>定义成“%.c”,意思是对<target-parrtern>所形成的目标集进行二次定义,其计算方法是。取<target-parrtern>模式中的“%”(也就是去掉了[.o]这个结尾)。并为其加上[.c]这个结尾,形成的新集合。



(八)嵌套运行make

我们有一个子文件夹叫add。这个文件夹下有个makefile文件,来指明了这个文件夹下文件的编译规则。那么我们总控的Makefile能够这样书写:

subsystem:

cd add && $(MAKE)

等价于

subsystem:

$(MAKE) -C add

1.假设你要让上一条命令的结果应用在下一条命令时,你应该使用分号(;)分隔这两条命令。或者使用“&&”。

2.假设你要传递变量到下级Makefile中,那么你能够使用这种声明:

 export < variable ... >

须要注意的是。有两个变量,一个是SHELL。一个是MAKEFLAGS,这两个变量无论你是否export,其总是要传递到下层makefile中。

(九)变量

变量在声明时须要给予初值,而在使用时。须要给在变量名前加上“$”符号,但最好用小括号“()”或是大括号“{}”把变量给包含起来。



1.当使用一个变量来定义还有一个变量时须要注意:

foo=$(bar)

bar=hello world!

使用“=”号时。右側变量的值能够定义在文件的不论什么一处。也就是说,右側中的变量不一定非要是已定义好的值,其也能够使用后面定义的值。

bar=hello world!

foo:=$(bar)

使用":="号时,前面的变量不能使用后面的变量,仅仅能使用前面已定义好了的变量。

2.空格

nullstring:=

space:=$(nullstring) # end of the line

dir:=/foo/bar    # directory to put the frobs in

nullstring 是一个Empty变量,当中什么也没有,而我们的space的值是一个空格。採用“#”凝视符来表示变量定义的终止。

dir这个变量的值是“/foo/bar    ”,后面跟了4个空格。



3.变量的静态模式

foo:=a.o b.o c.o

bar:=$(foo:%.o=%.c)

$(bar)变量的值为“a.c b.c c.c”。



4.变量的追加

objects=main.o foo.o bar.o utils.o

objects+=another.o

(十)隐含规则

对一个目标文件是“文件名称.o”,依赖文件是“文件名称.c"的规则,能够省略其编译规则的命令行。

由于假设make找到一个whatever.o。那么whatever.c,就会是whatever.o的依赖文件。而且
cc -c whatever.c 也会被推导出来。这样就能够省略掉描写叙述.c文件和.o依赖关系的规则,而仅仅须要给出那些特定的规则描写叙述(.o目标所须要的.h文件)。



1.编译C程序的隐含规则

“filename.o”的目标的依赖目标会自己主动推导为“filename.c”,而且其生成命令是“$(CC)
–c $(CXXFLAGS) $(CFLAGS)”



2.编译C++程序的隐含规则

“filename.o”的目标的依赖目标会自己主动推导为“filename.cc”或是“filename.C”,而且其生成命令是“$(CXX)
–c $(CXXFLAGS) $(CFLAGS)”



參考:

陈皓的《跟我一起写 Makefile》http://blog.csdn.net/haoel

宋敬彬的《Linux网络编程》

makefile知识点归纳的的更多相关文章

  1. 【重走Android之路】【路线篇(二)】知识点归纳

    [重走Android之路][路线篇(二)]知识点归纳   参考:http://blog.csdn.net/xujing81/article/details/7313507   第一阶段:Java面向对 ...

  2. makefile 学习归纳

    makefile 学习归纳 一直希望 好好整理下 makefile的写法,这在linux编程界是必备技能.下面就好好的说道说道. 可以参考的大神总结 整理 makefile是供make命令执行的 脚本 ...

  3. 《零压力学Python》 之 第四章知识点归纳

    第四章(决策和循环)知识点归纳 if condition: indented_statements [ elif condition: Indented_statements] [else: Inde ...

  4. 《零压力学Python》 之 第三章知识点归纳

    第三章(第一个程序)知识点归纳 编程犹如写剧本.Python函数与剧本差别不大,你可以反复调用函数,而它每次都执行预定的“脚本”(脚本也可以指整个程序). 在Python IDLE中,真正的编程是从编 ...

  5. 《零压力学Python》 之 第二章知识点归纳

    第二章(数字)知识点归纳 要生成非常大的数字,最简单的办法是使用幂运算符,它由两个星号( ** )组成. 如: 在Python中,整数是绝对精确的,这意味着不管它多大,加上1后都将得到一个新的值.你将 ...

  6. 《零压力学Python》 之 第一章知识点归纳

    第一章(初识Python)知识点归纳 Python是从ABC语言衍生而来的 ABC语言是Guido参与设计的一种教学语言,为非专业编程人员所开发的. Python是荷兰程序员 Guido Van Ro ...

  7. Django知识点归纳总结之HTTP协议与URL

    Django复习知识点归纳总结 1.HTTP协议 ​ 超文本传输协议(Hyper Text Transfer Protocol),是用于万维网服务器与本地浏览器之间的传输超文本的传送协议. ​ HTT ...

  8. 给Java新手的一些建议----Java知识点归纳(J2EE and Web 部分)

    J2EE(Java2 Enterprise Edition) 刚出现时一般会用于开发企业内部的应用系统,特别是web应用,所以渐渐,有些人就会把J2EE和web模式画上了等号.但是其实 J2EE 里面 ...

  9. 给Java新手的一些建议----Java知识点归纳(Java基础部分)

    写这篇文章的目的是想总结一下自己这么多年来使用java的一些心得体会,主要是和一些java基础知识点相关的,所以也希望能分享给刚刚入门的Java程序员和打算入Java开发这个行当的准新手们,希望可以给 ...

随机推荐

  1. 15个nosql

    1.MongoDB 介绍 MongoDB是一个基于分布式文件存储的数据库.由C++语言编写.主要解决的是海量数据的访问效率问题,为WEB应用提供可扩展的高性能数据存 储解决方案.当数据量达到50GB以 ...

  2. hdu 4274 Spy&#39;s Work(水题)

    Spy's Work Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total ...

  3. BaiduMap_SDK_DEMO_3.0.0_for_Xamarin.Android_by_imknown

    2.4.2 已稳定, 同一时候已经放置到分支/Release 2.4.2了. 3.0.0 已开发完毕, 可是不推荐大家用于项目中, 请观望或者自己进一步调试. 个人感觉尽管3.0.0简化了开发, 可是 ...

  4. 【mysql】关于子查询的一个例子

    假设表my_tbl包含三个字段a,b,c:现在需要查询表中列a的每个不同值下的列b为最小值的记录量. 比如表记录为: a  b  c 1  3  'cd' 2  3  'nhd' 1  5  'bg' ...

  5. coco2d-x CCScrollView实现背包翻页,仅供参考

    #include "CCCGameScrollView.h" USING_NS_CC; USING_NS_CC_EXT; CCCGameScrollView::CCCGameScr ...

  6. 在mysql数据库中关于日期时间字段的处理

    在mysql数据库中关于日期时间字段的处理 在开发中,日期时间字段一般有如下几种设计 假设要获取2013-08-15日到2013-08-16日之间的记录 1. 直接使用日期时间类字段 相关sql语句如 ...

  7. [IOS]UIWebView实现保存页面和读取服务器端json数据

    如何通过viewView保存访问过的页面?和如何获取并解析服务器端发送过来的json数据?通过一个简单的Demo来学习一下吧! 操作步骤: 1.创建SingleViewApplication应用,新建 ...

  8. 彻底理解Javascript原型继承

    彻底理解Javascript原型继承 之前写过一篇Javascript继承主题的文章,这篇文章作为一篇读书笔记,分析的不够深入. 本文试图进一步思考,争取彻底理解Javascript继承原理 实例成员 ...

  9. Linux查看进程线程个数

    1.根据进程号进行查询: # pstree -p 进程号 # top -Hp 进程号 2.根据进程名字进行查询: # pstree -p `ps -e | grep server | awk '{pr ...

  10. Linux中块设备驱动程序分析

    基于<Linux设备驱动程序>书中的sbull程序以对Linux块设备驱动总结分析. 開始之前先来了解这个块设备中的核心数据结构: struct sbull_dev {         i ...