Makefile语法学习_第1页
Makefile语法学习_第2页
Makefile语法学习_第3页
Makefile语法学习_第4页
Makefile语法学习_第5页
已阅读5页,还剩2页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、读书破万卷下笔如有神Makefile 语法学习有稍稍在Linux下碰过程序设计的开发者应该会知道,make是用来将程序代码、函式库、头文件及其它资源文件build成最终成果(即:最终的应用程序)的超强力辅助工具。当然了,并不是非得动用到make才能build程序,或许有什么程序设计魔人喜欢什么都自己手动进行;但利用 make及其参考档(输入档案)Make巾le将会让整个编译工作轻松许多。若您曾经打包过Debian Package ,那么应该会发现debuan/rule 这个档案的语法和Makefile几乎是一模一样,所以学习Make巾le的语法对于 Debian PackageMaintain

2、er而言也是一门必要的功课。Makefile 语法:以下为Makefile的基本语法,批注:以#开头的即为批注。变量宣告:(有人称之为宏)语法:MACRO = value注意到,在=前后必须加上空白,而变量名称为大小写相异。利用MACRO =来取消该变数。在惯例上,Makefile内部使用的变量名称使用 小写;而使用者很可能从命令行自行另外指 定数值的变量,像是CFLAGS ,则是使用大写。在Makefile 中,可利用 $(MACRO) 或$MACRO来存取已定义的变量。例:tragets = foo$(targets): common.hgcc -o $(targets) foo.c效果等

3、同:foo: common.h gcc -o foo foo.c:=语法注意到,make会将整个 Makefile展开后,再决定变数的值。也就是说,变量的值将会是 整个MacMle中最后被指定的值。例:x = fooy = $(x) barx = xyz# y的值为xyz bar在上例中,y的值将会是 xyz bar ,而不是 foo bar。您可以利用:=来避开这个问题。:=表示变量的值决定于它在Make巾le中的位置,而不是整个Makefile展开后最终的值。x := fooy := $(x) barx := xyz# y的值为foo bar在上例中,y的值将会是 foo bar ,而不是

4、xyz bar 了。?二语法:?二是一个简化的语法:若变量未定义,则替它指定新的值。否则,采用原有的值。例:FOO ?= bar若FOO 未定义,则 FOO = bar ;若FOO 已定义,则 FOO 的值维持不变。+=语法:例:CFLAGS = -Wall -gCFLAGS += -O2此时 CFLAGS 的值就变成 -Wall-g -O2 了。define 语法:使用define语法的唯一优点是它可以让变量直接使用断行。例:define foouname -aecho $SHELLendef all:$(foo)上例可以视同于:foo = uname -a; echo $SHELLall:

5、$(foo)注意到在上例中使用了$,让$'能传到Shell中。在target里另外指定变量的值可以在target里另外指定变量的值。例:foo = abcall: foo = xyzall:echo $(foo)#此时,foo的值为 xyz以下的语法提供了和上例相同的功能:all: override foo = xyzall: export foo = xyzmake也可以存取环境变量。例:all:echo $(CFLAGS)在上例中,虽然在 Makefile里虽然没有指定 CFLAGS 的值,但 make会试图以环境变 量来代出 CFLAGS 的值。可搭配 wildcard指令在变量

6、里展开* ?等通配符。例:objects=$(wildcard *.o)规则:(Rule)指示 make如何进行编译。主要语法:target: dependencies <Tab>Commands或target: dependencies; Commands<Tab>CommandsRule指示了 make如何建立target ;及何时要重新建立target。target :所要建立的档案dependencies :相依项目。make 会据此决定是否要重新编译target。Commands :建立 target 的指令。在Makefile 里并没有限定 Rule的先后顺

7、序。但默认上,make会参考all这个目标项目,并依据它的 dependencies 来决定要建立哪些项目。若没有 all项目,则会采用 Makefile 里的第一个项目。target :(目标项目)这个项目所要建立的档案,必须以:结尾。例:foo.o: common.hgcc -c foo.c其中,foo.o是这个项目要建立的档案;common.h 是相依性的项目/档案;而 gcc -c foo.c则为要产生这个项目所要执行的指令。make在编译时,若发现 target比较新,也就是 dependencies者B比target旧,那么将 不会重新建立target ,如此可以避免不必要的编译动

8、作。若该项目并非档案,则为fake项目。如此一来将不会建立target档案。但为了避免 make有时会无去判断 target是否为档案或 fake项目,建议利用.PHONY 来指定该项目为 fake项目。例:.PHONY: cleanclean:rm *.o在上例中,若不使用.PHONY 来指定clean为fake项目的话,若目录中同时存在了一 个名为clean的档案,则clean这个项目将被视为 要建立clean这个档案,但clean这 个项目却又没有任何的dependencies ,也因此,clean项目将永远被视为up-to-date ,永远不会被执行。因为利用了 .PHONY 来指定c

9、lean为fake项目,所以 make不会去检查目录中是否存 在了一个名为 clean的档案。如此也可以提升make的执行效率。其它类以.PHONY 的语法请参考:GNU 'make': 4.9 Special Built-in Target Names另外,如果某个非fake 项目里的 dependencies 包含了 fake项目的话,因为 make 一定会执行fake项目,这样一来,这个非 fake项目一定也会被执行。这可能不是理想的做 法。dependencies :(相依性项目,以空白间隔)dependencies 是指定在建立 target之前,必须先检查的项目。可

10、以不指定。例: foo.o: common.hgcc -c foo.c上例中是指:检查 common.h 。如果它的建立日期比 foo.o新,就执行 gcc -c foo.c 来重 新产生foo.o。也就是说,可以依需求建立 dependencies ,即使它和target 一点关系也没 有。相依性项目可以是Makefile中其它的target。也因此,在建立该target之前,它会先检查在 dependencies 里所指定的所有 target。Commands :(即为要执行的 Shell指令)必须以Tab开头。使用 Shell Script 语法。在 Makefile 里,只要以 Tab

11、开头都将 会被视为Shell Script 执行。每条法则必须写在同一行。每条 Command 会启动一个新的Shell ,预设为/bin/sh。若执 行完某条Command但传回了错误值,make就会中断执行。因为每条Command 会启动一个新的Shell ,所以有时执行的指令必须写在同一行,像是 使用if来进行条件判断,此时可以用;来分隔指令。例:all:if -f foo ; then rm foo;fi而以下是错误示范:all:cd subdir; $(MAKE)这时因为make只会检查最后一个指令的传回值,所以在以上指令中,即使 subdir不存 在,但make并不会因而中断执行,

12、并会继续执行$(MAKE)指令,而产生了不可预期的结果。为了避免这个问题,可以利用 &&来检查其中某个指令是否成功执行,再决定是否执行下 个指令。例:all:cd subdir && $(MAKE)特别字符: :不要显示执行的指令。-:表示即使该行指令出错,也不会中断执行。例:.PHONY: cleanclean:echo "Clean."-rm *.o因为make会一行一行将正在执行的Commands 显示在屏幕上,但您可以利用 来暂时关闭这个功能。而make只要遇到任何错误就会中断执行。但像是在进行clean时,也许根本没有任何档案可以c

13、lean ,因而rm会传回错误值,因而导致 make中断执行。我们可以利用-来关闭错误中断功能,让 make不会因而中断。隐性法则:在上例中的:foo.o: common.hgcc -c foo.c由于产生foo.o的指令就是 gcc -c foo.c ,因此在 Makefile 里可以将其简化为:foo.o: common.h此时 make会依据target的扩展名来猜测该如何编译target。如此可以让 Makefile更为简洁。您可以利用【空白指令】来避免 make依据隐性法则而进行编译。例:foo.o: common.h<Tab>内部变数:代表已被更新的 dependenc

14、ies 的值。$?:也就是 dependencies 中,比 tragets 还新的值。$:代表tragets的值。$<:代表第一个 dependencies 的值。$* : 代表tragets所指定的档案,但不包含扩展名。例:print: foo1.c foo2.c foo3.c lpr -p $?touch print这样会将fool.c foo2.c foo3.c中已有更新的内容印至打印机。内部函数:您可以在Make巾le使用make所支持的一些内部函数。详情请参考:GNU 'make': 8 Functions for Transforming Text条件判断:

15、可以在Makefile中使用以下的条件判断语法。但由于它们不是rule ,所以不可以 <Tab>开头;但其后要执行的指令则必须以<Tab>开头,make才会视其为 Shell指令。ifeq :(检查 value1, value2 是否相等)ifeq (value1, value2) else endif ifneq :(提供和ifeq相反的功能)ifneq (value1, value2) else endififdef :(检查 variable变量是否为空的)ifdef variable.else.endififndef:(提供和ifdef相反的功能)ifdef v

16、ariable.else.endif引入档案:将外部档案引入Makefile中。可以视为直接在此将该档案全数插入Makefile中。例:include foo.in将foo.in的内容全数引入Make巾le 里。可以同时引入多个档案、使用变量$(MACRO)或是使用通配符(* ?或.)。例:include foo.in common*.in $(MAKEINCS)子目录:如果该项目有多个目录,且每一个目录中都有Makefile ,则利用以下指令来进入子目录并进行编译:cd dir;$(MAKE)例:SUBDIRS = diri dir2 dir3all:for i in $(SUBDIRS); do(cd $i; make); doneclean:for i in $(SUBDIRS); do(cd $i; make clean); doneinstall:

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论