GNU make manual 翻译( 一百五十五)
繼續(xù)翻譯
6.2 The Two Flavors of Variables ================================There are two ways that a variable in GNU `make' can have a value; we call them the two "flavors" of variables. The two flavors are distinguished in how they are defined and in what they do when expanded.The first flavor of variable is a "recursively expanded" variable. Variables of this sort are defined by lines using `=' (*note Setting Variables: Setting.) or by the `define' directive (*note Defining Multi-Line Variables: Multi-Line.). The value you specify is installed verbatim; if it contains references to other variables, these references are expanded whenever this variable is substituted (in the course of expanding some other string). When this happens, it is called "recursive expansion".For example,foo = $(bar)bar = $(ugh)ugh = Huh?all:;echo $(foo)will echo `Huh?': `$(foo)' expands to `$(bar)' which expands to `$(ugh)' which finally expands to `Huh?'.This flavor of variable is the only sort supported by other versions of `make'. It has its advantages and its disadvantages. An advantage (most would say) is that:CFLAGS = $(include_dirs) -Oinclude_dirs = -Ifoo -Ibarwill do what was intended: when `CFLAGS' is expanded in a recipe, it will expand to `-Ifoo -Ibar -O'. A major disadvantage is that you cannot append something on the end of a variable, as inCFLAGS = $(CFLAGS) -Obecause it will cause an infinite loop in the variable expansion. (Actually `make' detects the infinite loop and reports an error.) Another disadvantage is that any functions (*note Functions for Transforming Text: Functions.) referenced in the definition will be executed every time the variable is expanded. This makes `make' run slower; worse, it causes the `wildcard' and `shell' functions to give unpredictable results because you cannot easily control when they are called, or even how many times.To avoid all the problems and inconveniences of recursively expanded variables, there is another flavor: simply expanded variables."Simply expanded variables" are defined by lines using `:=' (*note Setting Variables: Setting.). The value of a simply expanded variable is scanned once and for all, expanding any references to other variables and functions, when the variable is defined. The actual value of the simply expanded variable is the result of expanding the text that you write. It does not contain any references to other variables; it contains their values _as of the time this variable was defined_. Therefore,x := fooy := $(x) barx := lateris equivalent toy := foo barx := laterWhen a simply expanded variable is referenced, its value is substituted verbatim.Here is a somewhat more complicated example, illustrating the use of `:=' in conjunction with the `shell' function. (*Note The `shell' Function: Shell Function.) This example also shows use of the variable `MAKELEVEL', which is changed when it is passed down from level to level. (*Note Communicating Variables to a Sub-`make': Variables/Recursion, for information about `MAKELEVEL'.) ifeq (0,${MAKELEVEL})whoami := $(shell whoami)host-type := $(shell arch)MAKE := ${MAKE} host-type=${host-type} whoami=${whoami}endifAn advantage of this use of `:=' is that a typical `descend into a directory' recipe then looks like this: ${subdirs}:${MAKE} -C $@ allSimply expanded variables generally make complicated makefile programming more predictable because they work like variables in most programming languages. They allow you to redefine a variable using its own value (or its value processed in some way by one of the expansion functions) and to use the expansion functions much more efficiently (*note Functions for Transforming Text: Functions.).You can also use them to introduce controlled leading whitespace into variable values. Leading whitespace characters are discarded from your input before substitution of variable references and function calls; this means you can include leading spaces in a variable value by protecting them with variable references, like this:nullstring :=space := $(nullstring) # end of the lineHere the value of the variable `space' is precisely one space. The comment `# end of the line' is included here just for clarity. Since trailing space characters are _not_ stripped from variable values, just a space at the end of the line would have the same effect (but be rather hard to read). If you put whitespace at the end of a variable value, it is a good idea to put a comment like that at the end of the line to make your intent clear. Conversely, if you do _not_ want any whitespace characters at the end of your variable value, you must remember not to put a random comment on the end of the line after some whitespace, such as this:dir := /foo/bar # directory to put the frobs inHere the value of the variable `dir' is `/foo/bar ' (with four trailing spaces), which was probably not the intention. (Imagine something like `$(dir)/file' with this definition!) There is another assignment operator for variables, `?='. This is called a conditional variable assignment operator, because it only has an effect if the variable is not yet defined. This statement:FOO ?= baris exactly equivalent to this (*note The `origin' Function: Origin Function.):ifeq ($(origin FOO), undefined)FOO = barendifNote that a variable set to an empty value is still defined, so `?=' will not set that variable.6.2 變量的兩個(gè)風(fēng)格
================================
有兩種方法可以使得GNU make中的一個(gè)變量擁有一個(gè)值;我們成其為變量的兩個(gè)風(fēng)格。這兩個(gè)趣味由他們?nèi)绾味x和如何擴(kuò)展而區(qū)分開來。
第一個(gè)變量的趣味來自遞歸擴(kuò)展變量。此類變量用 =來定義(*note Setting Variables: Setting),或者用 define 指令(*note Defining Multi-Line Varaibles: Multi-Line)
你所定義的值會(huì)被逐字翻譯;如果它包含了對(duì)其他變量的參照。這些參照會(huì)在此變量被替換的時(shí)候進(jìn)行擴(kuò)展(在對(duì)其他字符串的擴(kuò)展時(shí))。當(dāng)它發(fā)生的時(shí)候,可以稱為遞歸擴(kuò)展。
例如,
foo = $(bar)
bar = $(ugh)
ugh = Huh?
all:;echo $(foo)
會(huì)顯示`Huh?': `$(foo)' 擴(kuò)展為 `$(bar)',它再繼續(xù)擴(kuò)展為`$(ugh)' ,最終擴(kuò)展為`Huh?'。
This flavor of variable is the only sort supported by other versions
of `make'. It has its advantages and its disadvantages. An advantage
(most would say) is that:
這種風(fēng)格的變量是唯一被其他版本make所支持的。它有優(yōu)點(diǎn)和缺點(diǎn)。一個(gè)優(yōu)點(diǎn)(大多數(shù)情況下)是:
CFLAGS = $(include_dirs) -O
include_dirs = -Ifoo -Ibar
將會(huì)執(zhí)行所期待的: 當(dāng) CFLAGS 在片段中被擴(kuò)展,它會(huì)擴(kuò)展為 ?-Ifoo -Ibar -O。一個(gè)主要的確定是你無法在變量后面最加一些東西,就像
CFLAGS = $(CFLAGS) -O
因?yàn)樗鼘?dǎo)致一個(gè)變量擴(kuò)展的無限的循環(huán)(實(shí)際上make會(huì)檢測到這個(gè)無限循環(huán)報(bào)告一個(gè)錯(cuò)誤)。
另一個(gè)壞處是,在定義中所參照的任何函數(shù)(*note Functiosn for Transforming Text: Functions.)在每次變量擴(kuò)展的時(shí)候都要執(zhí)行。這導(dǎo)致make 運(yùn)行緩慢。更糟糕的是,它導(dǎo)致通配符和shell 函數(shù)給出不確定的結(jié)果,因?yàn)槟銦o法簡單地控制它們何時(shí)以何種方式被調(diào)用多少次。
為了防止上述的所有問題和不方便之處,這里有另外一個(gè)風(fēng)格:簡單擴(kuò)展變量。
"簡單擴(kuò)展變量"由:=來定義(*note Setting Variables: Setting.),簡單擴(kuò)展變量的值只被掃描一次,在任何其他的對(duì)此變量進(jìn)行參照的變量和函數(shù)中擴(kuò)展。簡單擴(kuò)展變量的實(shí)際值就是你所寫的文本擴(kuò)展結(jié)果。它不包含任何對(duì)其他變量的參照;它包含此變量被定義時(shí)的值。因此,
x := foo
y := $(x) bar
x := later
等價(jià)于:
y := foo bar
x := later
當(dāng)一個(gè)簡單擴(kuò)展變量被參照的時(shí)候,它的值會(huì)被逐字逐句替換。
This example also shows use of the variable
`MAKELEVEL', which is changed when it is passed down from level to
level. (*Note Communicating Variables to a Sub-`make':
Variables/Recursion, for information about `MAKELEVEL'.)
這里有一個(gè)更加復(fù)雜的例子,顯示了和shell 函數(shù)結(jié)合,對(duì):=的利用。(*Note the 'shell' Function:Shell Function.)
ifeq (0,${MAKELEVEL})
whoami := $(shell whoami)
host-type := $(shell arch)
MAKE := ${MAKE} host-type=${host-type} whoami=${whoami}
endif
使用這種 :=的一個(gè)好處就是 典型的進(jìn)入目錄的片段會(huì)看起來像這樣:?
${subdirs}:
${MAKE} -C $@ all
簡單擴(kuò)展變量通常會(huì)使得復(fù)雜的makefile編程更精確,因?yàn)樗鼈兙拖翊蠖鄶?shù)的編程語言一樣進(jìn)行工作。它們允許你用變量的值來重新定義自己(或者用某種方式在擴(kuò)展函數(shù)中處理),可以更加高效地運(yùn)行擴(kuò)展函數(shù)(*note Functions for Transforming Text: Functions.)
你也可以用它們來在變量值中引入前導(dǎo)空格。在替換到變量參照和函數(shù)調(diào)用之前,前導(dǎo)空格會(huì)被忽略;這種方式下你可以通過利用變量參照來保護(hù)前導(dǎo)空格,像下面這樣:
nullstring :=
space := $(nullstring) # end of the line
這里變量space 的值是精確的一個(gè)空格。注釋'# end of the line' 在這里只是為了更加清晰地說明問題。因?yàn)槟┪驳目崭褡址粫?huì)從變量值中剝除,在行末的一個(gè)空格也可以達(dá)到同樣的效果(但是讀取來很困難)。
如果你在一個(gè)變量值得最后面附加一個(gè)空格,像上述那樣在此行后面附加一個(gè)注釋是一個(gè)好主意。相反地,如果你不想任何空格出現(xiàn)在你的變量末尾,你必須記住不要在行的末尾,在若干空格后面加一個(gè)注釋。就像這樣:
dir := /foo/bar # directory to put the frobs in
此時(shí),dir 變量的值是 '/foo/bar '(末尾有四個(gè)空格),這可能不符合我們的預(yù)期。(想象比如 $(dir)/file這樣的東西)
這一由另外一個(gè)對(duì)變量的復(fù)制操作符號(hào) ?=。這被常委一個(gè)條件變量夫之婦好,一位只有在一個(gè)變量尚未確定時(shí)它才有效果。下面的句子:
FOO ?= bar
等價(jià)于 (*note The `origin' Function: Origin
Function.):
ifeq ($(origin FOO), undefined)
FOO = bar
endif
請(qǐng)注意一個(gè)便來能夠設(shè)置為空值也相當(dāng)于定義了,所以`?='不會(huì)設(shè)定給那個(gè)變量。
后文待續(xù)
轉(zhuǎn)載于:https://www.cnblogs.com/gaojian/archive/2012/10/03/2710745.html
總結(jié)
以上是生活随笔為你收集整理的GNU make manual 翻译( 一百五十五)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: PushMe(交互式)
- 下一篇: [转]这才是真正的3D显示!Leap M