一乐电子

 找回密码
 请使用微信账号登录和注册会员

QQ登录

只需一步,快速开始

微信扫码登录

手机号码,快捷登录

手机号码,快捷登录

搜索
查看: 3599|回复: 0

makefile中的自动化变量 $@,$%,$

[复制链接]
发表于 2017-5-4 09:05 | 显示全部楼层 |阅读模式
makefile中的自动化变量 $@,$%,$ - ~" s- w7 o6 m3 c
! K  ^" T, L  J, Y; o
自动化变量 ! @; V8 Y& w0 N5 N, x' ~3 h0 ^( D
模式规则中,规则的目标和依赖文件名代表了一类文件名;规则的命令是对所有这0 V) }" e! P  r; Y/ f- g8 [) J
一类文件重建过程的描述,显然,在命令中不能出现具体的文件名,否则模式规则失去4 x2 c: B  O- B' @- x& V, L
意义。那么在模式规则的命令行中该如何表示文件,将是本小节的讨论的重点。
( ^2 q$ M9 h; Z4 \- K  o假如你需要书写一个将.c 文件编译到.o 文件的模式规则,那么你该如何为gcc 书写; p$ E: M: W/ ~- r1 J
正确的源文件名?当然了,不能使用任何具体的文件名,因为在每一次执行模式规则时
7 S" u; A4 y$ W: ?6 f9 R3 M源文件名都是不一样的。为了解决这个问题,就需要使用“自动环变量”,自动化变量/ d! H) Z, }4 l/ I& e6 n! Q+ b
的取值是根据具体所执行的规则来决定的,取决于所执行规则的目标和依赖文件名。
, |- @& u1 K/ j: `1 m2 i+ A* \下面对所有的自动化变量进行说明: " Y# _; D3 x- E& W
$@
  R; r9 M. r7 Y1 |, X9 Q表示规则的目标文件名。如果目标是一个文档文件(Linux中,一般称.a 文件为( |- d1 D' s/ H$ P
文档文件,也称为静态库文件),那么它代表这个文档的文件名。在多目标模式' s9 ?+ J' W# G) T+ B8 l
规则中,它代表的是哪个触发规则被执行的目标文件名。 7 b! h# ~" V7 U2 y* z& Y3 V. F
$%
9 V3 h9 H7 Q5 {* N% g3 e, G当规则的目标文件是一个静态库文件时,代表静态库的一个成员名。例如,规则2 I  s- D) E% a- `! L
的目标是“foo.a(bar.o)”,那么,“ $%”的值就为“bar.o”,“ $@ ”的值为“foo.a”。
9 s, B, y4 `) Q如果目标不是静态库文件,其值为空。
+ h" H+ l; {5 P* j( ?" l3 Z$< $ Y1 U& b, j& N' ~5 j6 _+ V
规则的第一个依赖文件名。如果是一个目标文件使用隐含规则来重建,则它代表) y' b8 ?/ b  ]9 i7 X/ V6 V
由隐含规则加入的第一个依赖文件。 , q( M8 T1 {, D7 M. e3 U
$?
5 z( }! j5 M) F" A- ?
所有比目标文件更新的依赖文件列表,空格分割。如果目标是静态库文件名,代
表的是库成员(.o 文件)。 + P$ K+ Z) |$ m9 [$ [/ _4 o$ }
$^
+ u0 c9 P: C: i" E: l规则的所有依赖文件列表,使用空格分隔。如果目标是静态库文件,它所代表的# f8 h0 m' X* O4 Z
只能是所有库成员(.o 文件)名。一个文件可重复的出现在目标的依赖中,变量
+ F. w7 {7 d8 q* g“$^”只记录它的一次引用情况。就是说变量“$^”会去掉重复的依赖文件。
" v1 b1 l+ g9 s/ G. _" o$+
& h) O( c2 S* B* J类似“$^”,但是它保留了依赖文件中重复出现的文件。主要用在程序链接时库
* z! B$ a% s' \1 _9 a3 X的交叉引用场合。
! B' }8 R, g+ s4 ^& \& B6 D$* 3 S" F4 N2 I) ^
在模式规则和静态模式规则中,代表“茎”。“茎”是目标模式中“% ”所代表的. c: H& d- ~9 q" _. }6 n* K6 x& Z
部分(当文件名中存在目录时,“茎”也包含目录(斜杠之前)部分,可参考  10.5.4 ! f; g, Z; q6 C* ^4 b
模式的匹配  一小节)。例如:文件“dir/a.foo.b”,当目标的模式为“a.%.b ”时,
0 `2 K% ~- G& I5 J8 r, Q: k“$* ”的值为“dir/a.foo ”。“茎”对于构造相关文件名非常有用。 $ i/ c8 H/ K  `% S
自动化变量“$* ”需要两点说明: 7 k2 d& t; Z" R( R4 ]! H4 R9 ]
?   对于一个明确指定的规则来说不存在“茎”,这种情况下“$* ”的含义发6 _2 V: }. \( f2 p, q7 f( l
生改变。此时,如果目标文件名带有一个可识别的后缀(参考  10.7 后6 B5 T+ ^3 u# O7 ^6 ?
缀规则  一节),那么“$* ”表示文件中除后缀以外的部分。例如:“foo.c”/ b. o0 m/ Y  C0 C5 w& b0 ]
则“$* ”的值为:“foo ”,因为.c 是一个可识别的文件后缀名。GUN make# \4 \( N( N5 n1 }' P! ~
对明确规则的这种奇怪的处理行为是为了和其它版本的make兼容。通  |  g, P# N7 X4 G/ c- S
常,在除静态规则和模式规则以外,明确指定目标文件的规则中应该避
& |* C# t& u- X免使用这个变量。   q4 L# e! E. D- J2 b6 c
?   当明确指定文件名的规则中目标文件名包含不可识别的后缀时,此变量
) z: z2 l( `, s+ r为空。 : _8 T( e/ l8 g0 |) U+ L" y
自动化变量“$?”在显式规则中也是非常有用的,使用它规则可以指定只对更新
- v) u" |" K9 @以后的依赖文件进行操作。例如,静态库文件“libN.a ”,它由一些.o 文件组成。这个规
6 q: U+ r" k, A" u& Q  v# v2 M- a则实现了只将更新后的.o 文件加入到库中:
7 w' A- _: v* C) |6 D
3 |: P' C% U# k  B& B% I     lib: foo.o bar.o lose.o win.o
' [0 ~! v0 K: F* B3 m             ar r lib $?
: X! W1 I; O5 M7 A) c " @4 H% X/ @9 _5 E: C# y: h% B
以上罗列的自动量变量中。其中有四个在规则中代表文件名($@ 、$<、$%、$* )。
# E. a* O7 |, u( p& t9 L而其它三个的在规则中代表一个文件名列表。GUN make 中,还可以通过这七个自动化
变量来获取一个完整文件名中的目录部分和具体文件名部分。在这些变量中加入“D”2 W1 Z+ J: ?5 E" r6 W8 M
或者“F”字符就形成了一系列变种的自动环变量。这些变量会出现在以前版本的make
9 w0 g6 @. ^7 h  g中,在当前版本的make中,可以使用“dir”或者“notdir”函数来实现同样的功能(可$ V) z/ C. A: R+ t
参考  8.3  文件名处理函数  一节)。
0 k+ I9 p3 I; m" j$ |
$(@D)
* M/ J8 z% A! W1 q: F: p8 D% T) v表示目标文件的目录部分(不包括斜杠)。如果“$@ ”是“dir/foo.o ”,那么“$(@D) ”9 j/ l) g, s6 Q+ @: e: s
的值为“dir”。如果“$@ ”不存在斜杠,其值就是“. ”(当前目录)。注意它和 函' B: C  |$ b0 `6 b8 u
数“dir”的区别!
5 F+ s& }% K) d. F, U( k# r; J! L$(@F)
* q% c, g% L: ~( @. s" I0 _4 T/ B目标文件的完整文件名中除目录以外的部分(实际文件名)。如果“$@ ”为- Y( o! E. d& y: k  K
“dir/foo.o ”,那么“$(@F) ”只就是“foo.o”。“$(@F) ”等价于函数“$(notdir
3 A, r* M" ~' c% f6 ^+ `$@) ”。 * H4 R) R  u5 i+ I% g2 i
$(*D)
2 y0 C% f7 o2 F% }$(*F)
4 q8 u* V' M6 M" n5 E分别代表目标“茎”中的目录部分和文件名部分。   n6 Z: ?% G9 `3 z, {- `
$(%D)
+ r9 E+ E( f( h( Q+ A6 F' _! T7 G$(%F)
1 b1 i' p' E2 q! {; {! J+ V当以如“archive(member) ”形式静态库为目标时,分别表示库文件成员4 u' v1 [( ?' {5 T$ [
“member”名中的目录部分和文件名部分。它仅对这种形式的规则目标有效。
2 v% O% h( d" {" n, V4 y2 ^! J$(<d)
% r5 s1 E! Q: X5 T. Y' U. F$(<f) + J; l* ?, ], u' c+ r, J7 u- G( h
分别表示规则中第一个依赖文件的目录部分和文件名部分。 5 e: Q/ _2 ~/ H2 E( l6 s' L
$(^D) ! Y( a" L& [$ {( x' e) O8 _, L
$(^F) 5 A& j& F8 N8 T% W% h
分别表示所有依赖文件的目录部分和文件部分(不存在同一文件)。 ! c* ]& i: {" F# Z
$(+D)
5 Y3 a. S* T! b' \: S0 Y$ g1 U$(+F) 1 ?) P4 h4 Z4 F8 T( g9 Z' K
分别表示所有依赖文件的目录部分和文件部分(可存在重复文件)。
. K5 c- S% Q! E; Q/ j9 C: q+ M$(?D)
$ M2 T) }" i  A- w; W3 g$(?F) # U1 E) F! f, r5 r  K) m  V
分别表示被更新的依赖文件的目录部分和文件名部分
在讨论自动化变量时,为了和普通变量(如:“CFLAGS ”)区别,我们直接使用了
# o. a9 G' v/ {8 y& d- A3 G: @+ E  ?# ^“$<”的形式。这种形式仅仅是为了和普通变量进行区别,没有别的目的。其实对于
# Z0 u" D, ~2 l! L8 g( t" z  D自动环变量和普通变量一样,代表规则第一个依赖文件名的变量名实际上是“< ”,我
% G% d9 A( ?+ l% T) d+ k们完全可以使用“$(<) ”来替代“$<”。但是在引用自动化变量时通常的做法是“$<”,
( q7 f. w+ R% }$ r因为自动化变量本身是一个特殊字符。
2 S1 d' [; u) }% L$ kGUN make同时支持“Sysv”特性,允许在规则的依赖列表中使用特殊的变量引  o9 \8 P9 }+ L; e; W( F4 i
用(一般的自动化变量只能在规则的命令行中被引用)“$$@”、“$$(@D)”和“$$(@F)”2 s: V# N  Z0 m$ F" u4 B/ }
(注意:要使用“$$”),它们分别代表了“目标的完整文件名”、“目标文件名中的目+ _) y1 h- c/ N
录部分”和“目标的实际文件名部分”。这三个特殊的变量只能用在明确指定目标文件# |/ x2 s( M. v& k/ p7 E0 E
名的规则中或者是静态模式规则中,不用于隐含规则中。另外Sysv make 和GNU make4 Z4 c1 s1 F6 y+ i
对规则依赖的处理也不尽相同。Sysv make对规则的依赖进行两次替换展开,而GUN 7 U1 W0 f5 H6 I5 k2 ]. h# [
make对依赖列表的处理只有一次,对其中的变量和函数引用直接进行展开。
9 l: c$ U4 v+ g8 M- s自动化变量的这个古怪的特性完全是为了兼容Sysv  版本的makefile文件。在使用$ O9 `1 o. o: c+ E( ]" `. L  \9 |
GNU make 时可以不考虑这个,也可以在Makefile中使用伪目标“.POSIX ”来禁止这一3 [' I( S2 l+ z* C, ?% Q
特性

  J6 E; P" B; a% m

本版积分规则

QQ|一淘宝店|手机版|商店|一乐电子 ( 粤ICP备09076165号 ) 公安备案粤公网安备 44522102000183号

GMT+8, 2025-10-28 06:19 , Processed in 0.033005 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表