通用Makefile模板及实例
Makefile文件语法
Makefile⽂件语法概述本⽂将介绍Makefile种注释、回显、通配符、变量、循环判断、函数注释Makefile中只有单⾏注释,没有多⾏注释,注释以 # 开头。
以下Makefile注释⽚段节选⾃的Makefile# Makefile for installing Lua# See doc/readme.html for installation and customization instructions.# == CHANGE THE SETTINGS BELOW TO SUIT YOUR ENVIRONMENT =======================# Your platform. See PLATS for possible values.PLAT= noneechoing(回显)通常,make在执⾏命令⾏之前会把要执⾏的命令⾏进⾏输出。
我们称之为“回显”,就好像我们输⼊命令执⾏⼀样。
@如果要执⾏的命令⾏以字符“@”开始,则make在执⾏时这个命令就不会被回显。
典型的⽤法是我们在使⽤“echo”命令输出⼀些信息时。
如:@echo 开始编译XXX模块......当make执⾏时,将输出“开始编译XXX模块......”这个信息。
如果在命令⾏之前没有字符“@”,那么,make的输出就是:echo编译XXX模块......编译XXX模块......“-n”或“--just-print”如果使⽤make的命令⾏参数“-n”或“--just-print”,那么make执⾏时只显⽰所要执⾏的命令,但不会真正的去执⾏这些命令。
只有在这种情况下make才会打印出所有make需要执⾏的命令,其中也包括了使⽤“@”字符开始的命令。
这个选项对于我们调试Makefile⾮常有⽤,使⽤这个选项我们可以按执⾏顺序打印出Makefile中所有需要执⾏的命令。
“-s”或“--slient”make参数“-s”或“--slient”则是禁⽌所有执⾏命令的显⽰,就好像所有的命令⾏均使⽤“@”开始⼀样。
GNU MakeFile 使用手册
GNU Make 使用手册(中译版)翻译:于凤昌译者注:本人在阅读Linux源代码过程中发现如果要全面了解Linux的结构、理解Linux的编程总体设计及思想必须首先全部读通Linux源代码中各级的Makefile文件。
目前,在网上虽然有一些著作,但都不能全面的解释Linux源代码中各级的Makefile文件,因此本人认真阅读了GNU Make 使用手册(3.79)版原文,在此基础上翻译了该手册,以满足对Linux源代码有兴趣或者希望采用GCC编写程序但对缺乏GNU Make全面了解之人士的需要。
本人是业余爱好不是专业翻译人士,如果有问题请通过电子信箱与我联系共同商讨,本人的E-mail为:yfc70@。
注意在文章中出现的斜体加粗字表示章节。
GNU make Version 3.79April 2000Richard M. Stallman and Roland McGrath目录GNU Make 使用手册(中译版) (1)GNU make Version 3.79 (1)April 2000 (1)目录 (1)1 Make 概述 (4)1.1怎样阅读本手册 (4)1.2问题和BUG (4)2 Makefile文件介绍 (5)2.1 规则的格式 (5)2.2一个简单的Makefile文件 (5)2.3 make处理makefile文件的过程 (6)2.4使用变量简化makefile文件 (6)2.5 让make推断命令 (7)2.6 另一种风格的makefile文件 (7)2.7 在目录中删除文件的规则 (7)3 编写makefile文件 (8)3.1 makefile文件的内容 (8)3.2 makfile文件的命名 (8)3.3 包含其它的makefile文件 (8)3.4 变量MAKEFILES (9)3.5 makefile文件重新生成的过程 (9)3.6 重载其它makefile文件 (10)3.7 make读取makefile文件的过程 (10)4编写规则 (11)4.1规则的语法 (11)4.2 在文件名中使用通配符 (11)4.2.1通配符例子 (11)4.2.2使用通配符的常见错误 (12)4.2.3函数wildcard (12)4.3在目录中搜寻依赖 (12)4.3.1 VPATH:所有依赖的搜寻路径 (12)4.3.2 vpath指令 (13)4.3.3目录搜寻过程 (13)4.3.4编写目录搜寻的shell命令 (14)4.3.5 目录搜寻和隐含规则 (14)4.3.6 连接库的搜寻目录 (14)4.4假想目标 (14)4.5 没有命令或依赖的规则 (15)4.6使用空目标文件记录事件 (16)4.7 内建的特殊目标名 (16)4.8 具有多个目标的规则 (17)4.9 具有多条规则的目标 (17)4.10 静态格式规则 (17)4.10.1 静态格式规则的语法 (18)4.10.2静态格式规则和隐含规则 (18)4.11双冒号规则 (18)4.12 自动生成依赖 (19)5在规则中使用命令 (19)5.1 命令回显 (20)5.2执行命令 (20)5.3 并行执行 (20)5.4命令错误 (21)5.5中断或关闭make (21)5.6递归调用make (22)5.6.1 变量MAKE的工作方式 (22)5.6.2与子make通讯的变量 (22)5.6.3与子make通讯的选项 (23)5.6.4 ‘--print-directory’选项 (24)5.7定义固定次序命令 (24)5.8 使用空命令 (25)6 使用变量 (25)6.1 变量引用基础 (25)6.2 变量的两个特色 (25)6.3变量引用高级技术 (27)6.3.1替换引用 (27)6.3.2嵌套变量引用(计算的变量名) (27)6.4变量取值 (28)6.5设置变量 (29)6.6 为变量值追加文本 (29)6.7 override指令 (30)6.8定义多行变量 (30)6.9 环境变量 (31)6.10 特定目标变量的值 (31)6.11 特定格式变量的值 (31)7 makefile文件的条件语句 (32)7.1条件语句的例子 (32)7.2条件语句的语法 (32)7.3测试标志的条件语句 (33)8 文本转换函数 (34)8.1函数调用语法 (34)8.2字符串替换和分析函数 (34)8.3文件名函数 (35)8.4函数foreach (36)8.5函数if (37)8.6函数call (37)8.7函数origin (38)8.8 函数shell (38)8.9 控制make的函数 (39)9 运行make (39)9.1 指定makefile文件的参数 (39)9.2指定最终目标的参数 (39)9.3 代替执行命令 (40)9.4避免重新编译文件 (41)9.5变量重载 (41)9.6 测试编译程序 (42)9.7 选项概要 (42)10 使用隐含规则 (44)10.1 使用隐含规则 (44)10.2隐含规则目录 (44)10.3隐含规则使用的变量 (46)10.4 隐含规则链 (47)10.5定义与重新定义格式规则 (48)10.5.1格式规则简介 (48)10.5.2格式规则的例子 (48)10.5.3自动变量 (49)10.5.4格式匹配 (50)10.5.5万用规则 (50)10.5.6删除隐含规则 (50)10.6 定义最新类型的缺省规则 (51)10.7 过时的后缀规则 (51)10.8隐含规则搜寻算法 (52)11使用make更新档案文件 (52)11.1档案成员目标 (53)11.2 档案成员目标的隐含规则 (53)11.2.1更新档案的符号索引表 (54)11.3 使用档案的危险 (54)11.4 档案文件的后缀规则 (54)12 GNU make的特点 (54)13 不兼容性和失去的特点 (56)14 makefile文件惯例 (56)14.1 makefile文件的通用惯例 (56)14.2 makefile文件的工具 (57)14.3 指定命令的变量 (57)14.4安装路径变量 (58)14.5用户标准目标 (60)14.6 安装命令分类 (62)15 快速参考 (63)16 make产生的错误 (66)17 复杂的makfile文件例子 (67)脚注 (70)(1) (70)(2) (70)(3) (70)名词翻译对照表 (71)1 Make 概述Make 可自动决定一个大程序中哪些文件需要重新编译,并发布重新编译它们的命令。
整理后的makefile中文手册
GNU make中文手册ver - 3.8翻译整理:徐海兵2004-09-11关于本书本文瑾献给所有热爱Linux的程序员!本中文文档版权所有。
本文比较完整的讲述GNU make工具,涵盖GNU make的用法、语法。
同时重点讨论如何为一个工程编写Makefile。
作为一个Linux程序员,make工具的使用以及编写Makefile是必需的。
系统、详细讲述make的中文资料比较少,出于对广大中文Linuxer 的支持,本人在工作之余,花了18个多月时间完成对‚info make‛的翻译整理,完成这个中文版手册。
本书不是一个纯粹的语言翻译版本,其中对GNU make的一些语法和用法根据我个人的工作经验进行了一些详细分析和说明,也加入了一些个人的观点和实践总结。
本书的所有的例子都可以在支持V3.8版本的GNU make的系统中正确执行。
由于个人水平限制,本文在一些地方存在描述不准确之处。
恳请大家在阅读过程中,提出您宝贵的意见,也是对我个人的帮助。
我的个人电子邮箱地址:xhbdahai@。
非常愿意和大家交流!共同学习。
阅读本书之前,读者应该对GNU的工具链和Linux的一些常用编程工具有一定的了解。
诸如:gcc、as、ar、ld、yacc等;同时在书写Makefile时,需要能够进行一些基本的shell编程。
这些工具是维护一个工程的基础。
如果大家对这些工具的用法不是很熟悉,可参考项目资料。
阅读本文的几点建议:1.如果之前你对GNU make没有了解、当前也不想深入的学习GNU make的读者。
可只阅读本文各章节前半部分的内容(作为各章节的基础知识)。
2.如果你已经对GNU make比较熟悉,你更需要关心此版本的新增特点、功能、和之前版本不兼容之处;也可以作为开发过程过程的参考手册。
3.之前你对GNU make没有概念、或者刚开始接触,本身又想成为一个Linux下的专业程序员,那么建议:完整学习本文的各个章节,包括了基础知识和高级用法、技巧。
makefile引用标准c函数
一、概述在软件开发过程中,为了提高代码的可维护性和可移植性,通常会使用Makefile来管理代码的编译和信息过程。
而在C语言的开发中,经常会用到标准C库中的各种函数。
本文将讨论如何在Makefile中引用标准C函数,以及一些注意事项和最佳实践。
二、Makefile中的规则Makefile是用来描述软件项目中文件之间的依赖关系的文件。
它包含了一系列规则,每个规则包含了一个目标文件、依赖文件和生成目标文件的命令。
当执行make命令时,Makefile会根据规则自动执行对应的命令,从而生成目标文件。
三、引用标准C函数1. 在Makefile中引用标准C函数需要首先确保C标准库的头文件被正确包含。
在C语言中,通过#include指令可以将标准C库的头文件包含到源文件中。
2. 在Makefile中,我们可以使用变量来定义编译器、编译选项和信息选项。
我们可以定义CC变量来指定C语言的编译器,CFLAGS变量来指定编译选项,LDFLAGS变量来指定信息选项。
3. 当我们需要在Makefile中引用标准C函数时,我们只需要在对应的规则中使用变量来指定编译选项和信息选项。
如果我们需要使用标准C函数printf,我们只需要在对应的规则中将需要用到的标准库信息到目标文件中。
四、注意事项和最佳实践1. 在Makefile中引用标准C函数时,我们需要确保编译时能找到对应的标准C库文件。
通常情况下,标准C库文件会在系统的标准库目录下,我们需要将这些目录添加到信息选项中。
2. 在Makefile中引用标准C函数时,我们需要确保编译器能找到对应的标准C库头文件,通常情况下,标准C库头文件会在系统的标准头文件目录下,我们需要将这些目录添加到编译选项中。
3. 在Makefile中引用标准C函数时,我们需要确保编译器能正确识别和处理对应的标准C函数的参数和返回值类型。
通常情况下,标准C函数的参数和返回值类型会在对应的头文件中定义,我们需要确保这些定义被正确包含到源文件中。
大型工程多个目录下的Makefile写法
⼤型⼯程多个⽬录下的Makefile写法1、前⾔2、简单测试 测试程序在同⼀个⽂件中,共有func.h、func.c、main.c三个⽂件,Makefile写法如下所⽰:1 CC = gcc2 CFLAGS = -g -Wall34 main:main.o func.o5 $(CC) main.o func.o -o main6 main.o:main.c7 $(CC) $(CFLAGS) -c main.c -o main.o8 func.o:func.c9 $(CC) $(CFLAGS) -c func.c -o func.o10 clean:11 rm -rf *.o执⾏过程如下图所⽰:3、通⽤模板 实际当中程序⽂件⽐较⼤,这时候对⽂件进⾏分类,分为头⽂件、源⽂件、⽬标⽂件、可执⾏⽂件。
也就是说通常将⽂件按照⽂件类型放在不同的⽬录当中,这个时候的Makefile需要统⼀管理这些⽂件,将⽣产的⽬标⽂件放在⽬标⽬录下,可执⾏⽂件放到可执⾏⽬录下。
测试程序如下图所⽰:完整的Makefile如下所⽰:1 DIR_INC = ./include2 DIR_SRC = ./src3 DIR_OBJ = ./obj4 DIR_BIN = ./bin56 SRC = $(wildcard ${DIR_SRC}/*.c)7 OBJ = $(patsubst %.c,${DIR_OBJ}/%.o,$(notdir ${SRC}))89 TARGET = main1011 BIN_TARGET = ${DIR_BIN}/${TARGET}1213 CC = gcc14 CFLAGS = -g -Wall -I${DIR_INC}1516 ${BIN_TARGET}:${OBJ}17 $(CC) $(OBJ) -o $@1819 ${DIR_OBJ}/%.o:${DIR_SRC}/%.c20 $(CC) $(CFLAGS) -c $< -o $@21 .PHONY:clean22 clean:23 find ${DIR_OBJ} -name *.o -exec rm -rf {}解释如下:(1)Makefile中的符号@, ^, < 的意思: @ 表⽰⽬标⽂件 ^ 表⽰所有的依赖⽂件 < 表⽰第⼀个依赖⽂件 $? 表⽰⽐⽬标还要新的依赖⽂件列表(2)wildcard、notdir、patsubst的意思: wildcard : 扩展通配符 notdir :去除路径 patsubst :替换通配符例如下图例⼦所⽰:输出结果如下所⽰:SRC = $(wildcard *.c)等于指定编译当前⽬录下所有.c⽂件,如果还有⼦⽬录,⽐如⼦⽬录为inc,则再增加⼀个wildcard函数,象这样:SRC = (wildcard *.c) (wildcard inc/*.c)(3)gcc -I -L -l的区别:gcc -o hello hello.c -I /home/hello/include -L /home/hello/lib -lworld上⾯这句表⽰在编译hello.c时-I /home/hello/include表⽰将/home/hello/include⽬录作为第⼀个寻找头⽂件的⽬录, 寻找的顺序是:/home/hello/include-->/usr/include-->/usr/local/include -L /home/hello/lib表⽰将/home/hello/lib⽬录作为第⼀个寻找库⽂件的⽬录, 寻找的顺序是:/home/hello/lib-->/lib-->/usr/lib-->/usr/local/lib-lworld表⽰在上⾯的lib的路径中寻找libworld.so动态库⽂件(如果gcc编译选项中加⼊了“-static”表⽰寻找libworld.a静态库⽂件)参考:Processing math: 0%。
手把手教你如何写Makefile
手把手教你如何写Makefile陈皓 2005.04.01一、Makefile的规则在讲述这个Makefile之前,还是让我们先来粗略地看一看Makefile的规则。
target ... : prerequisites ...commandtarget也就是一个目标文件,可以是Object File,也可以是执行文件。
还可以是一个标签(Label),对于标签这种特性,在后续的“伪目标”章节中会有叙述。
prerequisites就是,要生成那个target所需要的文件或是目标。
command也就是make需要执行的命令。
(任意的Shell命令)这是一个文件的依赖关系,也就是说,target这一个或多个的目标文件依赖于prerequisites 中的文件,其生成规则定义在command中。
说白一点就是说,prerequisites中如果有一个以上的文件比target文件要新的话,command所定义的命令就会被执行。
这就是Makefile的规则。
也就是Makefile中最核心的内容。
说到底,Makefile的东西就是这样一点,好像我的这篇文档也该结束了。
呵呵。
还不尽然,这是Makefile的主线和核心,但要写好一个Makefile还不够,我会以后面一点一点地结合我的工作经验给你慢慢到来。
内容还多着呢。
:)二、一个示例正如前面所说的,如果一个工程有3个头文件,和8个C文件,我们为了完成前面所述的那三个规则,我们的Makefile应该是下面的这个样子的。
edit : main.o kbd.o command.o display.o \insert.o search.o files.o utils.occ -o edit main.o kbd.o command.o display.o \insert.o search.o files.o utils.omain.o : main.c defs.hcc -c main.ckbd.o : kbd.c defs.h command.hcc -c kbd.ccommand.o : command.c defs.h command.hcc -c command.cdisplay.o : display.c defs.h buffer.hcc -c display.cinsert.o : insert.c defs.h buffer.hcc -c insert.csearch.o : search.c defs.h buffer.hcc -c search.cfiles.o : files.c defs.h buffer.h command.hcc -c files.cutils.o : utils.c defs.hcc -c utils.cclean :rm edit main.o kbd.o command.o display.o \insert.o search.o files.o utils.o反斜杠(\)是换行符的意思。
“万能makefile”写法详解,一步一步写一个实用的Makefile
“万能makefile”写法详解,一步一步写一个实用的Makefilehttps:///qq1452008/article/details/50865535? share_token=52d10253-88ef-4463-9727-2ebc94e23726&tt_from=copy_link&utm_source=copy_link&ut m_medium=toutiao_android&utm_campaign=client_share?=本文转载自:作者:胡彦 2013-5-21出处:/huyansoft/article/details/8924624 提示:本文在原博文的基础上做了一点点修改与完善,诸如原博文的后面有显示不全的地方,自己已完善!作者:胡彦 2013-5-21代码和文档下载地址:/share/link?shareid=616139&uk=2535441 82一目的:编写一个实用的makefile,能自动编译当前目录下所有.c/.cpp源文件,支持二者混合编译。
并且当某个.c/.cpp、.h或依赖的源文件被修改后,仅重编涉及到的源文件,未涉及的不编译。
二要达到这个目的,用到的技术有:1-使用wildcard函数来获得当前目录下所有.c/.cpp文件的列表。
2-make的多目标规则。
3-make的模式规则。
4-用gcc -MM命令得到一个.c/.cpp文件include了哪些文件。
(具体使用细节,请点击博文链接)5-用sed命令对gcc -MM命令的结果作修改。
6-用include命令包含依赖描述文件.d。
三准备知识(一)多目标对makefile里下面2行,可看出多目标特征,执行make bigoutput或make littleoutput可看到结果:bigoutput littleoutput: defs.h pub.h@echo $@ $(subst output,OUTPUT,$@) $^注释:$@指该规则目标集合中能引起该规则执行的目标,$^指这个规则里所有依赖的集合。
Makefile
Makefile规则:target … : prerequisites…command……target就是一个目标文件,可以是Object File,也可以是可执行文件。
还可以是一个标签(Lable)。
prerequisites 就是要生成target所需要的文件或目标。
command 就是make需要执行的命令。
文件的依赖关系:target这一个或多个的目标文件依赖于prerequisites中的文件,其生成规则定义在command中。
如果prerequisites中的文件有一个以上的文件比target中的文件要新的话,则需要执行command定义的命令。
(Makefile规则)在Makefile中的反斜杠(\)表示换行的意思。
make命令解析Makefile文件。
如果要删除可执行文件和中间目标文件,只需要执行“make clean”。
edit : main.o kbd.o display.occ –o edit main.o kdb.o display.omain.o : main.c defs.hcc –c main.ckdb.o : kdb.c defs.hcc –c kdb.cdisplay.o : display.c defs.h command.hcc –c display.cclean:rm edit main.o kdb.o kdb.o在上个Makefile中,target(目标文件)包含:可执行文件edit和*.o(所有的中间目标文件)。
prerequisites(依赖文件)就是冒号后面的所有文件。
依赖关系:其实就是说明了目标文件是由哪些文件生成的,换言之,就是目标文件是哪些文件更新的。
make命令作用:比较target与prerequisites的日期,如果target日期比prerequisites新,不执行命令;否则(target日期不比prerequisites新或是target不存在),执行command命令,并更新或生成target。
makefile obj用法
文章标题:深入探讨Makefile中的Obj用法在软件开发中,Makefile是一个非常重要的工具,它帮助程序员管理项目的编译和信息过程。
而Makefile中的Obj用法则是Makefile中非常重要的一部分,它用来指定项目中的目标文件。
在本篇文章中,我们将深入探讨Makefile中的Obj用法,从简单到复杂,由浅入深,帮助读者更好地理解和运用Obj用法。
1. 什么是Makefile在开始深入探讨Makefile中的Obj用法之前,我们先来了解一下什么是Makefile。
Makefile是一种文件,其中包含了一系列规则和命令,用于指导编译器如何编译和信息项目中的源文件,最终生成可执行文件。
Makefile通过维护文件之间的依赖关系,可以使得在修改源文件后,只重新编译需要重新编译的文件,而不是整个项目。
这样可以提高编译的效率,特别是在大型项目中非常重要。
2. Obj用法的基础概念Obj用法是Makefile中用来指定目标文件的一个重要部分。
在Makefile中,通常通过指定目标文件来定义一个编译单元,Obj用法就是用来指定这些目标文件的。
在Makefile中,Obj用法通常是在规则中使用的,用来指定编译的目标文件是哪些。
我们可以这样定义一个规则:```main.o : main.cgcc -c main.c -o main.o```在这个例子中,main.o就是通过Obj用法指定的目标文件,它告诉Makefile需要生成名为main.o的目标文件,并且它是由main.c编译而来的。
3. Makefile中的Obj用法进阶除了简单地指定目标文件外,Obj用法还可以进一步扩展。
在实际开发中,一个目标文件可能由多个源文件编译而来,这时候就需要用到Obj用法的进阶用法了。
在Makefile中,我们可以使用通配符来指定一组目标文件,例如:```%.o : %.cgcc -c $< -o $@```这个规则中,%表示任意的文件名,$<表示依赖文件,$@表示目标文件。
简单的makefile模板
简单的makefile模板makefile不是总⽤到,每次⽤到的时候总要重新找资料,有点⿇烦(怪⾃⼰基础知识不扎实,汗)。
留⼀个通⽤模板放这,⽅便以后使⽤CC = gccCXX = g++LINK = g++CFLAGS = -g -Wall -O2TARGET = mk0SRCS = $(wildcard *.cpp)SRCS += $(wildcard *.c)CXX_OBJS = $(patsubst %.cpp, %.o, $(wildcard *.cpp))C_OBJS = $(patsubst %.c, %.o, $(wildcard *.c))all:$(TARGET)$(TARGET):$(CXX_OBJS) $(C_OBJS)$(LINK) $(CFLAGS) -o $@ $^%.o:%.cpp$(CXX) $(CFLAGS) -c -o $@ $<%.o:%.c$(CC) $(CFLAGS) -c -o $@ $<.PHONY:cleanclean:rm -rf *.o $(TARGET) $(CXX_OBJS) $(C_OBJS)因为项⽬特殊性,经常c与cpp都会⽤到,所以简单写个这样的makefile⽂件上⾯makefile有很⼤局限性,⽐如只能使⽤与所有源⽂件在⼀个⽬录场景。
下⾯展⽰可以多个⽬录下源⽂件,以及程序使⽤动态库的特殊场景CC = gccCXX = g++LINKC = gccLINKCXX = g++CFLAGS = -g -Wall -O2TOP_DIR := $(shell pwd)SRC_DIRS := $(shell find $(TOP_DIR) -maxdepth 1 -type d)TARGET := $(TOP_DIR)/bin/mk0INC_PATH = -I$(TOP_DIR)/include/LIB_PATH = -L$(TOP_DIR)/lib/EXT_LIB = -Wl,-rpath,$(TOP_DIR)/bin/ -lcsayCXX_SRCS = $(foreach dir, $(SRC_DIRS), $(wildcard $(dir)/*.cpp))CXX_OBJS = $(patsubst %.cpp, %.o, $(CXX_SRCS))C_SRCS = $(foreach dir, $(SRC_DIRS), $(wildcard $(dir)/*.c))C_OBJS = $(patsubst %.c, %.o, $(C_SRCS))all:$(TARGET)$(TARGET):$(CXX_OBJS) $(C_OBJS) $(shell if [ ! -d $(TOP_DIR)/bin ]; then mkdir $(TOP_DIR)/bin; fi)ifeq ($(CXX_SRCS),) $(LINKC) $(LIB_PATH) $(EXT_LIB) $(CFLAGS) -o $@ $^else $(LINKCXX) $(LIB_PATH) $(EXT_LIB) $(CFLAGS) -o $@ $^endif%.o:%.cpp $(CXX) $(INC_PATH) $(CFLAGS) -c -o $@ $<%.o:%.c $(CC) $(INC_PATH) $(CFLAGS) -c -o $@ $<.PHONY:cleanclean:rm -rf $(TARGET) $(CXX_OBJS) $(C_OBJS)如上所⽰,代码包括了三个⽬录:. func0 func1⽬录。
Makefile面试
Makefile⾯试介绍⼀下make? 为什么使⽤make1、包含多个源⽂件的项⽬在编译时有长⽽复杂的命令⾏,可以通过makefile保存这些命令⾏来简化该⼯作2、make可以减少重新编译所需要的时间,因为make可以识别出哪些⽂件是新修改的3、make维护了当前项⽬中各⽂件的相关关系,从⽽可以在编译前检查是否可以找到所有的⽂件makefile:⼀个⽂本形式的⽂件,其中包含⼀些规则告诉make编译哪些⽂件以及怎样编译这些⽂件,每条规则包含以下内容:⼀个target,即最终创建的东西⼀个和多个dependencies列表,通常是编译⽬标⽂件所需要的其他⽂件需要执⾏的⼀系列commands,⽤于从指定的相关⽂件创建⽬标⽂件make执⾏时按顺序查找名为GNUmakefile,makefile或者Makefile⽂件,通常,⼤多数⼈常⽤MakefileMakefile规则:target: dependency dependency [..] command command [..]注意:command前⾯必须是制表符例⼦:editor: editor.o screen.o keyboard.ogcc -o editor editor.o screen.o keyboard.oeditor.o : editor.c editor.h keyboard.h screen.hgcc -c editor.cscreen.o: screen.c screen.hgcc -c screen.ckeyboard.o : keyboard.c keyboard.hgcc -c keyboard.cclean:rm editor *.o。
makefile 条件语句
makefile 条件语句
在Makefile中,可以使用条件语句来根据不同的条件执行不同的指令。
常用的条件语句有ifeq、ifneq、ifdef和ifndef。
以ifeq为例,其语法如下:
ifeq (条件1, 条件2)
#如果条件1等于条件2,则执行此处指令
else
#如果条件1不等于条件2,则执行此处指令
endif
条件可以是任意合法的表达式,如变量比较、函数调用等。
如果条件成立,则执行if语句块中的指令;否则,执行else语句块中的指令。
下面是一个示例,根据操作系统类型决定编译器的选项:
```makefile
ifeq ($(OS), Linu某)
CC=gcc
CFLAGS=-Wall -We某tra
else
CC=clang
CFLAGS=-Weverything
endif
.PHONY: all
all:
$(CC) $(CFLAGS) -o myprog main.c
```
在上述示例中,如果$(OS)的值为"Linu某",则CC变量的值为"gcc",CFLAGS变量的值为"-Wall -We某tra";否则,CC变量的值为"clang",CFLAGS变量的值为"-Weverything"。
在all目标中,使用$(CC)以及$(CFLAGS)变量来编译源文件main.c生成可执行文件myprog。
模块编译Makefile模板 && Nothing to be done for `modules'
最近在linux2.4内核上编译一个动态加载模块时遇到这样一个问题,执行make时编译器不编makefile文件中所指定的目标文件,而是提示一句Nothing to be done for `modules',然后就退出了。
主控Makefile文件中采用的式来编译模块的:$(MAKE) -C $(KERNELPA TH) SUBDIRS=$(shell pwd) modules下面我们来分析一下原因,并寻找解决的方法。
一、先看看执行$(MAKE) -C $(KERNELPA TH) SUBDIRS=$(shell pwd) modules后脚本是怎样执行的:1.进入内核目录,执行modules目标modules: $(patsubst %, _mod_%, $(SUBDIRS))这里把传入的SUBDIRS变量加上一个_mod_前缀,使modules依赖于他$(patsubst %, _mod_%, $(SUBDIRS)) : include/linux/version.h \ include/config/MARKER $(MAKE) -C $(patsubst _mod_%, %, $@) CFLAGS="$(CFLAGS) $(MODFLAGS)" MAKING_MODULES=1 modules这里回到SUBDIRS执行modules,但是带入CFLAGS变量2.回到SUBDIRS执行modules目标,但是Makefile文件中根本就没有这个目标的存在,当然会报Nothing to be done for `modules'了,那么这个modules目标到底是什么呢?找个2.4与2.6内核通用的模块编译Makefile文件看看,它通常在目标all之前有这样几行语句:-include $(TOPDIR)/Rules.makeall_targets:all这就是问题的关键所在!TOPDIR变量内核根Makefile文件中定义的TOPDIR := $(shell /bin/pwd)就是指内核的路径,所以Include前面的“-”就显得尤为重要。
makefile gcc编译
makefile gcc编译
Makefile 是一个用来组织代码编译的工具,而 GCC 是一个常用的 C 和 C++ 编译器。
在 Makefile 中使用 GCC 进行编译可以通过以下步骤完成:
1. 创建一个名为 "Makefile" 的文本文件,并确保它位于你的项目根目录下。
2. 在 Makefile 中定义你的编译规则。
例如,假设你有一个名为 "main.c" 的源文件需要编译成可执行文件 "app",你可以这样编写 Makefile:
make.
app: main.c.
gcc -o app main.c.
在这个例子中,我们定义了一个名为 "app" 的目标,它依赖于"main.c" 这个源文件。
当你运行 "make" 命令时,Make 工具会根
据这个规则来执行编译。
3. 打开终端,进入到包含 Makefile 的项目目录下。
4. 运行命令 "make"。
Make 工具会读取 Makefile 文件,并执行其中定义的编译规则。
在这个例子中,它会使用 GCC 编译器来编译 "main.c" 并生成可执行文件 "app"。
需要注意的是,Makefile 可以包含更复杂的规则和变量定义,以及支持多个源文件的编译。
你可以根据你的项目需求来进一步扩展和定制 Makefile 文件。
总之,通过合理编写 Makefile 并结合使用 GCC 编译器,你可以高效地组织和管理你的代码编译过程。
Makefile使用总结
Makefile使⽤总结1. Makefile 简介Makefile 是和 make 命令⼀起配合使⽤的.很多⼤型项⽬的编译都是通过 Makefile 来组织的, 如果没有 Makefile, 那很多项⽬中各种库和代码之间的依赖关系不知会多复杂. Makefile的组织流程的能⼒如此之强, 不仅可以⽤来编译项⽬, 还可以⽤来组织我们平时的⼀些⽇常操作. 这个需要⼤家发挥⾃⼰的想象⼒.本篇博客是基于⽽整理的, 有些删减, 追加了⼀些⽰例.⾮常感谢 gunguymadman_cu 提供如此详尽的Makefile介绍, 这正是我⼀直寻找的Makefile中⽂⽂档.1.1 Makefile 主要的 5个部分 (显⽰规则, 隐晦规则, 变量定义, ⽂件指⽰, 注释)Makefile基本格式如下:target ... : prerequisites ...command......其中,target - ⽬标⽂件, 可以是 Object File, 也可以是可执⾏⽂件prerequisites - ⽣成 target 所需要的⽂件或者⽬标command - make需要执⾏的命令 (任意的shell命令), Makefile中的命令必须以 [tab] 开头1. 显⽰规则 :: 说明如何⽣成⼀个或多个⽬标⽂件(包括⽣成的⽂件, ⽂件的依赖⽂件, ⽣成的命令)2. 隐晦规则 :: make的⾃动推导功能所执⾏的规则3. 变量定义 :: Makefile中定义的变量4. ⽂件指⽰ :: Makefile中引⽤其他Makefile; 指定Makefile中有效部分; 定义⼀个多⾏命令5. 注释 :: Makefile只有⾏注释 "#", 如果要使⽤或者输出"#"字符, 需要进⾏转义, "\#"1.2 GNU make 的⼯作⽅式1. 读⼊主Makefile (主Makefile中可以引⽤其他Makefile)2. 读⼊被include的其他Makefile3. 初始化⽂件中的变量4. 推导隐晦规则, 并分析所有规则5. 为所有的⽬标⽂件创建依赖关系链6. 根据依赖关系, 决定哪些⽬标要重新⽣成7. 执⾏⽣成命令2. Makefile 初级语法2.1 Makefile 规则2.1.1 规则语法规则主要有2部分: 依赖关系和⽣成⽬标的⽅法.语法有以下2种:target ... : prerequisites ...command...或者target ... : prerequisites ; commandcommand...*注* command太长, 可以⽤ "\" 作为换⾏符2.1.2 规则中的通配符* :: 表⽰任意⼀个或多个字符:: 表⽰任意⼀个字符[...] :: ex. [abcd] 表⽰a,b,c,d中任意⼀个字符, [^abcd]表⽰除a,b,c,d以外的字符, [0-9]表⽰ 0~9中任意⼀个数字~ :: 表⽰⽤户的home⽬录2.1.3 路径搜索当⼀个Makefile中涉及到⼤量源⽂件时(这些源⽂件和Makefile极有可能不在同⼀个⽬录中),这时, 最好将源⽂件的路径明确在Makefile中, 便于编译时查找. Makefile中有个特殊的变量VPATH就是完成这个功能的.指定了VPATH之后, 如果当前⽬录中没有找到相应⽂件或依赖的⽂件, Makefile 回到VPATH指定的路径中再去查找.. VPATH使⽤⽅法:vpath <directories> :: 当前⽬录中找不到⽂件时, 就从<directories>中搜索vpath <pattern> <directories> :: 符合<pattern>格式的⽂件, 就从<directories>中搜索vpath <pattern> :: 清除符合<pattern>格式的⽂件搜索路径vpath :: 清除所有已经设置好的⽂件路径# ⽰例1 - 当前⽬录中找不到⽂件时, 按顺序从 src⽬录 ../parent-dir⽬录中查找⽂件VPATH src:../parent-dir# ⽰例2 - .h结尾的⽂件都从 ./header ⽬录中查找VPATH %.h ./header# ⽰例3 - 清除⽰例2中设置的规则VPATH %.h# ⽰例4 - 清除所有VPATH的设置VPATH2.2 Makefile 中的变量2.2.1 变量定义 ( = or := )OBJS = programA.o programB.oOBJS-ADD = $(OBJS) programC.o# 或者OBJS := programA.o programB.oOBJS-ADD := $(OBJS) programC.o其中 = 和 := 的区别在于, := 只能使⽤前⾯定义好的变量, = 可以使⽤后⾯定义的变量测试 =# Makefile内容OBJS2 = $(OBJS1) programC.oOBJS1 = programA.o programB.oall:@echo $(OBJS2)# bash中执⾏make, 可以看出虽然 OBJS1 是在 OBJS2 之后定义的, 但在 OBJS2中可以提前使⽤$ makeprogramA.o programB.o programC.o测试 :=# Makefile内容OBJS2 := $(OBJS1) programC.oOBJS1 := programA.o programB.oall:@echo $(OBJS2)# bash中执⾏make, 可以看出 OBJS2 中的 $(OBJS1) 为空$ makeprogramC.o2.2.2 变量替换# Makefile内容SRCS := programA.c programB.c programC.cOBJS := $(SRCS:%.c=%.o)all:@echo "SRCS: " $(SRCS)@echo "OBJS: " $(OBJS)# bash中运⾏make$ makeSRCS: programA.c programB.c programC.cOBJS: programA.o programB.o programC.o2.2.3 变量追加值 +=# Makefile内容SRCS := programA.c programB.c programC.cSRCS += programD.call:@echo "SRCS: " $(SRCS)# bash中运⾏make$ makeSRCS: programA.c programB.c programC.c programD.c2.2.4 变量覆盖 override作⽤是使 Makefile中定义的变量能够覆盖 make 命令参数中指定的变量语法:override <variable> = <value>override <variable> := <value>override <variable> += <value>下⾯通过⼀个例⼦体会 override 的作⽤:# Makefile内容 (没有⽤override)SRCS := programA.c programB.c programC.call:@echo "SRCS: " $(SRCS)# bash中运⾏make$ make SRCS=nothingSRCS: nothing################################################## Makefile内容 (⽤override)override SRCS := programA.c programB.c programC.call:@echo "SRCS: " $(SRCS)# bash中运⾏make$ make SRCS=nothingSRCS: programA.c programB.c programC.c2.2.5 ⽬标变量作⽤是使变量的作⽤域仅限于这个⽬标(target), ⽽不像之前例⼦中定义的变量, 对整个Makefile都有效.语法:<target ...> :: <variable-assignment><target ...> :: override <variable-assignment> (override作⽤参见变量覆盖的介绍)⽰例:# Makefile 内容SRCS := programA.c programB.c programC.ctarget1: TARGET1-SRCS := programD.ctarget1:@echo "SRCS: " $(SRCS)@echo "SRCS: " $(TARGET1-SRCS)target2:@echo "SRCS: " $(SRCS)@echo "SRCS: " $(TARGET1-SRCS)# bash中执⾏make$ make target1SRCS: programA.c programB.c programC.cSRCS: programD.c$ make target2 <-- target2中显⽰不了 $(TARGET1-SRCS)SRCS: programA.c programB.c programC.cSRCS:2.3 Makefile 命令前缀Makefile 中书写shell命令时可以加2种前缀 @ 和 -, 或者不⽤前缀.3种格式的shell命令区别如下:不⽤前缀 :: 输出执⾏的命令以及命令执⾏的结果, 出错的话停⽌执⾏前缀 @ :: 只输出命令执⾏的结果, 出错的话停⽌执⾏前缀 - :: 命令执⾏有错的话, 忽略错误, 继续执⾏⽰例:# Makefile 内容 (不⽤前缀)all:echo"没有前缀"cat this_file_not_existecho"错误之后的命令" <-- 这条命令不会被执⾏# bash中执⾏make$ makeecho"没有前缀" <-- 命令本⾝显⽰出来没有前缀 <-- 命令执⾏结果显⽰出来cat this_file_not_existcat: this_file_not_exist: No such file or directorymake: *** [all] Error 1############################################################ Makefile 内容 (前缀 @)all:@echo "没有前缀"@cat this_file_not_exist@echo "错误之后的命令" <-- 这条命令不会被执⾏# bash中执⾏make$ make没有前缀 <-- 只有命令执⾏的结果, 不显⽰命令本⾝cat: this_file_not_exist: No such file or directorymake: *** [all] Error 1############################################################ Makefile 内容 (前缀 -)all:-echo"没有前缀"-cat this_file_not_exist-echo"错误之后的命令" <-- 这条命令会被执⾏# bash中执⾏make$ makeecho"没有前缀" <-- 命令本⾝显⽰出来没有前缀 <-- 命令执⾏结果显⽰出来cat this_file_not_existcat: this_file_not_exist: No such file or directorymake: [all] Error 1 (ignored)echo"错误之后的命令" <-- 出错之后的命令也会显⽰错误之后的命令 <-- 出错之后的命令也会执⾏2.4 伪⽬标伪⽬标并不是⼀个"⽬标(target)", 不像真正的⽬标那样会⽣成⼀个⽬标⽂件.典型的伪⽬标是 Makefile 中⽤来清理编译过程中中间⽂件的 clean 伪⽬标, ⼀般格式如下: .PHONY: clean <-- 这句没有也⾏, 但是最好加上clean:-rm -f *.o2.5 引⽤其他的 Makefile语法: include <filename> (filename 可以包含通配符和路径)⽰例:# Makefile 内容all:@echo "主 Makefile begin"@make other-all@echo "主 Makefile end"include ./other/Makefile# ./other/Makefile 内容other-all:@echo "other makefile begin"@echo "other makefile end"# bash中执⾏make$ lltotal 20K-rw-r--r-- 1 wangyubin wangyubin 125 Sep 2316:13 Makefile-rw-r--r-- 1 wangyubin wangyubin 11K Sep 2316:15 <-- 这个⽂件不⽤管drwxr-xr-x 2 wangyubin wangyubin 4.0K Sep 2316:11 other$ ll other/total 4.0K-rw-r--r-- 1 wangyubin wangyubin 71 Sep 2316:11 Makefile$ make主 Makefile beginmake[1]: Entering directory `/path/to/test/makefile'other makefile beginother makefile endmake[1]: Leaving directory `/path/to/test/makefile'主 Makefile end2.6 查看C⽂件的依赖关系写 Makefile 的时候, 需要确定每个⽬标的依赖关系.GNU提供⼀个机制可以查看C代码⽂件依赖那些⽂件, 这样我们在写 Makefile ⽬标的时候就不⽤打开C源码来看其依赖那些⽂件了.⽐如, 下⾯命令显⽰内核源码中 virt/kvm/kvm_main.c 中的依赖关系$ cd virt/kvm/$ gcc -MM kvm_main.ckvm_main.o: kvm_main.c iodev.h coalesced_mmio.h async_pf.h <-- 这句就可以加到 Makefile 中作为编译 kvm_main.o 的依赖关系2.7 make 退出码Makefile的退出码有以下3种:0 :: 表⽰成功执⾏1 :: 表⽰make命令出现了错误2 :: 使⽤了 "-q" 选项, 并且make使得⼀些⽬标不需要更新2.8 指定 Makefile,指定特定⽬标默认执⾏ make 命令时, GNU make在当前⽬录下依次搜索下⾯3个⽂件 "GNUmakefile", "makefile", "Makefile",找到对应⽂件之后, 就开始执⾏此⽂件中的第⼀个⽬标(target). 如果找不到这3个⽂件就报错.⾮默认情况下, 可以在 make 命令中指定特定的 Makefile 和特定的⽬标.⽰例:# Makefile⽂件名改为 MyMake, 内容target1:@echo "target [1] begin"@echo "target [1] end"target2:@echo "target [2] begin"@echo "target [2] end"# bash 中执⾏make$ lsMakefile$ mv Makefile MyMake$ lsMyMake$ make <-- 找不到默认的 Makefilemake: *** No targets specified and no makefile found. Stop.$ make -f MyMake <-- 指定特定的Makefiletarget [1] begintarget [1] end$ make -f MyMake target2 <-- 指定特定的⽬标(target)target [2] begintarget [2] end2.9 make 参数介绍make 的参数有很多, 可以通过 make -h 去查看, 下⾯只介绍⼏个我认为⽐较有⽤的.参数含义--debug[=<options>]输出make的调试信息, options 可以是 a, b, v-j --jobs同时运⾏的命令的个数, 也就是多线程执⾏ Makefile-r --no-builtin-rules禁⽌使⽤任何隐含规则-R --no-builtin-variabes禁⽌使⽤任何作⽤于变量上的隐含规则-B --always-make假设所有⽬标都有更新, 即强制重编译2.10 Makefile 隐含规则这⾥只列⼀个和编译C相关的.编译C时,<n>.o 的⽬标会⾃动推导为 <n>.c# Makefile 中main : main.ogcc -o main main.o#会⾃动变为:main : main.ogcc -o main main.omain.o: main.c <-- main.o 这个⽬标是隐含⽣成的gcc -c main.c2.11 隐含规则中的命令变量和命令参数变量2.11.1 命令变量, 书写Makefile可以直接写 shell时⽤这些变量.下⾯只列出⼀些C相关的变量名含义RM rm -fAR arCC ccCXX g++⽰例:# Makefile 内容all:@echo $(RM)@echo $(AR)@echo $(CC)@echo $(CXX)# bash 中执⾏make, 显⽰各个变量的值$ makerm -farccg++2.11.2 命令参数变量变量名含义ARFLAGS AR命令的参数CFLAGS C语⾔编译器的参数CXXFLAGS C++语⾔编译器的参数⽰例: 下⾯以 CFLAGS 为例演⽰# test.c 内容#include <stdio.h>int main(int argc, char *argv[]){printf ("Hello Makefile\n");return 0;}# Makefile 内容test: test.o$(CC) -o test test.o# bash 中⽤make来测试$ lltotal 24K-rw-r--r-- 1 wangyubin wangyubin 69 Sep 2317:31 Makefile-rw-r--r-- 1 wangyubin wangyubin 14K Sep 2319:51 <-- 请忽略这个⽂件-rw-r--r-- 1 wangyubin wangyubin 392 Sep 2317:31 test.c$ makecc -c -o test.o test.ccc -o test test.o <-- 这个是⾃动推导的$ rm -f test test.o$ make CFLAGS=-Wall <-- 命令中加的编译器参数⾃动追加⼊下⾯的编译中了cc -Wall -c -o test.o test.ccc -o test test.o2.12 ⾃动变量Makefile 中很多时候通过⾃动变量来简化书写, 各个⾃动变量的含义如下:⾃动变量含义$@⽬标集合$%当⽬标是函数库⽂件时, 表⽰其中的⽬标⽂件名$<第⼀个依赖⽬标. 如果依赖⽬标是多个, 逐个表⽰依赖⽬标$?⽐⽬标新的依赖⽬标的集合$^所有依赖⽬标的集合, 会去除重复的依赖⽬标$+所有依赖⽬标的集合, 不会去除重复的依赖⽬标$*这个是GNU make特有的, 其它的make不⼀定⽀持3. Makefile ⾼级语法3.1 嵌套Makefile在 Makefile 初级语法中已经提到过引⽤其它 Makefile的⽅法. 这⾥有另⼀种写法, 并且可以向引⽤的其它 Makefile 传递参数.⽰例: (不传递参数, 只是调⽤⼦⽂件夹 other 中的Makefile)# Makefile 内容all:@echo "主 Makefile begin"@cd ./other && make@echo "主 Makefile end"# ./other/Makefile 内容other-all:@echo "other makefile begin"@echo "other makefile end"# bash中执⾏make$ lltotal 28K-rw-r--r-- 1 wangyubin wangyubin 104 Sep 2320:43 Makefile-rw-r--r-- 1 wangyubin wangyubin 17K Sep 2320:44 <-- 这个⽂件不⽤管drwxr-xr-x 2 wangyubin wangyubin 4.0K Sep 2320:42 other$ ll other/total 4.0K-rw-r--r-- 1 wangyubin wangyubin 71 Sep 2316:11 Makefile$ make主 Makefile beginmake[1]: Entering directory `/path/to/test/makefile/other'other makefile beginother makefile endmake[1]: Leaving directory `/path/to/test/makefile/other'主 Makefile end⽰例: (⽤export传递参数)# Makefile 内容export VALUE1 := export.c <-- ⽤了 export, 此变量能够传递到 ./other/Makefile 中VALUE2 := no-export.c <-- 此变量不能传递到 ./other/Makefile 中all:@echo "主 Makefile begin"@cd ./other && make@echo "主 Makefile end"# ./other/Makefile 内容other-all:@echo "other makefile begin"@echo "VALUE1: " $(VALUE1)@echo "VALUE2: " $(VALUE2)@echo "other makefile end"# bash中执⾏make$ make主 Makefile beginmake[1]: Entering directory `/path/to/test/makefile/other'other makefile beginVALUE1: export.c <-- VALUE1 传递成功VALUE2: <-- VALUE2 传递失败other makefile endmake[1]: Leaving directory `/path/to/test/makefile/other'主 Makefile end*补充* export 语法格式如下:export variable = valueexport variable := valueexport variable += value3.2 定义命令包命令包有点像是个函数, 将连续的相同的命令合成⼀条, 减少 Makefile 中的代码量, 便于以后维护.语法:define <command-name>command...endef⽰例:# Makefile 内容define run-hello-makefile@echo -n "Hello"@echo " Makefile!"@echo "这⾥可以执⾏多条 Shell 命令!"endefall:$(run-hello-makefile)# bash 中运⾏make$ makeHello Makefile!这⾥可以执⾏多条 Shell 命令!3.3 条件判断条件判断的关键字主要有 ifeq ifneq ifdef ifndef语法:<conditional-directive><text-if-true>endif# 或者<conditional-directive><text-if-true>else<text-if-false>endif⽰例: ifeq的例⼦, ifneq和ifeq的使⽤⽅法类似, 就是取反# Makefile 内容all:ifeq ("aa", "bb")@echo "equal"else@echo "not equal"endif# bash 中执⾏make$ makenot equal⽰例: ifdef的例⼦, ifndef和ifdef的使⽤⽅法类似, 就是取反# Makefile 内容SRCS := program.call:ifdef SRCS@echo $(SRCS)else@echo "no SRCS"# bash 中执⾏make$ makeprogram.c3.4 Makefile 中的函数Makefile 中⾃带了⼀些函数, 利⽤这些函数可以简化 Makefile 的编写.函数调⽤语法如下:$(<function> <arguments>)# 或者${<function> <arguments>}<function> 是函数名<arguments> 是函数参数3.4.1 字符串函数字符串替换函数: $(subst <from>,<to>,<text>)功能: 把字符串<text> 中的 <from> 替换为 <to>返回: 替换过的字符串# Makefile 内容all:@echo $(subst t,e,maktfilt) <-- 将t替换为e# bash 中执⾏make$ makemakefile模式字符串替换函数: $(patsubst <pattern>,<replacement>,<text>)功能: 查找<text>中的单词(单词以"空格", "tab", "换⾏"来分割) 是否符合 <pattern>, 符合的话, ⽤ <replacement> 替代.返回: 替换过的字符串# Makefile 内容all:@echo $(patsubst %.c,%.o,programA.c programB.c)# bash 中执⾏make$ makeprogramA.o programB.o去空格函数: $(strip <string>)功能: 去掉 <string> 字符串中开头和结尾的空字符返回: 被去掉空格的字符串值# Makefile 内容VAL := " aa bb cc "all:@echo "去除空格前: " $(VAL)@echo "去除空格后: " $(strip $(VAL))# bash 中执⾏make去除空格前: aa bb cc去除空格后: aa bb cc查找字符串函数: $(findstring <find>,<in>)功能: 在字符串 <in> 中查找 <find> 字符串返回: 如果找到, 返回 <find> 字符串, 否则返回空字符串# Makefile 内容VAL := " aa bb cc "all:@echo $(findstring aa,$(VAL))@echo $(findstring ab,$(VAL))# bash 中执⾏make$ makeaa过滤函数: $(filter <pattern...>,<text>)功能: 以 <pattern> 模式过滤字符串 <text>, *保留* 符合模式 <pattern> 的单词, 可以有多个模式返回: 符合模式 <pattern> 的字符串# Makefile 内容all:@echo $(filter %.o %.a,program.c program.o program.a)# bash 中执⾏make$ makeprogram.o program.a反过滤函数: $(filter-out <pattern...>,<text>)功能: 以 <pattern> 模式过滤字符串 <text>, *去除* 符合模式 <pattern> 的单词, 可以有多个模式返回: 不符合模式 <pattern> 的字符串# Makefile 内容all:@echo $(filter-out %.o %.a,program.c program.o program.a)# bash 中执⾏make$ makeprogram.c排序函数: $(sort <list>)功能: 给字符串 <list> 中的单词排序 (升序)返回: 排序后的字符串# Makefile 内容all:@echo $(sort bac abc acb cab)# bash 中执⾏make$ makeabc acb bac cab取单词函数: $(word <n>,<text>)功能: 取字符串 <text> 中的第<n>个单词 (n从1开始)返回: <text> 中的第<n>个单词, 如果<n> ⽐ <text> 中单词个数要⼤, 则返回空字符串# Makefile 内容all:@echo $(word 1,aa bb cc dd)@echo $(word 5,aa bb cc dd)@echo $(word 4,aa bb cc dd)# bash 中执⾏make$ makeaadd取单词串函数: $(wordlist <s>,<e>,<text>)功能: 从字符串<text>中取从<s>开始到<e>的单词串. <s>和<e>是⼀个数字.返回: 从<s>到<e>的字符串# Makefile 内容all:@echo $(wordlist 1,3,aa bb cc dd)@echo $(word 5,6,aa bb cc dd)@echo $(word 2,5,aa bb cc dd)# bash 中执⾏make$ makeaa bb ccbb单词个数统计函数: $(words <text>)功能: 统计字符串 <text> 中单词的个数返回: 单词个数# Makefile 内容all:@echo $(words aa bb cc dd)@echo $(words aabbccdd)@echo $(words )# bash 中执⾏make$ make41⾸单词函数: $(firstword <text>)功能: 取字符串 <text> 中的第⼀个单词返回: 字符串 <text> 中的第⼀个单词# Makefile 内容all:@echo $(firstword aa bb cc dd)@echo $(firstword aabbccdd)@echo $(firstword )# bash 中执⾏make$ makeaaaabbccdd3.4.2 ⽂件名函数取⽬录函数: $(dir <names...>)功能: 从⽂件名序列 <names> 中取出⽬录部分返回: ⽂件名序列 <names> 中的⽬录部分# Makefile 内容all:@echo $(dir /home/a.c ./bb.c ../c.c d.c)# bash 中执⾏make$ make/home/ ./ ../ ./取⽂件函数: $(notdir <names...>)功能: 从⽂件名序列 <names> 中取出⾮⽬录部分返回: ⽂件名序列 <names> 中的⾮⽬录部分# Makefile 内容all:@echo $(notdir /home/a.c ./bb.c ../c.c d.c)# bash 中执⾏make$ makea.c bb.cc.cd.c取后缀函数: $(suffix <names...>)功能: 从⽂件名序列 <names> 中取出各个⽂件名的后缀返回: ⽂件名序列 <names> 中各个⽂件名的后缀, 没有后缀则返回空字符串# Makefile 内容all:@echo $(suffix /home/a.c ./b.o ../c.a d)# bash 中执⾏make$ make.c .o .a取前缀函数: $(basename <names...>)功能: 从⽂件名序列 <names> 中取出各个⽂件名的前缀返回: ⽂件名序列 <names> 中各个⽂件名的前缀, 没有前缀则返回空字符串# Makefile 内容all:@echo $(basename /home/a.c ./b.o ../c.a /home/.d .e)# bash 中执⾏make$ make/home/a ./b ../c /home/加后缀函数: $(addsuffix <suffix>,<names...>)功能: 把后缀 <suffix> 加到 <names> 中的每个单词后⾯返回: 加过后缀的⽂件名序列# Makefile 内容all:@echo $(addsuffix .c,/home/a b ./c.o ../d.c)# bash 中执⾏make$ make/home/a.c b.c ./c.o.c ../d.c.c加前缀函数: $(addprefix <prefix>,<names...>)功能: 把前缀 <prefix> 加到 <names> 中的每个单词前⾯返回: 加过前缀的⽂件名序列# Makefile 内容all:@echo $(addprefix test_,/home/a.c b.c ./d.c)# bash 中执⾏make$ maketest_/home/a.c test_b.c test_./d.c连接函数: $(join <list1>,<list2>)功能: <list2> 中对应的单词加到 <list1> 后⾯返回: 连接后的字符串# Makefile 内容all:@echo $(join a b c d,1234)@echo $(join a b c d,12345)@echo $(join a b c d e,1234)# bash 中执⾏make$ makea1 b2 c3 d4a1 b2 c3 d4 5a1 b2 c3 d4 e3.4.3 foreach语法:$(foreach <var>,<list>,<text>)⽰例:# Makefile 内容targets := a b c dobjects := $(foreach i,$(targets),$(i).o)all:@echo $(targets)@echo $(objects)# bash 中执⾏make$ makea b c da.ob.oc.od.o3.4.4 if这⾥的if是个函数, 和前⾯的条件判断不⼀样, 前⾯的条件判断属于Makefile的关键字语法:$(if <condition>,<then-part>)$(if <condition>,<then-part>,<else-part>)⽰例:# Makefile 内容val := aobjects := $(if $(val),$(val).o,nothing)no-objects := $(if $(no-val),$(val).o,nothing)all:@echo $(objects)@echo $(no-objects)# bash 中执⾏make$ makea.onothing3.4.5 call - 创建新的参数化函数语法:$(call <expression>,<parm1>,<parm2>,<parm3>...)⽰例:# Makefile 内容log = "====debug====" $(1) "====end===="all:@echo $(call log,"正在 Make")# bash 中执⾏make$ make====debug==== 正在 Make ====end====3.4.6 origin - 判断变量的来源语法:$(origin <variable>)返回值有如下类型:类型含义undefined<variable> 没有定义过default<variable> 是个默认的定义, ⽐如 CC 变量environment<variable> 是个环境变量, 并且 make时没有使⽤ -e 参数file<variable> 定义在Makefile中command line<variable> 定义在命令⾏中override<variable> 被 override 重新定义过automatic<variable> 是⾃动化变量⽰例:# Makefile 内容val-in-file := test-fileoverride val-override := test-overrideall:@echo $(origin not-define) # not-define 没有定义@echo $(origin CC) # CC 是Makefile默认定义的变量@echo $(origin PATH) # PATH 是 bash 环境变量@echo $(origin val-in-file) # 此Makefile中定义的变量@echo $(origin val-in-cmd) # 这个变量会加在make的参数中@echo $(origin val-override) # 此Makefile中定义的override变量@echo $(origin @) # ⾃动变量, 具体前⾯的介绍# bash 中执⾏make$ make val-in-cmd=val-cmdundefineddefaultenvironmentfilecommand lineoverrideautomatic3.4.7 shell语法:$(shell <shell command>)它的作⽤就是执⾏⼀个shell命令, 并将shell命令的结果作为函数的返回.作⽤和 `<shell command>` ⼀样, ` 是反引号3.4.8 make 控制函数产⽣⼀个致命错误: $(error <text ...>)功能: 输出错误信息, 停⽌Makefile的运⾏# Makefile 内容all:$(error there is an error!)@echo "这⾥不会执⾏!"# bash 中执⾏make$ makeMakefile:2: *** there is an error!. Stop.输出警告: $(warning <text ...>)功能: 输出警告信息, Makefile继续运⾏# Makefile 内容all:$(warning there is an warning!)@echo "这⾥会执⾏!"# bash 中执⾏make$ makeMakefile:2: there is an warning!这⾥会执⾏!3.5 Makefile中⼀些GNU约定俗成的伪⽬标如果有过在Linux上, 从源码安装软件的经历的话, 就会对 make clean, make install ⽐较熟悉.像 clean, install 这些伪⽬标, ⼴为⼈知, 不⽤解释就⼤家知道是什么意思了.下⾯列举⼀些常⽤的伪⽬标, 如果在⾃⼰项⽬的Makefile合理使⽤这些伪⽬标的话, 可以让我们⾃⼰的Makefile看起来更专业, 呵呵 :)伪⽬标含义all所有⽬标的⽬标,其功能⼀般是编译所有的⽬标clean删除所有被make创建的⽂件install安装已编译好的程序,其实就是把⽬标可执⾏⽂件拷贝到指定的⽬录中去print列出改变过的源⽂件tar把源程序打包备份. 也就是⼀个tar⽂件dist创建⼀个压缩⽂件, ⼀般是把tar⽂件压成Z⽂件. 或是gz⽂件TAGS更新所有的⽬标, 以备完整地重编译使⽤check 或 test⼀般⽤来测试makefile的流程。
通用makefile模板
############################################################# # Generic Makefile for C/C++ Program## License: GPL (General Public License)# Author: whyglinux <whyglinux AT gmail DOT com># Date: 2006/03/04 (version 0.1)# 2007/03/24 (version 0.2)# 2007/04/09 (version 0.3)# 2007/06/26 (version 0.4)# 2008/04/05 (version 0.5)## 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# may or may not work.## Usage:# ------# 1. Copy the Makefile to your program directory.# 2. Customize in the "Customizable Section" only if necessary:# * to use non-standard C/C++ libraries, set pre-processor or compiler# options to <MY_CFLAGS> and linker ones to <MY_LIBS># (See Makefile.gtk+-2.0 for an example)# * to search sources in more directories, set to <SRCDIRS># * to specify your favorite program name, set to <PROGRAM># 3. Type make to start building your program.## Make Target:# ------------# The Makefile provides the following targets to make:# $ make compile and link# $ make NODEP=yes compile and link without generating dependencies # $ make objs compile only (no linking)# $ make tags create tags for Emacs editor# $ make ctags create ctags for VI editor# $ make clean clean objects and the executable file# $ make distclean clean objects, the executable and dependencies# $ make help get the usage of the makefile##========================================================== =================## Customizable Section: adapt those variables to suit your program.##========================================================= =================# The pre-processor and compiler options.MY_CFLAGS =# The linker options.MY_LIBS =# The pre-processor options used by the cpp (man cpp for more). CPPFLAGS = -Wall# The options used in linking as well as in any direct use of ld.LDFLAGS =# The directories in which source files reside.# If not specified, only the current directory will be serached.SRCDIRS =# The executable file name.# If not specified, current directory name or `a.out' will be used.PROGRAM =## Implicit Section: change the following only when necessary.##========================================================= =================# The source file types (headers excluded).# .c indicates C source files, and others C++ ones.SRCEXTS = .c .C .cc .cpp .CPP .c++ .cxx .cp# The header file types.HDREXTS = .h .H .hh .hpp .HPP .h++ .hxx .hp# The pre-processor and compiler options.# Users can override those variables from the command line.CFLAGS = -g -O2CXXFLAGS= -g -O2# The C program compiler.#CC = gcc# The C++ program compiler.#CXX = g++# Un-comment the following line to compile C programs as C++ ones.#CC = $(CXX)# The command used to delete file.#RM = rm -fETAGS = etagsETAGSFLAGS =CTAGS = ctagsCTAGSFLAGS =## Stable Section: usually no need to be changed. But you can add more.##========================================================= =================SHELL = /bin/shEMPTY =SPACE = $(EMPTY) $(EMPTY)ifeq ($(PROGRAM),)CUR_PATH_NAMES = $(subst /,$(SPACE),$(subst $(SPACE),_,$(CURDIR)))PROGRAM = $(word $(words $(CUR_PATH_NAMES)),$(CUR_PATH_NAMES))ifeq ($(PROGRAM),)PROGRAM = a.outendifendififeq ($(SRCDIRS),)SRCDIRS = .endifSOURCES = $(foreach d,$(SRCDIRS),$(wildcard $(addprefix$(d)/*,$(SRCEXTS))))HEADERS = $(foreach d,$(SRCDIRS),$(wildcard $(addprefix $(d)/*,$(HDREXTS))))SRC_CXX = $(filter-out %.c,$(SOURCES))OBJS = $(addsuffix .o, $(basename $(SOURCES)))DEPS = $(OBJS:.o=.d)## Define some useful variables.DEP_OPT = $(shell if `$(CC) --version | grep "GCC" >/dev/null`; then \echo "-MM -MP"; else echo "-M"; fi )DEPEND = $(CC) $(DEP_OPT) $(MY_CFLAGS) $(CFLAGS) $(CPPFLAGS)DEPEND.d = $(subst -g ,,$(DEPEND))COMPILE.c = $(CC) $(MY_CFLAGS) $(CFLAGS) $(CPPFLAGS) -c COMPILE.cxx = $(CXX) $(MY_CFLAGS) $(CXXFLAGS) $(CPPFLAGS) -c LINK.c = $(CC) $(MY_CFLAGS) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS)LINK.cxx = $(CXX) $(MY_CFLAGS) $(CXXFLAGS) $(CPPFLAGS) $(LDFLAGS).PHONY: all objs tags ctags clean distclean help show# Delete the default suffixes.SUFFIXES:all: $(PROGRAM)# Rules for creating dependency files (.d).#------------------------------------------%.d:%.c@echo -n $(dir $<) > $@@$(DEPEND.d) $< >> $@%.d:%.C@echo -n $(dir $<) > $@@$(DEPEND.d) $< >> $@%.d:%.cc@echo -n $(dir $<) > $@@$(DEPEND.d) $< >> $@%.d:%.cpp@echo -n $(dir $<) > $@@$(DEPEND.d) $< >> $@%.d:%.CPP@echo -n $(dir $<) > $@@$(DEPEND.d) $< >> $@%.d:%.c++@echo -n $(dir $<) > $@@$(DEPEND.d) $< >> $@%.d:%.cp@echo -n $(dir $<) > $@@$(DEPEND.d) $< >> $@%.d:%.cxx@echo -n $(dir $<) > $@@$(DEPEND.d) $< >> $@# Rules for generating object files (.o). #---------------------------------------- objs:$(OBJS)%.o:%.c$(COMPILE.c) $< -o $@%.o:%.C$(COMPILE.cxx) $< -o $@%.o:%.cc$(COMPILE.cxx) $< -o $@%.o:%.cpp$(COMPILE.cxx) $< -o $@%.o:%.CPP$(COMPILE.cxx) $< -o $@%.o:%.c++$(COMPILE.cxx) $< -o $@%.o:%.cp$(COMPILE.cxx) $< -o $@%.o:%.cxx$(COMPILE.cxx) $< -o $@# Rules for generating the tags.#-------------------------------------tags: $(HEADERS) $(SOURCES)$(ETAGS) $(ETAGSFLAGS) $(HEADERS) $(SOURCES)ctags: $(HEADERS) $(SOURCES)$(CTAGS) $(CTAGSFLAGS) $(HEADERS) $(SOURCES)# Rules for generating the executable.#-------------------------------------$(PROGRAM):$(OBJS)ifeq ($(SRC_CXX),) # C program$(LINK.c) $(OBJS) $(MY_LIBS) -o $@@echo Type ./$@ to execute the program.else # C++ program$(LINK.cxx) $(OBJS) $(MY_LIBS) -o $@@echo Type ./$@ to execute the program.endififndef NODEPifneq ($(DEPS),)sinclude $(DEPS)endifendifclean:$(RM) $(OBJS) $(PROGRAM) $(PROGRAM).exedistclean: clean$(RM) $(DEPS) TAGS# Show help.help:@echo 'Generic Makefile for C/C++ Programs (gcmakefile) version 0.5' @echo 'Copyright (C) 2007, 2008 whyglinux <whyglinux@>' @echo@echo 'Usage: make [TARGET]'@echo 'TARGETS:'@echo ' all (=make) compile and link.'@echo ' NODEP=yes make without generating dependencies.'@echo ' objs compile only (no linking).'@echo ' tags create tags for Emacs editor.'@echo ' ctags create ctags for VI editor.'@echo ' clean clean objects and the executable file.'@echo ' distclean clean objects, the executable and dependencies.'@echo ' show show variables (for debug use only).'@echo ' help print this message.'@echo@echo 'Report bugs to <whyglinux AT gmail DOT com>.'# Show variables (for debug use only.)show:@echo 'PROGRAM :' $(PROGRAM)@echo 'SRCDIRS :' $(SRCDIRS)@echo 'HEADERS :' $(HEADERS)@echo 'SOURCES :' $(SOURCES)@echo 'SRC_CXX :' $(SRC_CXX)@echo 'OBJS :' $(OBJS)@echo 'DEPS :' $(DEPS)@echo 'DEPEND :' $(DEPEND)@echo 'COMPILE.c :' $(COMPILE.c)@echo 'COMPILE.cxx :' $(COMPILE.cxx)@echo 'link.c :' $(LINK.c)@echo 'link.cxx :' $(LINK.cxx)## End of the Makefile ## Suggestions are welcome ## All rights reserved ################################################################。
makefile call函数
makefile call函数Makefile是一个非常强大的工具,可以用来自动化构建和编译程序。
在Makefile中,call函数是一个非常有用的函数,它可以让我们定义一个可以被多次调用的模板。
在本文中,我们将探讨call 函数的用法和一些实际的例子。
1. call函数的语法call函数的语法如下:$(call variable,param1,param2,...)其中,variable是一个已经定义的变量名,param1、param2等是传递给变量的参数。
当调用call函数时,它将会把variable中的值作为一个模板,然后把传递的参数替换到模板中的$(1)、$(2)等位置上。
最后,call函数返回替换后的字符串。
2. call函数的实际应用2.1 定义可重用的命令在Makefile中,我们通常需要定义一些命令,比如编译、链接、打包等。
这些命令可能会被多次使用,如果每次都写一遍的话,会非常麻烦。
这时,我们可以使用call函数来定义一个可重用的命令模板。
例如,我们可以定义一个编译命令模板如下:define compilegcc $(1) -c $(2) -o $(3)endef然后,我们可以在Makefile中调用这个命令模板,传递不同的参数:$(call compile,-Wall,-O2,main.c,main.o)这个命令会被展开为:gcc -Wall -O2 main.c -o main.o这样,我们就可以避免在Makefile中写重复的命令,提高代码的可维护性。
2.2 定义可重用的路径在Makefile中,我们经常需要定义一些路径,比如源代码路径、头文件路径、库文件路径等。
这些路径可能会被多次使用,如果每次都写一遍的话,也会非常麻烦。
这时,我们可以使用call函数来定义一个可重用的路径模板。
例如,我们可以定义一个源代码路径模板如下:define src_dir$(1)/srcendef然后,我们可以在Makefile中调用这个路径模板,传递不同的参数:$(call src_dir,my_project)这个路径会被展开为:my_project/src这样,我们就可以避免在Makefile中写重复的路径,提高代码的可维护性。
makefile 中$(shell )用法
makefile 中$(shell )用法标题:Makefile中的$(shell )用法详解在编程中,自动化是提高效率的关键。
而在C/C++的开发过程中,Makefile是一个非常重要的工具,它可以自动编译和链接源代码,极大地提高了开发效率。
本文将详细讲解Makefile中的一个重要命令$(shell),并结合实例说明其用法。
一、$(shell)的基本概念在Makefile中,$(shell)是一个内置函数,它的功能是执行shell命令,并将命令的结果返回。
例如:```foo = $(shell echo hello world)```在这个例子中,`$(shell echo hello world)`会被替换为"hello world"。
二、$(shell)的应用场景1. 获取系统信息:$(shell)可以用来获取系统的相关信息,如当前的时间、日期、用户名等。
例如:```time=$(shell date +%T)user=$(shell whoami)```2. 调用其他命令或脚本:$(shell)可以调用其他命令或脚本来完成一些复杂的任务。
例如:```files=$(shell find . -name "*.c")```3. 在规则中使用:$(shell)也可以直接在规则中使用,用于动态生成依赖文件或者目标文件。
例如:```foo:@echo "Compiling $@..."$(CC) -o $@ $(shell echo *.c)```三、$(shell)的注意事项虽然$(shell)的功能强大,但在使用时也需要注意一些问题。
1. 执行速度:由于$(shell)需要启动一个子shell来执行命令,因此如果频繁使用,可能会对性能产生影响。
所以在可能的情况下,尽量减少$(shell)的使用。
2. 命令输出:$(shell)会捕获命令的标准输出,但不会捕获标准错误输出。
makefile 冒号的用法
Makefile 冒号的用法
在Makefile中,冒号(:)主要有两种用法:
规则中的冒号:在Makefile的规则中,冒号用于分隔目标文件和依赖项。
规则的格式为“目标文件:依赖项1 依赖项2 ... 命令”。
其中,目标文件是规则要生成的文件,依赖项是目标文件所依赖的其他文件,命令是用于生成目标文件的命令。
例如,下面的规则表示当目标文件“foo.o”发生变化时,执行命令“gcc -c foo.c”来重新生成它:
makefile
foo.o: foo.c
gcc -c foo.c
双冒号规则中的冒号:在Makefile中,双冒号规则是一种特殊的规则,用于指定当多个文件具有相同的依赖项时,如何执行不同的命令来生成目标文件。
双冒号规则的格式为“目标文件:: 依赖项1 依赖项2 ... 命令”。
例如,下面的规则表示当“foo.c”或“bar.c”发生变化时,分别执行不同的命令来重新生成“Newprog”目标文件:
makefile
Newprog :: foo.c $(CC) $(CFLAGS) $< -o $@
Newprog :: bar.c $(CC) $(CFLAGS) $< -o $@
在双冒号规则中,当同一个目标出现在多个规则中时,会按照规则的书写顺序执行。
因此,在上面的例子中,如果“foo.c”发生变化,将执行第一个规则重新生成“Newprog”,然后执行第二个规则重新生成“Newprog”,因为“bar.c”没有被修改。
总结起来,冒号在Makefile中有两种主要用法:一种是用于分隔目标文件
和依赖项的普通规则中的冒号,另一种是用于指定多个规则中如何执行不同命令的双冒号规则中的冒号。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
1 通用Makefile——1实现的功能:•make——编译和连接程序•make objs——编译程序,生成目标文件•make clean——清除编译产生的目标文件(*.o)和依赖文件(*.d)•make cleanall——清除目标文件(*.o)、依赖文件(*.d)和可执行文件(*.exe)•make rebuild——重新编译连接程序,相当于make clean && makeUsage:Makefile源代码# Gneric C/C++ Makefile####################################################PROGRAM :=SRCDIRS :=SRCEXTS :=CPPFLAGS :=CFLAGS :=CFLAGS +=CXXFLAGS :=CXXFLAGS +=LDFLAGS :=LDFLAGS +=SHELL = /bin/shSOURCES = $(foreach d,$(SRCDIRS),$(wildcard $(addprefix $(d)/*,$(SRCEXTS)))) OBJS = $(foreach x,$(SRCEXTS),\$(patsubst %$(x),%.o,$(filter %$(x),$(SOURCES))))DEPS = $(patsubst %.o,%.d,$(OBJS)).PHONY: all objs clean cleanall rebuildall : $(PROGRAM)%.d : %.c@$(CC) -MM -MD $(CFLAGS) {1}lt;%.d : %.C@$(CC) -MM -MD $(CXXFLAGS) {1}lt;objs : $(OBJS)%.o : %.c$(CC) -c $(CPPFLAGS) $(CFLAGS) {1}lt;%.o : %.cpp$(CXX) -c $(CPPFLAGS) $(CXXFLAGS) {1}lt;$(PROGRAM) : $(OBJS)ifeq ($(strip $(SRCEXTS)),.c)$(CC) -o $(PROGRAM) $(OBJS) $(LDFLAGS)else$(CXX) -o $(PROGRAM) $(OBJS) $(LDFLAGS)endif-include $(DEPS)rebuild: clean callclean:@$(RM) *.o *.dcleanall: clean@$(RM) $(PROGRAM) $(PROGRAM).exe2 通用Makefile——2############################################################################### ## Generic Makefile for C/C++ Program## Author: whyglinux (whyglinux AT hotmail DOT com)# Date: 2006/03/04# Description:# The makefile searches in <SRCDIRS> directories for the source files# with extensions specified in <SOURCE_EXT>, then compiles the sources# and finally produces the <PROGRAM>, the executable file, by linking# the objectives.# Usage:# $ make compile and link the program.# $ make objs compile only (no linking. Rarely used).# $ make clean clean the objectives and dependencies.# $ make cleanall clean the objectives, dependencies and executable.# $ make rebuild rebuild the program. The same as make clean && make all.#===================================================================== =========## Customizing Section: adjust the following if necessary.##==================================================================== =========# The executable file name.# It must be specified.# PROGRAM := a.out # the executable namePROGRAM :=# The directories in which source files reside.# At least one path should be specified.# SRCDIRS := . # current directorySRCDIRS :=# The source file types (headers excluded).# At least one type should be specified.# The valid suffixes are among of .c, .C, .cc, .cpp, .CPP, .c++, .cp, or .cxx.# SRCEXTS := .c # C program# SRCEXTS := .cpp # C++ program# SRCEXTS := .c .cpp # C/C++ programSRCEXTS :=# The flags used by the cpp (man cpp for more).# CPPFLAGS := -Wall -Werror # show all warnings and take them as errorsCPPFLAGS :=# The compiling flags used only for C.# If it is a C++ program, no need to set these flags.# If it is a C and C++ merging program, set these flags for the C parts.CFLAGS :=CFLAGS +=# The compiling flags used only for C++.# If it is a C program, no need to set these flags.# If it is a C and C++ merging program, set these flags for the C++ parts.CXXFLAGS :=CXXFLAGS +=# The library and the link options ( C and C++ common).LDFLAGS :=LDFLAGS +=## Implict Section: change the following only when necessary.##==================================================================== =========# The C program compiler. Uncomment it to specify yours explicitly.#CC = gcc# The C++ program compiler. Uncomment it to specify yours explicitly.#CXX = g++# Uncomment the 2 lines to compile C programs as C++ ones.#CC = $(CXX)#CFLAGS = $(CXXFLAGS)# The command used to delete file.#RM = rm -f## Stable Section: usually no need to be changed. But you can add more.##==================================================================== =========SHELL = /bin/shSOURCES = $(foreach d,$(SRCDIRS),$(wildcard $(addprefix $(d)/*,$(SRCEXTS))))OBJS = $(foreach x,$(SRCEXTS), \$(patsubst %$(x),%.o,$(filter %$(x),$(SOURCES))))DEPS = $(patsubst %.o,%.d,$(OBJS)).PHONY : all objs clean cleanall rebuildall : $(PROGRAM)# Rules for creating the dependency files (.d).#---------------------------------------------------%.d : %.c@$(CC) -MM -MD $(CFLAGS) $<%.d : %.C@$(CC) -MM -MD $(CXXFLAGS) $<%.d : %.cc@$(CC) -MM -MD $(CXXFLAGS) $<%.d : %.cpp@$(CC) -MM -MD $(CXXFLAGS) $<%.d : %.CPP@$(CC) -MM -MD $(CXXFLAGS) $<%.d : %.c++@$(CC) -MM -MD $(CXXFLAGS) $<%.d : %.cp@$(CC) -MM -MD $(CXXFLAGS) $<%.d : %.cxx@$(CC) -MM -MD $(CXXFLAGS) $<# Rules for producing the objects.#---------------------------------------------------objs : $(OBJS)%.o : %.c$(CC) -c $(CPPFLAGS) $(CFLAGS) $<%.o : %.C$(CXX) -c $(CPPFLAGS) $(CXXFLAGS) $<%.o : %.cc$(CXX) -c $(CPPFLAGS) $(CXXFLAGS) $<%.o : %.cpp$(CXX) -c $(CPPFLAGS) $(CXXFLAGS) $<%.o : %.CPP$(CXX) -c $(CPPFLAGS) $(CXXFLAGS) $<%.o : %.c++$(CXX -c $(CPPFLAGS) $(CXXFLAGS) $<%.o : %.cp$(CXX) -c $(CPPFLAGS) $(CXXFLAGS) $<%.o : %.cxx$(CXX) -c $(CPPFLAGS) $(CXXFLAGS) $<# Rules for producing the executable.#---------------------------------------------- $(PROGRAM) : $(OBJS)ifeq ($(strip $(SRCEXTS)), .c) # C file$(CC) -o $(PROGRAM) $(OBJS) $(LDFLAGS) else # C++ file$(CXX) -o $(PROGRAM) $(OBJS) $(LDFLAGS) endif-include $(DEPS)rebuild: clean allclean :@$(RM) *.o *.dcleanall: clean@$(RM) $(PROGRAM) $(PROGRAM).exe### End of the Makefile ## Suggestions are welcome ## All rights reserved ################################################################################## 下面提供两个例子来具体说明上面 Makefile 的用法。