Chinaunix首页 | 论坛 | 博客
  • 博客访问: 198879
  • 博文数量: 69
  • 博客积分: 1400
  • 博客等级: 上尉
  • 技术积分: 720
  • 用 户 组: 普通用户
  • 注册时间: 2005-08-03 11:35
文章分类

全部博文(69)

文章存档

2011年(13)

2010年(46)

2009年(10)

我的朋友

分类:

2010-10-08 23:03:02

 Make100928

GNU Make的使用简记 2

 

 

Email:

zcatt@163.com

Blog

http://zcatt.cublog.cn

 

 

 


文档简要整理了GNU Make的语法,函数,和命令。备忘和参考。本文的pdf格式已经发布到 百度wenku.

 

除了少数的例外,变量在读入的时候就会被展 开。这些少数的例外包括,recipe中,变量定义'='的右侧,define中。(deferred 参见2.4

变量名中不能包含':''#''='字符,和头尾的空白符。

变量名是大小写敏感的。推荐脚本内部使用的 变量名用小写。

另外,还有一些有专门用途的自动变量automatic variables值 得注意。

 

变量的引用形式 $(var_name) ${var_name}。推荐使用小括号。对于单个字符的变量名,可以不使用大小括号, 例如$x,但这种用法不推荐。

 

'='recursively expanded varible,递归扩展的变量。使用'='定义的变量右侧是deferred的,每次使用时,都会按字面展开,如果字面中还有其他变量的引用,则按照当前展开时的变量值继续展 开变量,直到字面中的变量展开完毕,这就是recursively递归的意义所在。(deferred,参见2.4

下例中的$(foo)'Huh?'

foo = $(bar)

bar = $(ugh)

ugh = Huh?

all:;echo $(foo)

使用'='定义变量有两点要注意一点,形如下的定义会产生变量扩展的无穷迭代。

CFLAGS = $(CFLAGS) -O

另一点,每次使用变量时,都会执行扩展,效 率较低。

 

':='simply expanded variables,简单展开变量。使用':='定义的变量在定义的时候就展开一次,其中的变量引用就按照当前的值展开。':='定义的变量使用时,就按照上述已经展开好的内容展开。(immediate,参见2.4)

 

下例中yfoo bar

x := foo

y := $(x) bar

x := later

 

'?=',条件变量赋值,仅当变量还没有定义时才有意义。如果变量已经定义过了,则忽略这个'?='变量定义。

 

'+='可用于追加内容。

 

使用define…endef也可以定义变量,而且define中允许使用换行符。

define two-lines=

echo foo

echo $(bar)

endef

 

已定义的变量名可以使用undefine取消。

 

一般的变量是全局范围的,如果变量的作用域 需要限定在某个target中,可以使用下面的形式

target ... : variable-assignment

例如

prog : CFLAGS = -g

prog : prog.o foo.o bar.o

变量引用除了前面描述的$(varName)${varName}外,还有 下面较复杂的用法:替 代引用

 

形式如下,变量中的字符a将被替代为b。另外也可以使用通配符%.

$(var:a=b)

 

下述例子中,bar都是a.c b.c c.c

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

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

 

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

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

嵌套变量名

展开的变量名中出现变量应用,称作computed variable namenested variable reference

下例中az.

x = y

y = z

a := $($(x))

另两个例子

x = y

y = z

z = u

a := $($($(x))

 

 

x = $(y)

y = z

z = Hello

a := $($(x))

 

嵌套变量名这种用法可以实现更加灵活的函数 和变量引用。下面例子。

a_dirs := dira dirb

1_dirs := dir1 dir2

a_files := filea fileb

1_files := file1 file2

ifeq "$(use_a)" "yes"

a1 := a

else

a1 := 1

endif

ifeq "$(use_dirs)" "yes"

df := dirs

else

df := files

endif

dirs := $($(a1)_$(df))

 

另一个例子

ifdef do_sort

func := sort

else

func := strip

endif

bar := a d b g q c

foo := $($(func) $(bar))

 

MAKEFILELIST

按照make分析的顺序排列的,make已经处理/分析过的makefile文件名列表。

 

.DEFAULT_GOAL

如果make没有指定创建或更新的target,则创建和更新.DEFAULT_GOAL指定的target.

 

.VARIABLES

所有全局变量的名字列表。

 

.INCLUDE_DIRS

make搜寻included makefile路径的列表。

环境变量

make读入脚本变量前,会优先读入环境变量MAKEFILES。但一般MAKEFILES变量仅用于make的递归调用,用于传递信息。通常不要使用这个变量。

 

make在当前目录下搜寻不到指定文件时,会 到VPATH指的 目录下搜索。通常是用在prerequisite files在当前目录下的情况。VPATH中的各路径用':'ws分隔。

例如

VPATH = src : ../headers

 

参考vpath命令。

常用自动变量

自动变量是一类特殊的变量,它的取值依赖于ruletargetprerequisite,仅使用在recipe中。

 

$@

ruletarget(文件名)

 

$%

target是归档成员(archive member)时,$%target成员名。例如,target'foo.a(bar.o)'时,$%'bar.o'$@'foo.a'。如果target不是archive member时,$%返回空。

 

$<

prerequisite中的第一项的名字。

 

$?

prerequisite列表中比target新的所有项的列表,空格间隔。

 

$^

prerequisite列表中的所有项,空格间隔。重复的项取消重复,只保留一个。

 

$+

$+,但保留重复。

 

$|

所有order-only prerequisite的成员列表,空格间隔。

 

$*

返回隐式规则implicit rule匹配的部分stem。例如target'dir/a.foo.b', 规则是'a.%.b',那么$*'dir/foo'。在static pattern rule中,stem是通配符'%'匹配的部分。

 

$(@D)

target文件名的目录路径部分,结尾的斜杠去掉。例如$@'dir/foo.o',那么$(@D)'dir'。如果$@不含目录路径,那么$@'.'

 

$(@F)

target文件名中不是目录路径的部分。等同于$(notdir $@)

 

$(*D)$(*F)

target stem部分的的dirnotdir部分。

 

$(%D), $(%F)

target archive member名的dir notdir部分。

 

$($(

prerequisite列表中第一项的dirnotdir部分。

 

$(^D)$(^F)

prerequisite列表中所有项的dirnotdir部分。

 

其他类似的还有 $(+D)$(+F)$(?D)$(?F)

条件判断的形式

conditional-directive

text-if-true

endif

 

or

 

conditional-directive

text-if-true

else

text-if-false

endif

 

or

 

conditional-directive

text-if-one-is-true

else conditional-directive

text-if-true

else

text-if-false

endif

 

conditional-directive的形式, 推荐使 用括号的形式。

ifeq (arg1, arg2)

ifeq arg1 arg2

ifeq "arg1" "arg2"

ifeq "arg1" arg2

ifeq arg1 "arg2"

ifneq (arg1, arg2)

ifneq arg1 arg2

ifneq "arg1" "arg2"

ifneq "arg1" arg2

ifneq arg1 "arg2"

ifdef variable-name

ifndef variable-name

函数

函数的调用形式,推荐使用小括号形式。

$(function arguments)

 

or

 

${function arguments}

make除了支持一些built-in自带的函数外,还允许用户创建自己的函数,使用call调用。

文本转换函数处理的文本,是空格间隔的词(word)的形式。

subst

$(subst from,to,text)

text中的from替换成to.

$(subst ee,EE,feet on the street)

 

result: fEEt on the strEEt

 

patsubst

$(patsubst pattern,replacement,text)

text中空格间隔的word词,符合pattern的,用replacement替换。多个连续空格将压缩称一个空格。另外,允许使用统配符'%',如果需要使用'%'字符,可 以前缀'\'转义。

$(patsubst %.c,%.o,x.c.c bar.c)

 

result: x.c.o bar.o

 

几个简单的等价形式

$(var:pattern=replacement)

等同于

$(patsubst pattern,replacement,$(var))

 

$(var:suffix=replacement)

等同于

$(patsubst %suffix,%replacement,$(var))

 

strip

$(strip string)

去除头尾空格,中间的连续空格用一个空格替 换。

 

findstring

$(findstring find, in)

in中查找find字串,有则返回查找到的字串,没有则返回空。常用到条件检测中。

 

filter

$(filter pattern…, text)

返回text中所有匹配任何一个pattern的词word,剔除不匹配pattern的词。可以使用通配符'%'

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

foo: $(sources)

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

 

result:

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

    cc foo.c bar.c baz.s -o foo

filter-out

$(filter-out pattern…, text)

filter函数相反,保佑不匹配的,剔除匹 配的。

sort

$(sort list)

按照词序排序list中的词,剔除重复的。

$(sort foo bar lose)

 

result: bar foo lose

word

$(word n,text)

返回list中第nword词。从1开始计数。

$(word 2, foo bar baz)

 

result: bar

wordlist

$(wordlist s,e,text)

返回text中第s个到第e个词。

$(wordlist 2, 3, foo bar baz)

 

result: bar baz

words

$(words text)

返回text中词的总数。

 

firstword

$(firstword names…)

返回names中的第一个词。

lastword

$(lastword names…)

返回names中的最后一个词。

dir

$(dir names…)

抽取names中每个文件名的目录路径部分。目录 路径部分是指到最后一个路径分隔符的部分。

$(dir src/foo.c hacks)

 

result: src/ ./

notdir

$(notdir names…)

抽取除目录路径外的部分。如果文件名不含目 录路径部分,即文件分隔符,则不变返回。

$(notdir src/foo.c hacks)

 

result: foo.c hacks

suffix

$(suffix names…)

抽取文件名后缀。

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

 

result: .c .c

 

basename

$(basename names…)

除了后缀,抽取其余部分。

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

 

result: src/foo src-1.0/bar hacks

addsuffix

$(addsuffix suffix, names…)

names中的每个词添加后缀suffix

$(addsuffix .c,foo bar)

 

result: foo.c bar.c

addprefix

$(addprefix prefix, names…)

names中的每个词添加前缀。

join

$(join list1, list2)

list1list2中的词一对一的链接起来。

$(join a b,.c .o)

 

result a.c b.o

wildcard

$(wildcard pattern)

返回当前文件名符合pattern的空格间隔的文件名列表。pattern是文件名的pattern,可以使用通配符'*''?',和'[…]'

realpath

$(realpath names…)

返回文件名的正则绝对路径。

abspath

$(abspath names…)

返回文件名的绝对路径。注意与正则绝对路径 不同,绝对路径不要求解析符号链接,不要求文件和目录真实存在。

if

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

 

or

$(or condition1[,condition2[,condition3…]])

 

and

$(and condition1[,condition2[,condition3…]])

 

$(foreach var,list,text)

var依次取值list中的每个值,代换到text中。

dirs := a b c d

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

 

result$(wildcard a/* b/* c/* d/*)

使用call可以调用你自己定义的带入口参数的函 数

 

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

make调用这个函数时,make会赋值临时变量$(0) variabile $(1) $(2)…等为param…

reverse = $(2) $(1)

foo = $(call reverse,a,b)

不展开,而返回一个变量的值。

$(value variable)

variable是变量的名字,而不是变量的引用。

FOO = $PATH

all:

@echo $(FOO)

@echo $(value FOO)

 

result

ATH

环境变量PATH的内容

'@echo $(FOO)'的输出,$P被认为是make的单字符变量,没有定义而认为空,最 终$(FOO)输 出为ATH

eval可以用于构造makefile中的结构。它展开两次,第一次是eval函数自己的展开,第一次展开的结果作为脚本内容进行第二次展开,第二次展开是make脚本的展开。

eval函数的返回是空串,因此eval函数实际上可以放在任何地方而不会产生make的语法错误。

PROGRAMS = server client

server_OBJS = server.o server_priv.o server_access.o

server_LIBS = priv protocol

client_OBJS = client.o client_api.o client_mem.o

client_LIBS = protocol

# Everything after this is generic

.PHONY: all

all: $(PROGRAMS)

define PROGRAM_template =

$(1): $$($(1)_OBJS) $$($(1)_LIBS:%=-l%)

ALL_OBJS += $$($(1)_OBJS)

endef

$(foreach prog,$(PROGRAMS),$(eval $(call PROGRAM_template,$(prog))))

$(PROGRAMS):

    $(LINK.o) $^ $(LDLIBS) -o $@

clean:

    rm -f $(ALL_OBJS) $(PROGRAMS)

 

shell函数将调用shell命令,返回shell命令的结果。注意返回的结果中,make将把换行符转换成一个空格,去掉每行头尾的多余空格。

contents := $(shell cat foo)

error

$(error text…)

产生一个错误fatal error,并输出消息text

warning

$(warning text…)

产生一个警告信息。

 

info

$(info text…)

打印提示信息。


Locations of visitors to this page

阅读(1367) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~