分享
 
 
 

GNU Make 使用手册!(5)

王朝other·作者佚名  2006-02-01
窄屏简体版  字體: |||超大  

在条件指令ifneq中用函数调用‘$(strip $(needs_made))'代替变量引用‘$(needs_made)'将不再出现问题。

$(findstring find,in)

在字符串‘in’中搜寻‘find’,如果找到,则返回值是‘find’,否则返回值为空。您可以在一个条件中使用该函数测试给定的字符串中是否含有特定的子字符串。这样,下面两个例子:

$(findstring a,a b c)

$(findstring a,b c)

将分别产生值‘a’和‘’。对于函数findstring的特定用法参阅测试标志的条件语句。

$(filter pattern...,text)

返回在‘text’中由空格隔开且匹配格式‘pattern...’的字,对于不符合格式‘pattern...’的字移出。格式用‘%’写出,和前面论述过的函数patsubst的格式相同。函数filter可以用来变量分离类型不同的字符串。例如:

sources := foo.c bar.c baz.s ugh.h

foo: $(sources)

cc $(filter

%.c %.s,$(sources)) -o foo

表明‘foo' 依靠‘foo.c',‘bar.c',‘baz.s' 和‘ugh.h';但仅有‘foo.c',‘bar.c' 和 ‘baz.s' 指明用命令编译。

$(filter-out pattern...,text)

返回在‘text’中由空格隔开且不匹配格式‘pattern...’的字,对于符合格式‘pattern...’的字移出。只是函数filter的反函数。例如:

objects=main1.o foo.o main2.o bar.o

mains=main1.o main2.o

下面产生不包含在变量‘mains’中的OBJ文件的文件列表:

$(filter-out $(mains),$(objects))

$(sort list)

将‘list’中的字按字母顺序排序,并取掉重复的字。输出是由单个空格隔开的字的列表。

$(sort foo bar lose)

返回值是‘bar foo lose’。顺便提及,由于函数sort可以取掉重复的字,您就是不关心排序也可以使用它的这个特点。

这里有一个实际使用函数subst和patsubst的例子。假设一个makefile文件使用变量VPATH指定make搜寻依赖文件的一系列路径(参阅VPATH:依赖搜寻路径)。这个例子表明怎样告诉C编译器在相同路径列表中搜寻头文件。

变量VPATH的值是一列用冒号隔开的路径名,如‘src:../headers'。首先,函数subst将冒号变为空格:

$(subst :, ,$(VPATH))

这产生值‘src ../headers'。然后,函数patsubst为每一个路径名加入‘-|’标志,这样这些路径可以加到变量CFLAGS中,就可以自动传递给C编译器:

override CFLAGS += $(patsubst

%,-I%,$(subst :, ,$(VPATH)))

结果是在以前给定的变量CFLAGS的值后追加文本‘-Isrc

-I../headers’。Override指令的作用是即使以前使用命令参数指定变量CFLAGS的值,新值也能起作用。参阅override指令。

8.3文件名函数

其中几个内建的扩展函数和拆分文件名以及列举文件名相关联。下面列举的函数都能执行对文件名的特定转换。函数的参数是一系列的文件名,文件名之间用空格隔开(前导和结尾空格被忽略)。列表中的每一个文件名都采用相同的方式转换,而且结果用单个空格串联在一起。

$(dir names...)

抽取‘names’中每一个文件名的路径部分,文件名的路径部分包括从文件名的开始到最后一个斜杠(含斜杠)之前的一切字符。如果文件名中没有斜杠,路径部分是‘./’。如:

$(dir src/foo.c hacks)

产生的结果为

‘src/ ./’。

$(notdir names...)

抽取‘names’中每一个文件名中除路径部分外一切字符(真正的文件名)。如果文件名中没有斜杠,则该文件名保持不变,否则,将路径部分移走。一个文件名如果仅包含路径部分(以斜杠结束的文件名)将变为空字符串。这是非常不幸的,因为这意味着在结果中如果有这种文件名存在,两文件名之间的空格将不是由相同多的空格隔开。但现在我们并不能看到其它任何有效的代替品。例如:

$(notdir src/foo.c hacks)

产生的结果为‘foo.c hacks’。

$(suffix names...)

抽取‘names’中每一个文件名的后缀。如果文件名中(或含有斜杠,且在最后一个斜杠后)含有句点,则后缀是最后那个句点以后的所有字符,否则,后缀是空字符串。如果结果为空意味着‘names’没有带后缀文件名,如果文件中含有多个文件名,则结果列出的后缀数很可能比原文件名数目少。例如:

$(suffix src/foo.c src-1.0/bar.c hacks)

产生的结果是‘.c .c’。

$(basename names...)

抽取‘names’中每一个文件名中除后缀外一切字符。如果文件名中(或含有斜杠,且在最后一个斜杠后)含有句点,则基本名字是从开始到最后一个句点(不包含)间的所有字符。如果没有句点,基本名字是整个文件名。例如:

$(basename src/foo.c src-1.0/bar hacks)

产生的结果为‘src/foo src-1.0/bar hacks’。

$(addsuffix suffix,names...)

参数‘names’作为一系列的文件名,文件名之间用空格隔开;suffix作为一个单位。将Suffix(后缀)的值附加在每一个独立文件名的后面,完成后将文件名串联起来,它们之间用单个空格隔开。例如:

$(addsuffix .c,foo bar)

结果为‘foo.c bar.c’。

$(addprefix prefix,names...)

参数‘names’作为一系列的文件名,文件名之间用空格隔开;prefix作为一个单位。将preffix(前缀)的值附加在每一个独立文件名的前面,完成后将文件名串联起来,它们之间用单个空格隔开。例如:

$(addprefix src/,foo bar)

结果为‘src/foo src/bar’。

$(join list1,list2)

将两个参数串联起来:两个参数的第一个字串联起来形成结果的第一个字,两个参数的第二个字串联起来形成结果的第二个字,以此类推。如果一个参数比另一个参数的字多,则多余的字原封不动的拷贝到结果上。例如,‘$(join a b,.c .o)'产生‘a.c b.o'。字之间多余的空格不再保留,它们由单个空格代替。该函数可将函数dir、notdir的结果合并,产生原始给定的文件列表。

$(word n,text)

返回‘text’中的第n个字。N的合法值从1开始。如果n比‘text’中的字的数目大,则返回空值。例如:

$(word 2, foo bar baz)

返回

‘bar’。

$(wordlist s,e,text)

返回‘text’中的从第s个字开始到第e个字结束的一列字。S、e的合法值从1开始。如果s比‘text’中的字的数目大,则返回空值;如果e比‘text’中的字的数目大,则返回从第s个字开始到‘text’结束的所有字;如果s比e大,不返回任何值。例如:

$(wordlist 2, 3, foo bar baz)

返回`bar baz'。

$(words text)

返回‘text’中字的数目。这样‘text’中的最后一个字是‘$(word $(words text),text)’。

$(firstword names...)

参数‘names’作为一系列的文件名,文件名之间用空格隔开;返回第一个文件名,其余的忽略。例如:

$(firstword foo bar)

产生结果‘foo’。 虽然 $(firstword text) 和 $(word 1,text)的作用相同,但第一个函数因为简单而保留下来。

$(wildcard pattern)

参数‘pattern’是一个文件名格式,典型的包含通配符(和shel中的文件名一样)。函数wildcard的结果是一列和格式匹配的且文件存在的文件名,文件名之间用一个空格隔开,参阅在文件名中使用通配符。

8.4函数foreach

函数foreach和其它函数非常不同,它导致一个文本块重复使用,而且每次使用该文本块进行不同的替换;它和shell sh中的命令for及C-shell

csh中的命令foreach类似。

函数foreach语法如下:

$(foreach var,list,text)

前两个参数,‘var’和‘list’,将首先扩展,注意最后一个参数‘text’此时不扩展;接着,对每一个‘list’扩展产生的字,将用来为‘var’扩展后命名的变量赋值;然后‘text’引用该变量扩展;因此它每次扩展都不相同。

结果是由空格隔开的‘text’ 在‘list’中多次扩展的字组成的新的‘list’。‘text’多次扩展的字串联起来,字与字之间由空格隔开,如此就产生了函数foreach的返回值。

这是一个简单的例子,将变量‘files’的值设置为 ‘dirs’中的所有目录下的所有文件的列表:

dirs := a b c d

files := $(foreach dir,$(dirs),$(wildcard

$(dir)/*))

这里‘text’是‘$(wildcard

$(dir)/*)’。第一个为变量dir发现的值是‘a’,所以产生函数foreach结果的第一个字为‘$(wildcard a/*)’;第二个重复的值是‘b’,所以产生函数foreach结果的第二个字为‘$(wildcard b/*)’;第三个重复的值是‘c’,所以产生函数foreach结果的第三个字为‘$(wildcard c/*)’;等等。该例子和下例有共同的结果:

files := $(wildcard a/* b/* c/* d/*)

如果‘text’比较复杂,您可以使用附加变量为它命名,这样可以提高程序的可读性:

find_files = $(wildcard $(dir)/*)

dirs := a b c d

files := $(foreach

dir,$(dirs),$(find_files))

这里我们使用变量find_file。我们定义变量find_file时,使用了‘=’,因此该变量为递归调用型变量,这样变量find_file所包含的函数调用将在函数foreach控制下在扩展;对于简单扩展型变量将不是这样,在变量find_file定义时就调用函数wildcard。

函数foreach对变量‘var’没有长久的影响,它的值和变量特色在函数foreach调用结束后将和前面一样,其它从‘list’得到的值仅在函数foreach执行时起作用,它们是暂时的。变量‘var’在函数foreach执行期间是简单扩展型变量,如果在执行函数foreach之前变量‘var’没有定义,则函数foreach调用后也没有定义。参阅变量的两个特色。

当使用复杂变量表达式产生变量名时应特别小心,因为许多奇怪的字符作为变量名是有效的,但很可能不是您所需要的,例如:

files := $(foreach Esta escrito en espanol!,b c

ch,$(find_files))

如果变量find_file扩展引用名为‘Esta

escrito en espanol!’变量,上例是有效的,但它极易带来错误。

8.5函数if

函数if对在函数上下文中扩展条件提供了支持(相对于GNU make makefile文件中的条件语句,例如ifeq指令,参阅条件语句的语法)。

一个函数if的调用,可以包含两个或三个参数:

$(if condition,then-part[,else-part])

第一个参数‘condition’,首先把前导、结尾空格去掉,然后扩展。如果扩展为非空字符串,则条件‘condition’为‘真’;如果扩展为空字符串,则条件‘condition’为‘假’。

如果条件‘condition’为‘真’,那么计算第二个参数‘then-part’的值,并将该值作为整个函数if的值。

如果条件‘condition’为‘假’,第三个参数如果存在,则计算第三个参数‘else-part’的值,并将该值作为整个函数if的值;如果第三个参数不存在,函数if将什么也不计算,返回空值。

注意仅能计算‘then-part’和‘else-part’二者之一,不能同时计算。这样有可能产生副作用(例如函数shell的调用)。

8.6函数call

函数call是唯一的创建新的带有参数函数的函数。您可以写一个复杂的表达是作为一个变量的值,然后使用函数call用不同的参数调用它。

函数call的语法为:

$(call variable,param,param,...)

当make扩展该函数时,它将每一个参数‘param’赋值给临时变量$(1)、$(2)等;变量$(0)的值是变量‘variable’。对于参数‘param’的数量无没有最大数目限制,也没有最小数目限制,但是如果使用函数call而没有任何参数,其意义不大。

变量‘variable’在这些临时变量的上下文中被扩展为一个make变量,这样,在变量‘variable’中对变量‘$(1)’的引用决定了调用函数call时对第一个参数‘param’的使用。

注意变量‘variable’是一个变量的名称,不是对该变量的引用,所以,您不能采用‘$’和圆括号的格式书写该变量,当然,如果您需要使用非常量的文件名,您可以在文件名中使用变量引用。

如果变量名是内建函数名,则该内建函数将被调用(即使使用该名称的make变量已经存在)。函数call在给临时变量赋值以前首先扩展参数,这意味着,变量‘variable’对内建函数的调用采用特殊的规则进行扩展,象函数foreach或if,它们的扩展结果和您预期的结果可能不同。下面的一些例子能够更清楚的表达这一点。

该例子时使用宏将参数的顺序翻转:

reverse = $(2) $(1)

foo = $(call reverse,a,b)

这里变量foo的值是‘b a’。

下面是一个很有意思的例子:它定义了一个宏,使用该宏可以搜寻变量PATH包含的所有目录中的第一个指定类型的程序:

pathsearch = $(firstword $(wildcard $(addsufix

/$(1),$(subst :, ,$(PATH)))))

LS := $(call pathsearch,ls)

现在变量LS的值是‘/bin/ls’或其它的类似的值。

在函数call中可以使用嵌套。每一次递归调用都可以为它自己的局部变量‘$(1)’等赋值,从而代替上一层函数call赋的值。例如:这实现了映像函数功能。

map = $(foreach a,$(2),$(call $(1),$(a)))

现在您可以映像(map)仅有一个参数的函数,如函数origin,一步得到多个值:

o = $(call map,origin,o map MAKE)

最后变量o包含诸如‘file file default’这样的值。

警告:在函数call的参数中使用空格一定要十分小心。因为在其它函数中,第二个或接下来的参数中的空格是不删除的,这有可能导致非常奇怪的结果。当您使用函数call时,去掉参数中任何多余的空格才是最安全的方法。

8.7函数origin

函数origin不想一般函数,它不对任何变量的值操作;它仅仅告诉您一些关于一个变量的信息;它特别的告诉您变量的来源。

函数origin的语法:

$(origin variable)

注意变量‘variable’是一个查询变量的名称,不是对该变量的引用所以,您不能采用‘$’和圆括号的格式书写该变量,当然,如果您需要使用非常量的文件名,您可以在文件名中使用变量引用。

函数origin的结果是一个字符串,该字符串变量是怎样定义的:

‘undefined'

如果变量‘variable’从没有定义。

‘default'

变量‘variable’是缺省定义,通常和命令CC等一起使用,参阅隐含规则使用的变量。注意如果您对一个缺省变量重新进行了定义,函数origin将返回后面的定义。

‘environment'

变量‘variable’作为环境变量定义,选项‘-e’没有打开(参阅选项概要)。

‘environment override'

变量‘variable’作为环境变量定义,选项‘-e’已打开(参阅选项概要)。

‘file'

变量‘variable’在makefile中定义。

‘command line'

变量‘variable’在命令行中定义。

‘override'

变量‘variable’在makefile中用override指令定义(参阅override指令)。

‘automatic'

变量‘variable’是自动变量,定义它是为了执行每个规则中的命令(参阅自动变量)。

这种信息的基本用途(其它用途是满足您的好奇心)是使您要了解变量值的依据。例如,假设您有一个名为‘foo’的makefile文件,它包含了另一个名为‘bar’的makefile文件,如果在环境变量中已经定义变量‘bletch’,您希望运行命令‘make –f bar’在makefile文件‘bar’中重新定义变量‘bletch’。但是makefile文件‘foo’在包括makefile文件‘bar’之前已经定义了变量‘bletch’,而且您也不想使用override指令定义,那么您可以在makefile文件‘foo’中使用override指令,因为override指令将会重载任何命令行中的定义,所以其定义的优先权超越以后在makefile文件‘bar’中的定义。因此makefile文件‘bar’可以包含:

ifdef bletch

ifeq "$(origin bletch)"

"environment"

bletch = barf, gag, etc.

endif

endif

如果变量‘bletch’在环境中定义,这里将重新定义它。

即使在使用选项‘-e’的情况下,您也要对来自环境的变量‘bletch’重载定义,则您可以使用如下内容:

ifneq "$(findstring environment,$(origin

bletch))" ""

bletch = barf, gag, etc.

endif

如果‘$(origin bletch)’返回‘environment’或‘environment

override’,这里将对变量‘bletch’重新定义。参阅字符串替换和分析函数。

8.8 函数shell

除了函数wildcard之外,函数shell和其它函数不同,它是make与外部环境的通讯工具。函数shell和在大多数shell中后引号(’)执行的功能一样:它用于命令的扩展。这意味着它起着调用shell命令和返回命令输出结果的参数的作用。Make仅仅处理返回结果,再返回结果替换调用点之前,make将每一个换行符或者一对回车/换行符处理为单个空格;如果返回结果最后是换行符(和回车符),make将把它们去掉。由函数shell调用的命令,一旦函数调用展开,就立即执行。在大多数情况下,当makefile文件读入时函数shell调用的命令就已执行。例外情况是在规则命令行中该函数的调用,因为这种情况下只有在命令运行时函数才能扩展,其它调用函数shell的情况和此类似。

这里有一些使用函数shell的例子:

contents := $(shell cat foo)

将含有文件foo的目录设置为变量contents的值,是用空格(而不是换行符)分离每一行。

files := $(shell echo *.c)

将‘*.c’的扩展设置为变量files的值。除非make使用非常怪异的shell,否则这条语句和‘wildcard

*.c’的结果相同。

8.9 控制make的函数

这些函数控制make的运行方式。通常情况下,它们用来向用户提供makefile文件的信息或在侦测到一些类型的环境错误时中断make运行。

$(error text...)

通常‘text’是致命的错误信息。注意错误是在该函数计算时产生的,因此如果您将该函数放在命令的脚本中或递归调用型变量赋值的右边,它直到过期也不能计算。‘text’将在错误产生之前扩展,例如:

ifdef ERROR1

$(error error is $(ERROR1))

endif

如果变量ERROR01已经定义,在将makefile文件读入时产生致命的错误。或,

ERR = $(error found an error!)

.PHONY: err

err: ; $(ERR)

如果err目标被调用,在make运行时产生致命错误。

$(warning text...)

该函数和函数error工作的方式类似,但此时make不退出,即虽然‘text’扩展并显示结果信息,但make仍然继续执行。扩展该函数的结果是空字符串。

9 运行make

讲述编译程序的makefile文件,可以由多种方式实现。最简单的方式是编译所有过期的文件,对于通常所写的makefile文件,如果不使用任何参数运行make,那么将这样执行。

但是您也许仅仅更新一部分文件;您也许需要使用不同的编译器或不同的编译选项;您也许仅仅希望找出过时的文件而不更新它们。这些只有通过在运行make时给出参数才能实现。退出make状态有三种情况:

0

表示make成功完成退出。

2

退出状态为2表示make运行中遇到错误,它将打印信息描述错误。

1

退出状态为1表示您运行make时使用了‘-q’标志,并且make决定一些文件没有更新。参阅代替执行命令。

9.1 指定makefile文件的参数

指定makefile文件名的方法是使用‘-f’或‘--file’选项(‘--makefile’也能工作)。例如,‘-f altmake’说明名为‘altmake’的文件作为makefile文件。

如果您连续使用‘-f’标志几次,而且每一个‘-f’后面都带有参数,则所有指定的文件将连在一起作为makefile文件。

如果您不使用‘-f’或‘--file’选项,缺省的是按次序寻找‘GNUmakefile', ‘makefile', 和 ‘Makefile',使用这三个中第一个能够找到的存在文件或能够创建的文件,参阅编写makefile文件。

9.2指定最终目标的参数

最终目标(gaol)是make最终努力更新的目标。其它更新的目标是因为它们作为最终目标的依赖,或依赖的依赖,等等以此类推。

缺省情况下,makefile文件中的第一个目标是最终目标(不计算那些以句点开始的目标)。因此,makefile文件的第一个编译目标是对整个程序或程序组描述。如果第一个规则同时拥有几个目标,只有该规则的第一个目标是缺省的最终目标。

您可以使用make的参数指定最终目标。方法是使用目标的名字作为参数。如果您指定几个最终目标,make按您命名时的顺序一个接一个的处理它们。

任何在makefile文件中出现的目标都能作为最终目标(除了以‘-’开始或含有‘=’的目标,它们一种解析为开关,另一种是变量定义)。即使在makefile文件中没有出现的目标,按照隐含规则可以说明怎样生成,也能指定为最终目标。

Make将在命令行中使用特殊变量MAKECMGOALS设置您指定的最终目标。如果没有在命令行指定最终目标,该变量的值为空值。注意该变量值能在特殊场合下使用。

一个合适的例子是在清除规则中避免删除包括‘.d’的文件(参阅自动产生依赖),因这样make不会一创建它们,就立即又删除它们:

sources = foo.c bar.c

ifneq ($(MAKECMDGOALS),clean)

include $(sources:.c=.d)

endif

指定最终目标的一个用途是仅仅编译程序的一部分或程序组中的几个程序。如是这样,您可以将您希望变异的文件指定为最终目标。例如,在一个路径下包含几个程序,一个makefile文件以下面的格式开始:

.PHONY: all

all: size nm ld ar as

如果您仅对程序size编译,则您可以使用‘make size’命令,这样就只有您指定的程序才重新编译。

指定最终目标的另一个用途是编译产生哪些没有正常生成的文件。例如,又一个文件需要调试,或一个版本的程序需要编译进行测试,然而该文件不是makefile文件规则中缺省最终目标的依赖,此时,可以使用最终目标参数指定它们。

指定最终目标的另一个用途是运行和一个假想目标(参阅假想目标)或空目标(使用空目标记录事件)相联系的命令。许多makefile文件包含一个假想目标‘clean’删除除了原文件以外的所有文件。正常情况下,只有您具体指明使用‘make clean’命令,make才能执行上述任务。下面列出典型的假想目标和空目标的名称。对GNU make软件包使用的所有标准目标名参阅用户标准目标:

‘all'

创建makefile文件的所有顶层目标。

`clean'

删除所有make正常创建的文件。

`mostlyclean'

象假象目标‘clean’,但避免删除人们正常情况下不重新建造的一少部分文件。例如,用于GCC的目标‘mostlyclean’不删除‘libgcc.a’,因为重建它的情况十分稀少,而且创建它又需要很多时间。

`distclean'

`realclean'

`clobber'

这些目标可能定义为比目标‘clean’ 删除更多的文件。例如,删除配置文件或为编译正常创建的准备文件,甚至makefile文件自身不能创建的文件。

‘install’

向命令搜寻目录下拷贝可执行文件;向可执行文件寻找目录下拷贝可执行文件使用的辅助文件。

‘print’

打印发生变化的文件列表。

‘tar’

创建源文件的压缩‘tar’文件。

‘shar’

为源文件创建一个shell的档案文件。

‘dist’

为源文件创建一个发布文件。这可能是‘tar’文件, ‘shar’文件,或多个上述的压缩版本文件。

‘TAGS’

更新该程序的‘tags’标签。

`check'

`test'

对该makefile文件创建的程序执行自我测试。

9.3 代替执行命令

makefile文件告诉make怎样识别一个目标是否需要更新以及怎样更新每一个目标。但是更新目标并不是您一直需要的,一些特定的选项可以用来指定make的其它活动:

`-n'

`--just-print'

`--dry-run'

`--recon'

‘No-op’。make的这项活动是打印用于创建目标所使用的命令,但并不执行它们。

`-t'

`--touch'

‘touch’。这项活动是做更新标志,实际却不更改它们。换句话说,make假装编译了目标,但实际对它们没有一点儿改变。

`-q'

`--question'

‘question’。这项活动是暗中察看目标是否已经更新;但是任何情况下也不执行命令。换句话说,即不编译也不输出。

`-W file'

`--what-if=file'

`--assume-new=file'

`--new-file=file'

‘What if’。每一个‘-W’标志后跟一个文件名。所有文件名的更改时间被make记录为当前时间,但实际上更改时间保持不变。如果您要更新文件,您可以使用‘-W’标志和‘-n’标志连用看看将发生什么。

使用标志‘-n’,make打印那些正常执行的命令,但却不执行它们。

使用标志‘-t’,make忽略规则中的命令,对那些需要更新的目标使用‘touch’命令。如果不使用‘-s’或.SILENT,‘touch’命令同样打印。为了提高执行效率,make并不实际调用程序touch,而是使touch直接运行。

使用标志‘-q’,make不打印输出也不执行命令,如果所有目标都已经更新到最新,make的退出状态是0;如果一部分需要更新,退出状态是1;如果make遇到错误,退出状态是2,因此您可以根据没有更新的目标寻找错误。

在运行make时对以上三个标志如果同时两个或三个将产生错误。标志‘-n’、‘-t’和‘-s’对那些以字符‘+’开始的命令行和包含字符串‘$(MAKE)' 或‘${MAKE}'命令行不起作用。注意仅有这些以字符‘+’开始的命令行和包含字符串‘$(MAKE)' 或‘${MAKE}'命令行运行时不注意这些选项。参阅变量MAKE的工作方式。

‘-W’标志有一下两个特点:

l

l

如果同时使用标志‘-n’或‘-q’,如果您更改一部分文件,看看make将会做什么。

l

l

没有使用标志‘-n’或‘-q’,如果make运行时采用标志‘-W’,则make假装所有文件已经更新,但实际上不更改任何文件。

注意选项‘-p’和‘-v’允许您得到更多的make信息或正在使用的makefile文件的信息(参阅选项概要)。

9.4避免重新编译文件

有时您可能改变了一个源文件,但您并不希望编译所有依靠它的文件。例如,假设您在一个许多文件都依靠的头文件种添加了一个宏或一个声明,按照保守的规则,make认为任何对于该头文件的改变,需要编译所有依靠它的文件,但是您知道那是不必要的,并且您没有等待它们完全编译的时间。

如果您提前了解改变头文件以前的问题,您可以使用‘-t’选项。该标志告诉make不运行规则中的命令,但却将所有目标的时间戳改到最新。您可按下述步骤实现上述计划:

1、用make命令重新编译那些需要编译的源文件;

2、更改头文件;

3、使用‘make –t’命令改变所有目标文件的时间戳,这样下次运行make时就不会因为头文件的改变而编译任何一个文件。

如果在重新编译那些需要编译的源文件前已经改变了头文件,则按上述步骤做已显得太晚了;作为补救措施,您可以使用‘-o file’标志,它能将指定的文件的时间戳假装改为以前的时间戳(参阅选项概要)。这意味着该文件没有更改,因此您可按下述步骤进行:

1、使用‘make -o file’命令重新编译那些不是因为改变头文件而需要更新的文件。如果涉及几个头文件,您可以对每个头文件都使用‘-o’标志进行指定。

2、使用‘make –t’命令改变所有目标文件的时间戳。

9.5变量重载

使用‘=’定义的变量:‘v=x’将变量v的值设为x。如果您用该方法定义了一个变量,在makefile文件后面任何对该变量的普通赋值都将被make忽略,要使它们生效应在命令行将它们重载。

最为常见的方法是使用传递附加标志给编译器的灵活性。例如,在一个makefile文件中,变量CFLAGS已经包含了运行C编译器的每一个命令,因此,如果仅仅键入命令make时,文件‘foo.c’将按下面的方式编译:

cc -c $(CFLAGS) foo.c

这样您在makefile文件中对变量CFALAGS设置的任何影响编译器运行的选项都能生效,但是每次运行make时您都可以将该变量重载,例如:如果您说‘make CFLAGS='-g -O'’,任何C编译器都将使用‘cc -c -g -O’编译程序。这还说明了在重载变量时,怎样使用shell命令中的引用包括空格和其它特殊字符在内的变量的值。

变量CFALAGS仅仅是您可以使用这种方式重载的许多标准变量中的一个,这些标准变量的完整列表见隐含规则使用的变量。

您也可以编写makefile察看您自己的附加变量,从而使用户可通过更改这些变量控制make运行时的其它面貌。

当您使用命令参数重载变量时,您可以定义递归调用扩展型变量或简单扩展型变量。上例中定义的是递归调用扩展型变量,如果定义简单扩展型变量,请使用‘:=’代替‘=’。注意除非您在变量值中使用变量引用或函数调用,这两种变量没有任何差异。

利用这种方式也可以改变您在makfile文件中重载的变量。在makfile文件中重载的变量是使用override指令,是和‘override variable = value’相似的命令行。详细内容参阅override指令。

9.6 测试编译程序

正常情况下,在执行shell命令时一旦有错误发生,make立即退出返回非零状态;不会为任何目标继续运行命令。错误表明make不能正确的创建最终目标,并且make一发现错误就立即报告。

当您编译您修改过的程序时,这不是您所要的结果。您希望make能够经可能的试着编译每一个程序,并尽可能的显示每一个错误。

这种情况下,您可以使用‘-k’或‘--keep-going’选项。这种选项告诉make遇到错误返回非零状态之前,继续寻找该目标的依赖,如果有必要则重新创建它们。例如,在编译一个目标文件时发现错误,即使make已经知道连接它们已是不可能的, ‘make –k’也将继续编译其它目标文件。除在shell命令失败后继续运行外,即使发在make不知道如何创建的目标和依赖文件以后,‘make –k’也将尽可能的继续运行。在没有‘-k’选项时,这些错误将是致命的(参阅选项概要)。

通常情况下,make的行为是基于假设您的目标是使最终目标更新;一旦它发现这是不可能的它就立即报告错误。选项‘-k’说真正的目标是尽可能测试改变对程序的影响,发现存在的问题,以便在下次运行之前您可以纠正它们。这是Emacs M-x compile命令缺省传递‘-k’选项的原因。

9.7 选项概要

下面是所有make能理解的选项列表:

`-b'

`-m'

和其它版本make兼容时,这些选项被忽略。

`-C dir'

`--directory=dir'

在将makefile读入之前,把路径切换到‘dir’下。如果指定多个‘-C’选项,每一个都是相对于前一个的解释:‘-C/-C etc’等同于‘-C/etc’。该选项典型用在递归调用make过程中,参阅递归调用make。

‘-d’

在正常处理后打印调试信息。调试信息说明哪些文件用于更新,哪个文件作为比较时间戳的标准以及比较的结果,哪些文件实际上需要更新,需要考虑、使用哪些隐含规则等等----一切和make决定最终干什么有关的事情。‘-d’选项等同于‘--debug=a’选项(参见下面内容)。

`--debug[=options]'

在正常处理后打印调试信息。可以选择各种级别和类型的输出。如果没有参数,打印‘基本’级别的调试信息。以下是可能的参数,仅仅考虑第一个字母,各个值之间使用逗号或空格隔开:

a (all)

显示所有调试信息,该选项等同于‘-d’选项。

b (basic)

基本调试信息打印每一个已经过时的目标,以及它们重建是否成功。

v (verbose)

比‘基本’级高一个的等级的调试信息。包括makefile文件的语法分析结果,没有必要更新的依赖等。该选项同时包含基本调试信息。

i (implicit)

打印隐含规则搜寻目标的信息。该选项同时包含基本调试信息。

j (jobs)

打印各种子命令调用的详细信息。

m (makefile)

以上选项不包含重新创建makefile文件的信息。该选项包含了这方面的信息。注意,选项‘all’也不包含这方面信息。该选项同时包含基本调试信息。

`-e'

`--environment-overrides'

设置从环境中继承来的变量的优先权高于makefile文件中的变量的优先权。参阅环境变量。

`-f file'

`--file=file'

`--makefile=file'

将名为‘file’的文件设置为makefile文件。参阅编写makefile文件。

`-h'

`--help'

向您提醒make 能够理解的选项,然后退出。

`-i'

`--ignore-errors'

忽略重建文件执行命令时产生的所有错误。

`-I dir'

`--include-dir=dir'

第一頁    上一頁    第5頁/共9頁    下一頁    最後頁
第01頁 第02頁 第03頁 第04頁 第05頁 第06頁 第07頁 第08頁 第09頁 
 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有