一乐电子

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

QQ登录

只需一步,快速开始

微信扫码登录

搜索
查看: 4852|回复: 1

Makefile中常用的函数----特别是MAKE -C

[复制链接]
发表于 2017-5-4 18:32 | 显示全部楼层 |阅读模式
在Makefile中可以使用函数来处理变量,从而让我们的命令或是规则更为的灵活和具有智能。make所支持的函数也不算很多,不过已经足够我们的操作了。函数调用后,函数的返回值可以当做变量来使用。9 f6 }3 W5 H9 A3 c% m8 s' m
一、函数的调用语法) t/ ?: U5 I, Y  e- J7 J% Y+ c
函数调用,很像变量的使用,也是以“$”来标识的,其语法如下:
/ |" C, [# ?. G* X/ [# Q! U    $(
  Y* _; T* _( k)# i% ], j% K/ U/ R, |+ r2 O
或是
8 t% j6 X4 _6 n, r    ${. [! V. V9 ^: U' U* V% G! E( m
}4 b1 y3 p$ S! l) q$ _/ H
这里,就是函数名,make支持的函数不多。是函数的参数,参数间以逗号“,”分隔,而函数名和参数之间以“空格”分隔。函数调用以“$”开头,以圆括号或花括号把函数名和参数括起。感觉很像一个变量,是不是?函数中的参数可以使用变量,为了风格的统一,函数和变量的括号最好一样,如使用“$(subst
! V& w' H, ~. I  ta,b,$(x))”这样的形式,而不是“$(subst a,b,${x})”的形式。因为统一会更清楚,也会减少一些不必要的麻烦。
, w/ r: l( m' `8 a6 G还是来看一个示例:
* X+ x& G/ {! I    comma:= ,
4 c- E3 z4 t% R% t0 [9 P2 l    empty:=
' O1 j/ T/ u' Z' y# n5 V& @* w    space:= $(empty) $(empty)
. t+ Y* ^9 T2 o( o    foo:= a b c/ K  {( K+ x& n# K
    bar:= $(subst $(space),$(comma),$(foo))# T2 o7 g5 e+ ^7 m' b: b! x% S) `
在这个示例中,$(comma)的值是一个逗号。$(space)使用了$(empty)定义了一个空格,$(foo)的值是“a b c”,$(bar)的定义用,调用了函数“subst”,这是一个替换函数,这个函数有三个参数,第一个参数是被替换字串,第二个参数是替换字串,第三个参数是替换操作作用的字串。这个函数也就是把$(foo)中的空格替换成逗号,所以$(bar)的值是“a,b,c”。1 N/ A, I, w8 g6 n/ ]2 O$ V7 [3 w
二、字符串处理函数
; ^5 Z1 X8 z0 P$(subst; x# T5 F# ~4 T. @$ u/ N
,,)

* n+ I8 U  n" Z7 l2 o' L5 l" Q    名称:字符串替换函数——subst。; q9 y% O2 s" g4 K, N' Z) T
    功能:把字串中的字符串替换成。- _& H5 @  A$ D& n2 q0 |
    返回:函数返回被替换过后的字符串。3 z  k, E7 k, [& ^( G9 O3 D& S
    示例:
% \# e# X$ F5 \2 D+ y  v6 D        ' H6 I" c3 ~7 |- O; h
        $(subst ee,EE,feet on the street),
+ e& i# J) K) G$ n2 x$ Q        : Z- e- O$ B0 ?, H2 ?
        把“feet on the street”中的“ee”替换成“EE”,返回结果是“fEEt& v5 d8 C2 y9 w  m8 e$ u: e
on the strEEt”。
/ r: ]% [% h$ q- Q* v: S4 C- x$(patsubst ,,) 6 N9 p/ q5 T+ n. }
    名称:模式字符串替换函数——patsubst。' O9 T7 Z/ {$ \  Y0 |* |
    功能:查找中的单词(单词以“空格”、“Tab”或“回车”“换行”分隔)是否符合模式,如果匹配的话,则以替换。这里,可以包括通配符“%”,表示任意长度的字串。如果中也包含“%”,那么,中的这个“%”将是中的那个“%”所代表的字串。(可以用“\”来转义,以“\%”来表示真实含义的“%”字符)$ Y# B$ D+ [* H2 U5 z3 N6 S
    返回:函数返回被替换过后的字符串。0 p8 P4 q; B6 l9 W4 b; Q
    示例:
3 b2 o5 ]( d6 a0 T/ v; P, s( M3 s! P       ! c2 r$ B' e& X$ o
$(patsubst %.c,%.o,x.c.c bar.c)
  J% e( ^1 a. `* u9 [+ m        把字串“x.c.c4 r) {8 x6 V6 C
bar.c”符合模式[%.c]的单词替换成[%.o],返回结果是“x.c.o
; C# ~8 g. Z- p6 G2 `bar.o”" Z: @, ?0 r. h) V6 F
    备注:! U/ X, F& H' T) @) V
        这和我们前面“变量章节”说过的相关知识有点相似。如:
7 }6 d- V( `+ s0 z4 X        “$(var:=)”$ O7 m3 V( ~0 k( y  u
         相当于% Y/ G1 c+ `' R7 E9 t
        “$(patsubst2 e/ E6 V' u: c: f4 Z# e1 b: c0 v
,,$(var))”,8 @& ~& _" H& {- x+ N
         而“$(var:
2 g8 _# W' Y2 K9 R2 Y=)”( U4 p8 G# e, @- R- t- T
         则相当于
! V% Q6 C6 `' L! h5 r* m7 G0 x         “$(patsubst! q3 e2 F% x1 F8 @  j. S
%,%,$(var))”。: I+ \$ r/ T2 P7 A
         例如有:objects = foo.o0 l4 m2 H2 n* s6 v% H7 E
bar.o baz.o,
  [0 L( l9 {1 h0 \2 y2 R  ]         那么,“$(objects:.o=.c)”和“$(patsubst1 [8 W) _9 g# R3 X- |
%.o,%.c,$(objects))”是一样的。
  R7 L3 g* q' {5 l) c* ]1 Z! f& w/ ^6 o$(strip )7 N" q( \$ B! t( f9 n, H  Q
    名称:去空格函数——strip。7 p& y4 `+ u5 `' N' B8 M
    功能:去掉字串中开头和结尾的空字符。* n6 [+ \9 R; \& W/ D# f$ _
    返回:返回被去掉空格的字符串值。% q- P5 ^% O, n
    示例:8 }: a, I2 I1 k1 d. l2 N, i( V
        ) c5 F; A  ~; o
        $(strip a b c )1 U, L. y% ]: K% e$ {* q2 D9 |
        把字串“a b7 g7 f) T/ H. K; m6 W6 G& d2 A+ ~
c ”去到开头和结尾的空格,结果是“a b c”。
+ ~# p% V' b: ^4 P. U. ~& H( t) _$(findstring ,)' e3 `" H7 Q8 E" f
    名称:查找字符串函数——findstring。8 H# Z% r* R% G9 y8 d4 v
    功能:在字串中查找字串。1 I0 |) f# C4 Y. M( d
    返回:如果找到,那么返回,否则返回空字符串。
' V8 H. C$ h' P/ r4 E" ?4 s    示例:
/ r+ H6 U% L, c  P2 d+ I$ X       5 ~% k+ @2 b  S. L
$(findstring a,a b c)8 _$ F  e; r' T. `7 w9 a
        $(findstring a,b c)# E6 `" u; M' [3 q2 S
        第一个函数返回“a”字符串,第二个返回“”字符串(空字符串)
& k+ z3 u$ m( d" }- ~+ R, l4 N$(filter
2 [/ K& |9 R8 y1 T. ?  g9 i9 b,)

$ |# d& c2 S1 |2 w4 Q1 Q( S    名称:过滤函数——filter。
; w/ ~/ t+ w+ M% S5 x) k' @  h+ v    功能:以模式过滤字符串中的单词,保留符合模式的单词。可以有多个模式。3 L  M  f6 S2 C$ Y
    返回:返回符合模式的字串。& [2 q; [5 q  e/ g6 X
    示例:& z; K1 p$ b4 }/ T: ]9 v" L, O+ j
        sources
3 J% a' A; ~. d3 k0 y:= foo.c bar.c baz.s ugh.h
  }& {5 n% `/ h: }. G        foo: $(sources)
& J4 n: j4 B1 f! n6 m5 }               + Y% [7 L' w1 I: f2 z- |
cc $(filter %.c %.s,$(sources)) -o foo; P) h5 O- X. b9 D+ ^1 {, [
      
5 o, m5 M: H7 W% X; I) Z$(filter %.c %.s,$(sources))返回的值是“foo.c bar.c baz.s”。* o$ S% ^+ D6 u2 L
$(filter-out) d& l) U+ j" P# ^0 k5 v
,)
# [. E. ]3 d5 N8 B7 a+ g$ ?* D
    名称:反过滤函数——filter-out。3 M1 a- h2 C  x  G2 c
    功能:以模式过滤字符串中的单词,去除符合模式的单词。可以有多个模式。' P; k- i  V% Y+ o4 I6 n
    返回:返回不符合模式的字串。: p5 P+ s! V: r( i. o" G
    示例:/ j, P# l9 _; {- e
       ) `3 N2 o0 Y3 \
objects=main1.o foo.o main2.o bar.o2 @2 R$ z. [1 {" {3 d
        mains=main1.o main2.o+ P1 ~. n1 A; }$ g; s
        / Y  n9 U$ a* }2 y3 N8 P
        $(filter-out $(mains),$(objects)) 返回值是“foo.o
" R. b+ K5 n  C1 B- `! Q) P  ]bar.o”。( E! }8 E1 {2 y, r& @& k! z8 a  o
        ; e$ x6 P" S" m9 a4 o5 I$ C/ ~
$(sort )2 U' q/ `' _. z
名称:排序函数——sort功能:给字符串中的单词排序(升序)。返回:返回排序后的字符串。示例:$(sort foo bar lose)返回“bar foo lose备注:sort函数会去掉中相同的单词。
+ r: ]* C3 @5 Y$(word ,)4 G! G2 Z8 |. ], v+ N% a" g* ?
名称:取单词函数——word功能:取字符串中第个单词。(从一开始)返回:返回字符串中第个单词。如果中的单词数要大,那么返回空字符串。示例:$(word 2, foo bar baz)返回值是“bar”。4 M/ A' S/ t) p8 r5 ^
$(wordlist
4 v3 P* h8 y% S# j" J2 M3 @,,)
  / W; G6 w2 L% u) `5 R
    名称:取单词串函数——wordlist。
. P1 S1 I- U5 Y    功能:从字符串中取从开始到的单词串。和是一个数字。( i  l$ q+ {7 O4 k
    返回:返回字符串中从到的单词字串。如果比中的单词数要大,那么返回空字符串。如果大于的单词数,那么返回从开始,到结束的单词串。( d- r5 g+ \% \5 c1 c( |  ~  }
    示例: $(wordlist 2, 3, foo bar baz)返回值是“bar& g% `4 p2 G* V& P0 V
baz”。
; z0 `; M, O1 c) W& m$(words )
) J& X' c; z( B0 O5 \    名称:单词个数统计函数——words。% j1 c5 B! _! j& T  n
    功能:统计中字符串中的单词个数。
' B8 W6 R1 {. D  o6 r# X& _3 j  ]    返回:返回中的单词数。
1 H1 b6 F+ |& Z1 C% P    示例:$(words, foo bar baz)返回值是“3”。8 j$ Z% \1 {1 N2 H* `% E( S+ j
    备注:如果我们要取中最后的一个单词,我们可以这样:$(word
4 b" W0 ^3 k" e5 N! @+ y; I# z$(words ),)。
# _/ T) o. u9 C# `% S) g5 g  F$(firstword )4 c" u, c3 a4 O
    名称:首单词函数——firstword。
  t  H2 h) g- U, r( n    功能:取字符串中的第一个单词。
% z- K! r* N! R! e7 I    返回:返回字符串的第一个单词。
1 F! h7 h) q3 C+ ]; `& R    示例:$(firstword foo bar)返回值是“foo”。/ I# @/ e! P( F. a& W$ A; |7 y6 ^
    备注:这个函数可以用word函数来实现:$(word
" I* V- G& a/ r1,)。, X  ^; G' M7 r
以上,是所有的字符串操作函数,如果搭配混合使用,可以完成比较复杂的功能。这里,举一个现实中应用的例子。我们知道,make使用“VPATH”变量来指定“依赖文件”的搜索路径。于是,我们可以利用这个搜索路径来指定编译器对头文件的搜索路径参数CFLAGS,如:
3 }! n" l, M# l    override CFLAGS += $(patsubst
& B- ^# c, N" i7 Z0 w8 T( U%,-I%,$(subst :, ,$(VPATH)))9 ^! A  i( }9 I3 E( D: |( J
    如果我们的“$(VPATH)”值是“src:../headers”,那么“$(patsubst
& j- E; a' N. j2 w# s. o8 w%,-I%,$(subst :, ,$(VPATH)))”将返回“-Isrc -I../headers”,这正是cc或gcc搜索头文件路径的参数。
: ?' ?# F+ u) {" V+ a  |6 m/ T三、文件名操作函数
/ _; d. L  _. m  q下面我们要介绍的函数主要是处理文件名的。每个函数的参数字符串都会被当做一个或是一系列的文件名来对待。+ e3 z8 Y, i; [
$(wildcard )
' _# u3 }" w) |名称:文件名展开函数——wildcard 。
/ Y5 k" N' E& K; t7 G7 G: `9 X7 u! W    功能:功能是展开成一列所有符合由其参数描述的文件名,文件间以空格间隔。2 `( `7 M$ T" S( S1 k5 ~0 u+ O
    返回:函数返回展开后的文件名列表。
; B( C4 `# B4 o6 \# b# {, O0 x    . a# P' ?" {$ y4 v, K
示例:: A) U; z0 Q  H6 h: R+ f: n$ ]
        & W; q/ T" C5 l/ x8 A2 ]; |
        $(wildcard *.c)
6 C$ C  R7 b' X) I7 e, y2 r        
- B; y) y" K3 J0 _5 N9 s  j        返回结果是一个所有以 '.c' 结尾的文件的列表。
4 B0 M: H4 P6 Z; S& h% H( C$(dir ) " _; p2 C. y* h$ @: e5 u
    名称:取目录函数——dir。
2 @# w5 P* j1 }/ @4 J    功能:从文件名序列中取出目录部分。目录部分是指最后一个反斜杠(“/”)之前的部分。如果没有反斜杠,那么返回“./”。
  B6 t& N2 {! P, P% |    返回:返回文件名序列的目录部分。
8 O+ ]; n( n& k    示例: $(dir src/foo.c hacks)返回值是“src/- F, k& d% \$ T) X
./”。: M: H5 ~6 K3 V
$(notdir )
# K) w* r2 }! t% a# u    名称:取文件函数——notdir。6 z0 K" X, Y$ I/ c- @
    功能:从文件名序列中取出非目录部分。非目录部分是指最后一个反斜杠(“/”)之后的部分。& |6 A: o* L" k8 z
    返回:返回文件名序列的非目录部分。
( e6 M0 M2 @1 @8 ]+ w    示例: $(notdir src/foo.c hacks)返回值是“foo.c- `3 U# S  y1 R, U0 U& T
hacks”。
/ _4 ]# W8 z$ m" m% @2 w
) ?- I5 U, X2 z8 a$(suffix )
. `. ^+ [" c7 n    % M( y- o" [9 [8 T
    名称:取后缀函数——suffix。
3 R; w; S$ R3 z5 Z    功能:从文件名序列中取出各个文件名的后缀。- a  d- {4 a; S" t# g9 Q
    返回:返回文件名序列的后缀序列,如果文件没有后缀,则返回空字串。7 a  T. S( j9 @+ ^- K' |
    示例:$(suffix src/foo.c src-1.0/bar.c hacks)返回值是“.c6 a. W7 w" E3 J) F, Y0 s
.c”。  k0 m- I1 X. y( j9 g& x
$(basename ); O* ]7 x6 w0 ]
    名称:取前缀函数——basename。& S/ A  Q1 u) Y" n& T% R$ C5 @( U
    功能:从文件名序列中取出各个文件名的前缀部分。
1 _& Y% D# @( N  c9 }( T    返回:返回文件名序列的前缀序列,如果文件没有前缀,则返回空字串。
3 }$ y  {7 W' ?4 x2 j' Z1 j/ H9 }  V    示例:$(basename src/foo.c src-1.0/bar.c hacks)返回值是“src/foo
3 z9 x* K0 N- ]src-1.0/bar hacks”。
8 M4 T/ V* j+ d: b& n7 l$(addsuffix
) O# V; l# g; E6 `. A,)
% [4 {2 G) \/ |
    名称:加后缀函数——addsuffix。$ o+ J6 Q3 _2 b/ P5 N
    功能:把后缀加到中的每个单词后面。* V! q$ u& D9 i; p: Y8 f
    返回:返回加过后缀的文件名序列。
4 `# D+ J* O1 c# I+ u8 l    示例:$(addsuffix .c,foo bar)返回值是“foo.c( K/ i4 {8 U$ G1 K' L
bar.c”。7 y8 v1 z+ K: S, d$ u( p$ }8 Z
$(addprefix6 f$ n# j# J! G5 L; g7 G- U
,)

  q# S+ m+ }: y! H( l  g    名称:加前缀函数——addprefix。! F- g& l' T# A+ z; }
    功能:把前缀加到中的每个单词后面。
- p2 ~! V3 a- K' E, [: x    返回:返回加过前缀的文件名序列。& @1 B3 m4 o1 P" ]+ l( W. ?
    示例:$(addprefix src/,foo bar)返回值是“src/foo) W! i! N" U$ q* c0 D& Z
src/bar”。; s, f5 m$ W9 I  L; z* g8 h
$(join ,)2 ]+ B. a3 K; z8 {
    名称:连接函数——join。
, Q5 m  H' [7 S% [  J    功能:把中的单词对应地加到的单词后面。如果的单词个数要比的多,那么,中的多出来的单词将保持原样。如果的单词个数要比多,那么,多出来的单词将被复制到中。
3 N9 L1 u% D" ^) B    返回:返回连接过后的字符串。  r( W% S& y) S/ ^4 I7 e  _9 d0 ^
    示例:$(join aaa bbb , 111 222 333)返回值是“aaa111* ?4 B0 |: f# f4 a) q. @% w" `/ [1 U: c
bbb222 333”。
9 r+ T" K* Q, Y8 ^" r2 e2 o
# H8 I) Z' K: l) _* m四、foreach 函数
  \( [! d# {* V6 u% s. m
0 s8 D6 F0 ]4 ~foreach函数和别的函数非常的不一样。因为这个函数是用来做循环用的,Makefile中的foreach函数几乎是仿照于Unix标准Shell(/bin/sh)中的for语句,或是C-Shell(/bin/csh)中的foreach语句而构建的。它的语法是:
2 H6 V* C7 I4 e/ {: A
) a" p- k- F1 ^    $(foreach" G; t' m' K4 a+ M0 G8 G/ n& B
,,)' G' ?0 b- J$ I0 a5 ]6 z$ u. z
2 V  A4 C$ _9 E6 b. h  v
这个函数的意思是,把参数中的单词逐一取出放到参数所指定的变量中,然后再执行所包含的表达式。每一次会返回一个字符串,循环过程中,的所返回的每个字符串会以空格分隔,最后当整个循环结束时,所返回的每个字符串所组成的整个字符串(以空格分隔)将会是foreach函数的返回值。$ J! G+ w% C/ i( O

2 \. Q1 b4 v8 R0 c所以,最好是一个变量名,可以是一个表达式,而中一般会使用这个参数来依次枚举中的单词。举个例子:! c$ C: x* E, E# A* {  Z; F

$ W0 U0 c5 O. s: Z' q0 L    names := a b c d- O) }( i! r0 S; V/ g. j: `! d
    files := $(foreach n,$(names),$(n).o)
; _5 o; |2 f3 E% |/ b0 k0 s! |4 Q2 T/ x. O; u5 C$ A0 `$ F
上面的例子中,$(name)中的单词会被挨个取出,并存到变量“n”中,“$(n).o”每次根据“$(n)”计算出一个值,这些值以空格分隔,最后作为foreach函数的返回,所以,$(files)的值是“a.o b.o c.o d.o”。9 }* B9 h* b7 r  }3 B7 Q9 o1 P
. r2 d* h) n- M2 G! j* f9 S! Y$ ]0 k9 ?
注意,foreach中的参数是一个临时的局部变量,foreach函数执行完后,参数的变量将不在作用,其作用域只在foreach函数当中。
8 I8 w+ e7 A, i; r7 W* @8 ~2 N, E  D& y( D

/ V* D: B8 [# Y/ x五、if 函数
; ^7 v5 O$ W; Y% Q& D# `/ S
! L9 E6 }6 q3 hif函数很像GNU的make所支持的条件语句——ifeq(参见前面所述的章节),if函数的语法是:* |% C) R0 i# A% j4 }

5 `' E" I, N, X' ]& z    $(if ,)
6 p4 B) @" ]7 `  X1 `' v6 y0 Q1 M: o
或是# E" o2 W% s! ~6 j4 O# ?# I1 ~
) e/ U- c! H7 X0 J6 |
    $(if
0 f( o, U! y" _6 @,,)0 T- O+ G# D1 }% k1 W
: d" R( p1 M0 ~
可见,if函数可以包含“else”部分,或是不含。即if函数的参数可以是两个,也可以是三个。参数是if的表达式,如果其返回的为非空字符串,那么这个表达式就相当于返回真,于是,会被计算,否则会被计算。
) F  \$ O; y  f+ Z, u2 j, |2 q6 S, [6 a2 j5 Z- X5 [
而if函数的返回值是,如果为真(非空字符串),那个会是整个函数的返回值,如果为假(空字符串),那么会是整个函数的返回值,此时如果没有被定义,那么,整个函数返回空字串。3 ?* U* X/ Q; M* S3 j' s3 }* v
% U4 p4 m+ s/ ]& v- ^
所以,和只会有一个被计算。
9 i% a  P4 l# d  r0 [- w$ r; v9 q# K3 q" w: k! G; \- Z

! i+ \( o. g: q' u+ b$ E六、call函数. b. B& {: H, h. J; z9 O! ^- ^- f7 \, \

/ I5 Y% W6 h5 [- m" z/ n  u/ T" tcall函数是唯一一个可以用来创建新的参数化的函数。你可以写一个非常复杂的表达式,这个表达式中,你可以定义许多参数,然后你可以用call函数来向这个表达式传递参数。其语法是:& z# D' k( o9 B$ {) s
3 s) s) @3 Y1 K* l3 R- g
    $(call
3 g& ~" n5 _6 f5 ~' M,,,...)
! w: O- t6 i2 d& @! q
) Z( D" F, c: F' z: u当make执行这个函数时,参数中的变量,如$(1),$(2),$(3)等,会被参数,,依次取代。而的返回值就是call函数的返回值。例如:
/ i3 L/ _/ U1 \" @. s# E  p; f    reverse =  $(1) $(2)
$ Z6 c2 D/ d, {7 b$ t8 c    foo = $(call reverse,a,b)
+ e' E4 ?; V! Y0 U6 F$ g那么,foo的值就是“a b”。当然,参数的次序是可以自定义的,不一定是顺序的,如:
4 u" O  I0 H( q6 B2 u- k
0 H8 A( ~, w/ t+ k& A: ]; F    reverse =
" \8 H4 A' n& E) g$(2) $(1)8 j4 ~1 M- ?# O5 Z# X1 n' l
    foo = $(call reverse,a,b)9 j" x4 O5 B6 f+ }: ^$ Y6 D
此时的foo的值就是“b a”。
" I; B% C5 P, I" i% l
. i6 T( x8 w  g% H- f+ U; |, Q
! J; D$ t; [. `# d% e/ a七、origin函数: \2 X+ p. l3 I
origin函数不像其它的函数,他并不操作变量的值,他只是告诉你你的这个变量是哪里来的?其语法是:
1 ~% s" \9 k, P$ U! y% O/ c
) f0 l& J6 O; }    $(origin )- A& I" v% q# X5 w5 q+ ]7 @

6 ^* m" E9 C. n) q+ r+ T0 m注意,是变量的名字,不应该是引用。所以你最好不要在中使用“$”字符。Origin函数会以其返回值来告诉你这个变量的“出生情况”,下面,是origin函数的返回值:0 o# Q* X; y1 U6 n  |+ q

; e$ j' Q1 G  r% q1 H/ ~% T. J% e9 e“undefined”
: ~7 r5 S0 C, T" [2 J7 [" e! a      如果从来没有定义过,origin函数返回这个值“undefined”。
( T4 L% |7 G( I3 f" I% A, w9 Z7 [6 o# k
“default”
, C6 c, C3 e$ ]6 T* z+ @0 I      如果是一个默认的定义,比如“CC”这个变量,这种变量我们将在后面讲述。
2 e3 c! ]9 g+ N, T% M+ u1 c& j0 i& f) W% `! a
“environment”# Q8 k7 c+ F4 c, R
      如果是一个环境变量,并且当Makefile被执行时,“-e”参数没有被打开。
/ i5 R$ u& O* ?+ G- D! T
7 c$ j3 X$ Q( H2 ?$ y! y8 T“file”
( t- d4 R' p1 j8 t" C' a1 b: ^      如果这个变量被定义在Makefile中。
' P# d! h4 o* t1 s0 _  e0 D& K) H  \. b2 K) ]- F5 }) x, T* g% d
“command, s; W. c% L; @: f+ ?9 E
line”
# A6 }. n, U! Q' v8 V: e      如果这个变量是被命令行定义的。/ W6 P" j% a% r+ q, \# N* t2 J% r' a

0 q/ c& v# o5 z“override”
. q0 Y) _1 ^) h( q+ d9 R% ?% F      如果是被override指示符重新定义的。
. {. E  n$ C- u, z8 C) o
0 T( m: e0 b; k7 a! x“automatic”& l4 x8 |0 C" v% i
      如果是一个命令运行中的自动化变量。关于自动化变量将在后面讲述。
; ?5 [7 _  E0 w2 r% ]! Z( ]' S5 F
$ j* F2 Q/ j( O这些信息对于我们编写Makefile是非常有用的,例如,假设我们有一个Makefile其包了一个定义文件Make.def,在Make.def中定义了一个变量“bletch”,而我们的环境中也有一个环境变量“bletch”,此时,我们想判断一下,如果变量来源于环境,那么我们就把之重定义了,如果来源于Make.def或是命令行等非环境的,那么我们就不重新定义它。于是,在我们的Makefile中,我们可以这样写:
0 [3 ]) o% s4 e) e+ o% \% _- D+ g. u  C( e1 f9 P
    ifdef bletch
) s8 t3 v0 @& s  N% J5 ]    ifeq "$(origin bletch)"8 b' t+ r" O. @: g, X, d
"environment"
7 b) @8 ~, _' J& g' Z8 u    bletch = barf, gag, etc.
' N4 a' G. J3 P. `/ P: a    endif2 }  c" ?% z+ ?# `; Q
    endif* |" S# j$ U9 s. M$ b9 H! l
& W2 [! `- ~: \/ m' A% q6 }2 K
当然,你也许会说,使用override关键字不就可以重新定义环境中的变量了吗?为什么需要使用这样的步骤?是的,我们用override是可以达到这样的效果,可是override过于粗暴,它同时会把从命令行定义的变量也覆盖了,而我们只想重新定义环境传来的,而不想重新定义命令行传来的。
/ T6 X/ C( K0 r. b( R. o. R; {+ g
. h) x1 \- |/ i) M7 d3 M! b5 v. i
八、shell函数) _! s! N" [7 L" V
2 X/ k, p" r& i' N& ?& s
shell函数也不像其它的函数。顾名思义,它的参数应该就是操作系统Shell的命令。它和反引号“`”是相同的功能。这就是说,shell函数把执行操作系统命令后的输出作为函数返回。于是,我们可以用操作系统命令以及字符串处理命令awk,sed等等命令来生成一个变量,如:4 g# i0 D0 e% |

  t* l2 Z2 s9 {0 N! E0 ]8 s    contents := $(shell cat foo)
, S2 B$ _+ C1 E7 Z! t. e/ a  V* k, ?+ _" @- r/ X; z: O) O- I
    files := $(shell echo *.c). X4 I/ ]5 L. o
8 `# Q' l" [0 x$ C( f" h! {# K
注意,这个函数会新生成一个Shell程序来执行命令,所以你要注意其运行性能,如果你的Makefile中有一些比较复杂的规则,并大量使用了这个函数,那么对于你的系统性能是有害的。特别是Makefile的隐晦的规则可能会让你的shell函数执行的次数比你想像的多得多。
% o1 U$ c* t) j/ y% g                2 g) `  ]$ n6 g9 ~
 楼主| 发表于 2017-5-4 18:33 | 显示全部楼层
在linux项目中,使用makefile来规定编译规则。7 Q" m. Q: {) h' \3 N. g
makefile中如何调用到子目录下的makefile呢,有很多中方式。
2 ^/ `0 l: L8 A1 n9 X0 }2 m在这里,我要使用的是 -C2 O& c% Q2 \& L
- N6 z" l( f' o8 ?4 c: \
28458801_1414577793Z2n9.jpg * ^/ o: A1 v4 p  z+ y
28458801_1414577808K1i9.jpg
, N0 F& T6 J& e1 Q) U0 R4 H& u6 j5 f& \( |$ M5 n
6 u; z. K& U: J5 k+ m# p9 q- d( [- }
点击(此处)折叠或打开

5 B" F, M- T6 j- a2 p
  • # ============= lib compile option ===========#
  • LIB_TARGET := libzbar.a
  • EXP_LIB_INC := $(IMP_INC_DIR)/zbar
  • LIB_SRC := $(PWD)/zbar
  • LIB_CFLAGS := $(ARCH_FLAGS) -fstack-protector -Wall -Wno-parentheses -I$(IMP_INC_DIR) -I$(EXP_LIB_INC) -I$(IMP_TARGET_DIR)
  • LIB_CPPFLAGS:=$(LIB_CFLAGS)
  • LIB_LDFLAGS := -lpthread -L$(PWD)/zbar -lrt -fPIC $(EX_LDFLAGS)
  • # ---------------------------------------------#
  • LIB_MAKE_PARAM := -C $(LIB_SRC)
  • TARGET=$(LIB_TARGET)
  • EXPORT_INC_FILE="$(PWD)/zbar/zbar_interface.h"
  • EXPORT_TARGET_DIR=$(EXP_TARGET_DIR)
  • EXPORT_INC_DIR=$(EXP_INC_DIR)
  • CFLAGS="$(LIB_CFLAGS)"
  • CXXFLAGS="$(LIB_CFLAGS)"
  • LDFLAGS="$(LIB_LDFLAGS)"5 ?" V# H3 ~7 G) ~; N
0 m% i  F3 ^, i/ X' Z: s5 X7 l
0 y  J. ?) }# S- I8 s( K

8 ]  J+ m  b$ D3 `" D0 N- R% y( I7 S
$ I( j! m; {& a4 D# |! Z- `$ A. e' P5 M; b/ l* h

6 D' N% o  j# M. {' m8 `1 \, P$ Z
1 \1 ?! b; |, I2 Q

- t# D! @& b0 Z, S% a4 a6 \
回复

使用道具 举报

本版积分规则

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

GMT+8, 2025-8-20 09:02 , Processed in 0.045652 second(s), 23 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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