makefile基础实例讲解 分类: C/C++ 2015-03-16 10:11 66人阅读 评论(0) 收藏

时间:2023-01-06 20:49:35

一、makefile简介

定义:makefile定义了软件开发过程中,项目工程编译链、接接的方法和规则。

产生:由IDE自动生成或者开发者手动书写。

作用:Unix(MAC OS、Solars)和Linux(Red
Hat、Ubuntu)系统下由make命令调用当前目录下的makefile文件执行,可实现项目工程的自动化编译。

二、语法规则

target:prerequisites

command

其中,target为需要生成的目标,prerequisites为依赖项,command为make需要执行的命令(任意的Shell命令)。

注意:其中command前必须以tab键开始。

三、makefile内容

Makefile里主要包含了五个东西:显式规则、隐晦规则、变量定义、文件指示和注释。

1.显式规则。显式规则说明了,如何生成一个或多的的目标文件。这是由Makefile的书写者明显指出,要生成的文件,文件的依赖文件,生成的命令。

2.隐晦规则。由于我们的make有自动推导的功能,所以隐晦的规则可以让我们比较粗糙地简略地书写Makefile,这是由make所支持的。

3.变量的定义。在Makefile中我们要定义一系列的变量,变量一般都是字符串,这个有点你C语言中的宏,当Makefile被执行时,其中的变量都会被扩展到相应的引用位置上。

4.文件指示。其包括了三个部分,一个是在一个Makefile中引用另一个Makefile,就像C语言中的include一样;另一个是指根据某些情况指定Makefile中的有效部分,就像C语言中的预编译#if一样;还有就是定义一个多行的命令。有关这一部分的内容,请参考文末的参考资料。

5.注释。Makefile中只有行注释,和UNIX的Shell脚本一样,其注释是用“#”字符,这个就像C/C++中的“//”一样。如果你要在你的Makefile中使用“#”字符,可以用反斜框进行转义,如:“\#”。

四、make的工作流程

在默认的方式下,也就是我们只输入make命令,则相当于make first_objname_in_makefile。意思是生成出现在makefile中第一个目标文件。或者指明生成的目标名称,如make [objname]。

按默认方式,输入make命令,其工作方式是:

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

2.如果找到,它会找文件中的第一个目标文件(target),在上面的例子中,并把这个文件作为最终的目标文件。

3.如果target不存在,则根据target后的依赖项和command生成target。如果target已存在,则make检测target依赖项是否有修改,若修改,则跟新target。

四、实例讲解

鄙人将以实际工作项目的makefile为例为大家讲解makefile的创建过程。Makefile内容如下:

CCFILES += $(wildcard src/*.cpp)

SRCDIR := ./src/

VPATH = src:./include:./src/xmlparser:./lib

# Compilers

#CC        := /opt/intel/composer_xe_2013.0.079/bin/intel64/icpc

CC := icpc

# Compilers para

FLAGS := -openmp -openmp-report -vec-report-O2

OBJECT :=file_interface.o tinyxml2.omic_decomposer.o Charset.o network.o buffer.o \ task_queue.o common.o main.omic_function.o hashtree.o nodeconfig.o md5_mic.o ntlm_mic.o

ALG.out : $(OBJECT)

$(CC)$(FLAGS) -o ALG.out $(OBJECT) ./lib/libxmlextern.a

file_interface.o :global.h tinyxml2.hfile_interface.h $(SRCDIR)file_interface.cpp

$(CC)$(FLAGS) -c $(SRCDIR)file_interface.cpp

tinyxml2.o :tinyxml2.h$(SRCDIR)tinyxml2.cpp

$(CC)$(FLAGS) -c $(SRCDIR)tinyxml2.cpp

mic_decomposer.o :$(SRCDIR)mic_decomposer.cppmic_decomposer.h mic_define.h cnre.h \ common.h hashtree.h

$(CC)$(FLAGS) -c $(SRCDIR)mic_decomposer.cpp

Charset.o :Charset.h cnre.h$(SRCDIR)Charset.cpp

$(CC)$(FLAGS) -c $(SRCDIR)Charset.cpp

network.o :network.h task_queue.hnetwork_packet.h nodeconfig.h $(SRCDIR)network.cpp

$(CC)$(FLAGS) -c $(SRCDIR)network.cpp

buffer.o :network.h task_queue.hnetwork_packet.h nodeconfig.h buffer.h $(SRCDIR)buffer.cpp

$(CC)$(FLAGS) -c $(SRCDIR)buffer.cpp

task_queue.o :task_queue.h$(SRCDIR)task_queue.cpp

$(CC)$(FLAGS) -c $(SRCDIR)task_queue.cpp

common.o :common.h mic_define.hmic_function.h $(SRCDIR)common.cpp

$(CC)$(FLAGS) -c $(SRCDIR)common.cpp

main.o :task_queue.h global.h network.hnetwork_packet.h common.h nodeconfig.h \ mic_define.h mic_function.hfile_interface.h $(SRCDIR)main.cpp

$(CC)$(FLAGS) -c $(SRCDIR)main.cpp

mic_function.o :mic_function.h$(SRCDIR)mic_function.cpp

$(CC)$(FLAGS) -c $(SRCDIR)mic_function.cpp

hashtree.o :hashtree.h$(SRCDIR)hashtree.cpp

$(CC)$(FLAGS) -c $(SRCDIR)hashtree.cpp

nodeconfig.o :nodeconfig.h./src/xmlparser/tinyxml.h $(SRCDIR)nodeconfig.cpp

$(CC)$(FLAGS) -c $(SRCDIR)nodeconfig.cpp

md5_mic.o :simd.h mic_define.h common.hshare_macro.h md5_macro.h md5_mic.h \ file_interface.h $(SRCDIR)md5_mic.cpp

$(CC)$(FLAGS) -c $(SRCDIR)md5_mic.cpp

ntlm_mic.o :simd.h mic_define.h common.hshare_macro.h ntlm_macro.h ntlm_mic.h

$(CC)$(FLAGS) -c $(SRCDIR)sha256_mic.cpp

.PHONY clean:

rm-f *.o *.out

具体讲解:

1.      CCFILES += $(wildcardsrc/*.cpp)

利用wildcard函数获取src目录下所有.cpp文件,并赋值给自定义变量CCFILES。其中#号是makefile的注释符号。

2.      SRCDIR:= ./src/

用于指明.cpp源文件所在目录。SRCDIR变量在command中出现时,以类似于宏替换的方式将其载入command中。

3.      VPATH= src:./include:./src/xmlparser:./lib

指明makefile寻找依赖项时,若当前目录不存在,则去VPATH指明的目录去寻找。各目录以“:”号隔开。

4.      CC := icpc,自定义变量CC指明为icpc,表示使用Intelc++ Compiler编译项目。

5.      FLAGS := -openmp -openmp-report-vec-report -O2,指明编译选项。

6.      OBJECT :=file_interface.otinyxml2.o mic_decomposer.o Charset.o network.o buffer.o \

task_queue.o common.o main.o mic_function.o hashtree.onodeconfig.o md5_mic.o ntlm_mic.o指明目标文件;其中反斜杠\表示一行还未结束。

7.      ALG.out : $(OBJECT)

$(CC) $(FLAGS) -o ALG.out$(OBJECT) ./lib/libxmlextern.a

此处表示makefile需要生成的第一个目标文件,也是不指明目标文件的make命令默认生成的目标文件。加入icpc的编译选项,并指明目标ALG.out依赖的目标文件和静态链接库项./lib/libxmlextern.a后,进行链接生成可执行文件ALG.out。

8.      file_interface.o :global.htinyxml2.h file_interface.h $(SRCDIR)file_interface.cpp

$(CC) $(FLAGS) -c$(SRCDIR)file_interface.cpp

指明file_interface.o的依赖项并编译成二进制文件file_interface.o。后面的每个目标文件皆是如此做法。

9.      .PHONY clean:

rm -f *.o *.out

使用.PHONY关键字,指明clean是伪目标,仅作标签使用。此处不依赖与任何项,使用方法是显示调用make clean,用于执行rm操作。但也可以添加依赖项,如:

all : prog1 prog2 prog3

.PHONY : all

则all依赖于ALG.out,那么使用 makeall则可以生成三个目标文件prog1、prog2和prog3。若将all放在所有目标文件的前面,则使用make即可,无需指明make all,原因是make命令将makefile中第一个出现的目标作为最终目标,若不放在最前面,则必须指明make all。

注意事项:

1.      makefile赋值符号= := +=?=的区别

= 是最基本的赋值,以makefile中最后赋值为准;

:= 是覆盖之前的值,以当前赋值为准;

?= 是如果没有被赋值过就赋予等号后面的值;

+= 是添加等号后面的值,即拼接等号后面的值。

其中=和:=的区别见如下代码:

(1)“=”

make会将整个makefile展开后,再决定变量的值。也就是说,变量的值将会是整个makefile中最后被指定的值。看例子:

x = foo

y = $(x) bar

x = xyz

在上例中,y的值将会是 xyz bar,而不是 foo bar 。

(2)“:=”

“:=”表示变量的值决定于它在makefile中的位置,而不是整个makefile展开后的最终值。

x := foo

y := $(x) bar

x := xyz

在上例中,y的值将会是 foo bar ,而不是 xyz bar 了。

2.makefile中目标文件一定要把依赖的头文件包含进去吗?

不一定,可以不包含进去。makefile是根据依赖项是否被修改决定是否重新执行command。如果不把头文件写入依赖项中,则面临的风险就是修改了头文件,目标文件不会被重新编译。我们的原则是,自己定义的头文件写入依赖项,库的头文件无需包含,除非你要修改库的头文件。

3.VPATH环境变量只能用来makefile寻找目标文件的依赖项,不能帮助编译器寻找所需编译的文件。

参考资料:

[1] http://blog.csdn.net/ruglcc/article/details/7814546/

[2] makefile百度百科

版权声明:本文为博主原创文章,未经博主允许不得转载。

makefile基础实例讲解 分类: C/C++ 2015-03-16 10:11 66人阅读 评论(0) 收藏的更多相关文章

  1. 改变HTML中超链接的显示样式 分类: C1_HTML/JS/JQUERY 2014-08-27 10:11 595人阅读 评论(0) 收藏

    更详细的内容请参考:http://www.w3school.com.cn/tags/tag_a.asp HTML中的代码如下: <a class="news_title" t ...

  2. OC基础知识总结 分类: ios学习 OC 2015-06-26 17&colon;58 58人阅读 评论&lpar;0&rpar; 收藏

    //OC: Objective-C, 面向对象的C语言 //OC与C的区别 //1.OC是C的超集, C语言的所有语法都可以在OC中使用 //2.OC是面向对象 //3.OC是一门运行时语言 //4. ...

  3. UI基础&colon;UILabel&period;UIFont 分类: iOS学习-UI 2015-07-01 19&colon;38 107人阅读 评论&lpar;0&rpar; 收藏

    UILabel:标签 继承自UIView ,在UIView基础上扩充了显示文本的功能.(文本框) UILabel的使用步骤 1.创建控件 UILabel *aLabel=[[UILabel alloc ...

  4. OC基础&colon;NSString NSNumber 分类: ios学习 OC 2015-06-17 17&colon;55 77人阅读 评论&lpar;0&rpar; 收藏

    OC中的基本数据类型 NSString  在64位系统下,相当于long,在非64位系统下,想当于int. CGFloat   在64位系统下,相当于double,在非64位系统之下,想当与float ...

  5. UI基础&colon;UIButton&period;UIimage 分类: iOS学习-UI 2015-07-01 21&colon;39 85人阅读 评论&lpar;0&rpar; 收藏

    UIButton是ios中用来响应用户点击事件的控件.继承自UIControl 1.创建控件 UIButton *button=[UIButton buttonWithType:UIButtonTyp ...

  6. JavaScript、Ajax与jQuery的关系 分类: C1&lowbar;HTML&sol;JS&sol;JQUERY 2014-07-31 10&colon;15 3388人阅读 评论&lpar;0&rpar; 收藏

    简单总结: 1.JS是一门前端语言. 2.Ajax是一门技术,它提供了异步更新的机制,使用客户端与服务器间交换数据而非整个页面文档,实现页面的局部更新. 3.jQuery是一个框架,它对JS进行了封装 ...

  7. 全面解析sizeof(下) 分类: C&sol;C&plus;&plus; StudyNotes 2015-06-15 10&colon;45 263人阅读 评论&lpar;0&rpar; 收藏

    以下代码使用平台是Windows7 64bits+VS2012. sizeof作用于基本数据类型,在特定的平台和特定的编译中,结果是确定的,如果使用sizeof计算构造类型:结构体.联合体和类的大小时 ...

  8. 全面解析sizeof(上) 分类: C&sol;C&plus;&plus; StudyNotes 2015-06-15 10&colon;18 188人阅读 评论&lpar;0&rpar; 收藏

    以下代码使用平台是Windows7 64bits+VS2012. sizeof是C/C++中的一个操作符(operator),其作用就是返回一个对象或者类型所占的内存字节数,使用频繁,有必须对齐有个全 ...

  9. MS SQL 合并结果集并求和 分类: SQL Server 数据库 2015-02-13 10&colon;59 92人阅读 评论&lpar;0&rpar; 收藏

    业务情景:有这样一张表:其中Id列为表主键,Name为用户名,State为记录的状态值,Note为状态的说明,方便阅读. 需求描述:需要查询出这样的结果:某个人某种状态的记录数,如:张三,待审核记录数 ...

随机推荐

  1. MessageBox&period;Show&lpar;&rpar;的各种用法

    [函数] <整型> MessageBox(<字符串> Text, <字符串> Title, <整型> nType,MessageBoxIcon); [函 ...

  2. 一段神奇的代码(python 2&period;7)网上抓图小Demo

    二话不说 先上代码: #coding=utf-8 import urllib import re import time global x x = 1 def getHtml(url): page = ...

  3. CSS笔记(三)背景

    CSS 允许应用纯色作为背景,也允许使用背景图像创建相当复杂的效果. 参考:http://www.w3school.com.cn/css/css_background.asp 背景色 p {backg ...

  4. class0513&lpar;html基础加强2)

    使用VS创建网页 新建Web项目(新建→ASP.Net Web应用程序),新建html页面(添加→新建项→Web→HTML页) 查看页面的方式: 切换到“设计”视图,可以在这里查看初步的预览效果,不是 ...

  5. ikely&lpar;&rpar;与unlikely&lpar;&rpar; 都等同于if, 此处只是做编译优化

    ikely()与unlikely()在2.6内核中,随处可见,那为什么要用它们?它们之间有什么区别呢? 首先明确: if (likely(value))等价于if (value)if (likely( ...

  6. Java-io流入门到精通详细总结

    IO流:★★★★★,用于处理设备上数据. 流:可以理解数据的流动,就是一个数据流.IO流最终要以对象来体现,对象都存在IO包中. 流也进行分类: 1:输入流(读)和输出流(写). 2:因为处理的数据不 ...

  7. String 操作

    String nbbms ="col_1_1_1_1,col_2_2_2_@,"; @ 实现将最后一个逗号去掉:从第一个字符串到最后一个逗号之前的字符串截取[java] Strin ...

  8. springmvc el表达式取值顺序问题

    最近遇到一个问题,两次访问同一个controler, 第二次根据判断条件,明明没有设置model的值,在jsp中通过${data}还是能取到值,最后找到原因是 我为了能够加快响应速度,在session ...

  9. 【BZOJ】1798&colon; &lbrack;Ahoi2009&rsqb;Seq 维护序列seq 线段树多标记(区间加&plus;区间乘)

    [题意]给定序列,支持区间加和区间乘,查询区间和取模.n<=10^5. [算法]线段树 [题解]线段树多重标记要考虑标记与标记之间的相互影响. 对于sum*b+a,+c直接加上即可. *c后就是 ...

  10. Django 最佳实践

    不错的Django实践规范,转自Github: https://github.com/brantyoung/zh-django-best-practices/blob/master/readme.rs ...