一乐电子

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

QQ登录

只需一步,快速开始

微信扫码登录

手机号码,快捷登录

手机号码,快捷登录

搜索
查看: 4001|回复: 0

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

[复制链接]
发表于 2017-5-4 09:05 | 显示全部楼层 |阅读模式
makefile中的自动化变量 $@,$%,$ # z/ _1 e; m0 T4 S  }5 J" e$ F# P

; v% h3 u( U4 n自动化变量 + b  X1 ?! X1 u7 ]0 L8 l4 J
模式规则中,规则的目标和依赖文件名代表了一类文件名;规则的命令是对所有这1 J( K, |0 y2 p, ]) n
一类文件重建过程的描述,显然,在命令中不能出现具体的文件名,否则模式规则失去# I" }/ N( [+ Q3 q3 k0 t) `# @) N
意义。那么在模式规则的命令行中该如何表示文件,将是本小节的讨论的重点。
( u  A) G4 {1 U. R& q假如你需要书写一个将.c 文件编译到.o 文件的模式规则,那么你该如何为gcc 书写
0 |' B( Y# t; E3 |! g5 c5 F正确的源文件名?当然了,不能使用任何具体的文件名,因为在每一次执行模式规则时  J9 l; O+ [3 `  T  e! e
源文件名都是不一样的。为了解决这个问题,就需要使用“自动环变量”,自动化变量
, a# [1 G% S0 k' ^: J! |的取值是根据具体所执行的规则来决定的,取决于所执行规则的目标和依赖文件名。 - ~5 k3 D( d! ~& q- J( s
下面对所有的自动化变量进行说明:
9 q+ M) |- m9 m7 w$@ ; M! e3 N/ V+ j1 T4 B1 j6 T" h9 k, {
表示规则的目标文件名。如果目标是一个文档文件(Linux中,一般称.a 文件为- y) z* w+ l' m+ Z
文档文件,也称为静态库文件),那么它代表这个文档的文件名。在多目标模式9 X$ {! j$ C6 q( Z1 d% `. F/ x
规则中,它代表的是哪个触发规则被执行的目标文件名。
) n# Y9 C. i. |' w5 l0 S3 i3 {$% " d) y2 O4 @& F5 z8 F, n
当规则的目标文件是一个静态库文件时,代表静态库的一个成员名。例如,规则
* s% h/ m- W) s6 g  ]的目标是“foo.a(bar.o)”,那么,“ $%”的值就为“bar.o”,“ $@ ”的值为“foo.a”。$ J* w, u2 `, ^. F$ Y4 D
如果目标不是静态库文件,其值为空。
3 f+ X$ e4 R) q0 l# P  w  ?$<
+ e1 X& r% ?; p( R3 l规则的第一个依赖文件名。如果是一个目标文件使用隐含规则来重建,则它代表
# E+ X3 s5 e" b7 Y7 T$ }& I  Y由隐含规则加入的第一个依赖文件。 7 X( k: v. b0 d7 K& N
$?
5 Q0 ]( |! e5 U1 \4 T, c
所有比目标文件更新的依赖文件列表,空格分割。如果目标是静态库文件名,代
表的是库成员(.o 文件)。
( @/ R8 g7 j$ W. C- L3 U$^ 9 G8 k% V- u# ~
规则的所有依赖文件列表,使用空格分隔。如果目标是静态库文件,它所代表的2 D3 b5 v4 E* ~$ r7 }# ?
只能是所有库成员(.o 文件)名。一个文件可重复的出现在目标的依赖中,变量& M9 D2 [+ j' u. S
“$^”只记录它的一次引用情况。就是说变量“$^”会去掉重复的依赖文件。 % e2 M9 D6 o; L; c* `& ?5 |
$+ " h- s  d& Y9 ~
类似“$^”,但是它保留了依赖文件中重复出现的文件。主要用在程序链接时库
, O% c2 K' d! y) k$ i4 L: I的交叉引用场合。
  G- _( K- O- }" H! V3 R2 L8 r2 C: C$*
0 v& ?; V+ B& ~5 g, p' l- O2 ]在模式规则和静态模式规则中,代表“茎”。“茎”是目标模式中“% ”所代表的
1 D& i  G  V0 P: i2 T1 Z, H0 \* V部分(当文件名中存在目录时,“茎”也包含目录(斜杠之前)部分,可参考  10.5.4 : {) C  B, L0 M0 F& x# X
模式的匹配  一小节)。例如:文件“dir/a.foo.b”,当目标的模式为“a.%.b ”时,$ s3 a/ S8 }4 q6 V9 W
“$* ”的值为“dir/a.foo ”。“茎”对于构造相关文件名非常有用。
* e! ?* P5 j  e  J自动化变量“$* ”需要两点说明: 2 M0 V; M2 v: a1 _; L
?   对于一个明确指定的规则来说不存在“茎”,这种情况下“$* ”的含义发
- y; l; k4 b/ i: Y) ^* h生改变。此时,如果目标文件名带有一个可识别的后缀(参考  10.7 后
" m( e" F7 f, o* P7 T! [缀规则  一节),那么“$* ”表示文件中除后缀以外的部分。例如:“foo.c”* J; T* J( Q3 o% K  c9 J- R
则“$* ”的值为:“foo ”,因为.c 是一个可识别的文件后缀名。GUN make
3 K" k4 w; H- T2 x  ^对明确规则的这种奇怪的处理行为是为了和其它版本的make兼容。通
) A/ ]3 n  @9 q+ }6 b2 ?常,在除静态规则和模式规则以外,明确指定目标文件的规则中应该避
2 b% X" S, `& }/ \6 z! R免使用这个变量。
; E/ x: |# m2 K?   当明确指定文件名的规则中目标文件名包含不可识别的后缀时,此变量% I& w. Y( K* x  U
为空。 ( L/ m  P% e3 U; n) F
自动化变量“$?”在显式规则中也是非常有用的,使用它规则可以指定只对更新* J5 p  b5 }% Q3 L) O
以后的依赖文件进行操作。例如,静态库文件“libN.a ”,它由一些.o 文件组成。这个规
5 U9 X( A% E( w+ {# K则实现了只将更新后的.o 文件加入到库中:
. y% i' `" t& B, x0 K
, Z% h8 R- W  n     lib: foo.o bar.o lose.o win.o
" }' o: o: r5 C7 H             ar r lib $? 1 t9 B0 I* k6 ^3 Z$ L# D! I
" z; O. n* Z/ q3 v% i
以上罗列的自动量变量中。其中有四个在规则中代表文件名($@ 、$<、$%、$* )。3 c; R2 f8 I8 S- E$ c  ?$ y
而其它三个的在规则中代表一个文件名列表。GUN make 中,还可以通过这七个自动化
变量来获取一个完整文件名中的目录部分和具体文件名部分。在这些变量中加入“D”
9 e6 m0 I6 Y' F* m* ^, l或者“F”字符就形成了一系列变种的自动环变量。这些变量会出现在以前版本的make" J; h, y4 X# F8 B1 O
中,在当前版本的make中,可以使用“dir”或者“notdir”函数来实现同样的功能(可& K9 J  U. x$ z; T6 g, \8 C3 X
参考  8.3  文件名处理函数  一节)。

" D( Y8 C" _- a9 D$(@D)
: F+ f7 C" j1 {% r* V. ~8 {表示目标文件的目录部分(不包括斜杠)。如果“$@ ”是“dir/foo.o ”,那么“$(@D) ”4 o, `. g5 @4 u
的值为“dir”。如果“$@ ”不存在斜杠,其值就是“. ”(当前目录)。注意它和 函
/ f4 w6 {. f" U3 O6 _数“dir”的区别! 9 X5 C; q$ J4 `6 ~( ^8 ^2 C  b5 W
$(@F) * J- K6 f9 {5 s. w
目标文件的完整文件名中除目录以外的部分(实际文件名)。如果“$@ ”为7 N9 e5 n$ ?9 p! R' t+ m
“dir/foo.o ”,那么“$(@F) ”只就是“foo.o”。“$(@F) ”等价于函数“$(notdir # `6 r. B; R' W  ~$ @6 @0 D
$@) ”。
; U) K- M" W5 z. i3 N  j$(*D)
: Q. D: ^" i- K' U0 r% ~$(*F) 6 B* I8 t$ A& H9 U1 b
分别代表目标“茎”中的目录部分和文件名部分。
8 E8 Q4 f( ^6 @, n! f) f" x1 p* g$(%D) 3 g) l9 t, \( d: [
$(%F) - U1 H4 C1 A9 e! E+ n! G- L
当以如“archive(member) ”形式静态库为目标时,分别表示库文件成员; @2 g/ d" U7 G: l+ Y
“member”名中的目录部分和文件名部分。它仅对这种形式的规则目标有效。
1 b. H! Y; e& g( _$(<d)
% Z4 ?  n' z5 {" _4 R$ w  n$ o$(<f) & C; N$ B" @2 b! n
分别表示规则中第一个依赖文件的目录部分和文件名部分。
% I" M7 \# @9 a: n" m* [$(^D) 1 v& E7 Y1 M% v& J% r1 `+ k
$(^F)
1 g1 \  Y0 [" q1 o& [7 L: [" s8 G) \分别表示所有依赖文件的目录部分和文件部分(不存在同一文件)。
0 K9 Q4 b+ E6 W) N# ^$(+D) 3 v" v& g' `. ?5 M$ R' P/ y# L/ `
$(+F)
, R' o4 U* y7 C' x% Y- I分别表示所有依赖文件的目录部分和文件部分(可存在重复文件)。 " E# S; ~% ^* m# M3 O% r; E
$(?D)
3 K6 K; U) O1 @' d" e$(?F) 1 p* Y3 k: N/ ^
分别表示被更新的依赖文件的目录部分和文件名部分
在讨论自动化变量时,为了和普通变量(如:“CFLAGS ”)区别,我们直接使用了
. q" q" Q% L% r' [& ~: D- V“$<”的形式。这种形式仅仅是为了和普通变量进行区别,没有别的目的。其实对于
  |/ `8 P* o1 ~1 j自动环变量和普通变量一样,代表规则第一个依赖文件名的变量名实际上是“< ”,我
( O4 o5 P: ]7 v; @% M* j1 F们完全可以使用“$(<) ”来替代“$<”。但是在引用自动化变量时通常的做法是“$<”,
, V: {2 y! P" }, W因为自动化变量本身是一个特殊字符。 $ {; [5 t) l+ Q( r, ~2 ^2 `
GUN make同时支持“Sysv”特性,允许在规则的依赖列表中使用特殊的变量引
* o" n) e6 o' w4 j  Y6 I用(一般的自动化变量只能在规则的命令行中被引用)“$$@”、“$$(@D)”和“$$(@F)”& x$ h/ e2 H& W% g1 {
(注意:要使用“$$”),它们分别代表了“目标的完整文件名”、“目标文件名中的目
, |& t0 @+ U4 ]: m$ B9 H+ V录部分”和“目标的实际文件名部分”。这三个特殊的变量只能用在明确指定目标文件
1 p7 Q: ?0 Z' z2 f/ l名的规则中或者是静态模式规则中,不用于隐含规则中。另外Sysv make 和GNU make
5 w4 Z$ i( P1 D; G对规则依赖的处理也不尽相同。Sysv make对规则的依赖进行两次替换展开,而GUN & j& _" d) x* M. x7 @- Y
make对依赖列表的处理只有一次,对其中的变量和函数引用直接进行展开。 & g) ?/ w7 h( I( [# i
自动化变量的这个古怪的特性完全是为了兼容Sysv  版本的makefile文件。在使用
" i1 l+ H1 V( X  E5 u8 G+ qGNU make 时可以不考虑这个,也可以在Makefile中使用伪目标“.POSIX ”来禁止这一5 s3 C, n! }6 y) |/ D; P+ H
特性
" a) b! y( E0 N

本版积分规则

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

GMT+8, 2026-4-19 18:33 , Processed in 0.032179 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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