Makefile 笔记

1 Makefile的一般语法

targets ... : prerequisties ...  or targets ... : prerequisties ... ;command

[TAB键开头]command

...
  • targets:可以是一个或多个目标文件,,还可以是标签(Label)
  • prerequisites:就是要生成target所需要的文件或是目标。
  • command:也就是make需要执行的命令。(任意的Shell命令)。定义了如何使用prerequisites来生成targets

 例子:

一个简单的例子
 1 edit : main.o kbd.o command.o display.o \
 2 insert.o search.o files.o utils.o
 3     cc -o edit main.o kbd.o command.o display.o \
 4 insert.o search.o files.o utils.o
 5 main.o : main.c defs.h
 6     cc -c main.c
 7 kbd.o : kbd.c defs.h command.h
 8     cc -c kbd.c
 9 command.o : command.c defs.h command.h
10     cc -c command.c
11 display.o : display.c defs.h buffer.h
12     cc -c display.c
13 insert.o : insert.c defs.h buffer.hcc -c insert.c
14 search.o : search.c defs.h buffer.h
15     cc -c search.c
16 files.o : files.c defs.h buffer.h command.h
17     cc -c files.c
18 utils.o : utils.c defs.h
19     cc -c utils.c
20 clean :
21     rm edit main.o kbd.o command.o display.o \
22 insert.o search.o files.o utils.o

Notice:'\'与c语言一样,是换行符

2 make命令是如何工作的

  1. 在当前目录下找名字叫“Makefile”或“makefile”的文件
  2. 如果找到,会以文件中第一个目标作为最终目标
  3. 如果最终目标的依赖对象中有任意一个做过修改或最终目标不存在时,则执行后面的命令。

3 变量的使用

makefile中的变量与c语言中的预处理命令#define很相似,只是简单的字符串替换,如:

objects=a.o b.o c.o
main.out:$(objects)
    gcc -o main.out $(objects)

4 makefile的自动推导

GNU的make很强大,它可以自动推导文件以及文件依赖关系后面的命令,于是我们就没必要去在每一个[.o]文件后都写上类似的命令,因为,我们的make会自动识别,并自己推导命令。只要make看到一个[.o]文件,它就会自动的把[.c]文件加在依赖关系中,如果make找到一个 whatever.o,那么 whatever.c,就会是 whatever.o 的依赖文件。并且 gcc -c whatever.c 也会被推导出来,于是,我们的makefile再也不用写得这么复杂。如:

main.out:a.o b.o

#因为makefile的自动推导,所以不用添加依赖a.c及命令gcc -c a.c
a.o:a.h

Notice:makefile的命令前加个减号的意思是也许某些文件出现问题,但不要管,继续做后面的事。

5 引用其他makefile

就像c语言的#include,它可以把其他makefile的内容插进来。如:

include foo.make a.mk b.mk c.mk e.mk f.mk

make会在当前目录下首先寻找include下的makefile,如果当前目录下没有找到,那么,make还会在
下面的几个目录下找:

  1. 如果make执行时,有“-I”或“--include-dir”参数,那么make就会在这个参数所指定的目录下去寻找。

  2. 如果目录<prefix>/include(一般是:/usr/local/bin或/usr/include)存在的话,make也会去找

6 环境变量MAKEFILES

当设置了环境变量MAKEFILES后,make命令运行时会把MAKEFILES变量下的makefile文件include进来,但这些makefile文件中的目标不会被执行。

强烈建议不要使用MAKEFILES环境变量!

7 GUN的make命令的执行步骤

  1. 读入所有的Makefile
  2. 读入被include的其它Makefile。
  3. 初始化文件中的变量。
  4. 推导隐晦规则,并分析所有规则。
  5. 为所有的目标文件创建依赖关系链。
  6. 根据依赖关系,决定哪些目标要重新生成。
  7. 执行生成命令。

如果定义的变量被使用了,那么,make会把其展开在使用的位置。但make并不会完全马上展开,make使用的是拖延战术,如果变量出现在依赖关系的规则中,那么仅当这条依赖被决定要使用了,变量才会在其内部展开。

Notice:makefile中支持三个通配符:*,?,...

8 文件搜寻

当make需要去找寻文件的依赖关系时,你可以在文件前加上路径,但最好的方法是把一个路径告诉make,让make自动去找。Makefile文件中的特殊变量“VPATH”就是完成这个功能的,如果没有指明这个变量,make只会在当前的目录中去找寻依赖文件和目标文件。如果定义了这个变量,那么,make就会在当前目录找不到的情况下,到所指定的目录中去找寻文件了。VPATH变量的设定类似环境变量PATH设定一样,以':'分隔多个路径,如:

VPATH = src:../headers

另一个设置文件搜索路径的方法是使用make的“vpath”关键字(注意,它是全小写的),这不是变量,这是一个make的关键字,这和上面提到的那个VPATH变量很类似,但是它更为灵活。它可以指定不同的文件在不同的搜索目录中。这是一个很灵活的功能。它的使用方法有三种:

  1. vpath <pattern> <directories> :为符合模式<pattern>的文件指定搜索目录<directories>。
  2. vpath <pattern> :清除符合模式<pattern>的文件的搜索目录
  3. vpath :清除所有已被设置好了的文件搜索目录。

vapth使用方法中的<pattern>需要包含“%”字符。 “%”的意思是匹配零或若干字符,例如,“%.h”表示所有以“.h”结尾的文件。<pattern>指定了要搜索的文件集,而<directories>则指定了<pattern>的文件集的搜索的目录。例如:

vpath %.h ../headers

该语句表示,要求make在“../headers”目录下搜索所有以“.h”结尾的文件。 (如果某文件在当前目录没有找到的话)我们可以连续地使用vpath语句,以指定不同搜索策略。如果连续的vpath语句中出现了相同的<pattern>,或是被重复了的<pattern>,那么,make会按照vpath语句的先后顺序来执行搜索。如:

vpath %.c foo:bar
vpath % blish

而上面的语句则表示“.c”结尾的文件,先在“foo”目录,然后是“bar”目录,最后才是“blish”目录。

9 伪目标

伪目标,就是该目标并不是对应一个文件,而仅仅是一个标志。可使用 .PHONY来强制指定目标为伪目标。伪目标与普通的目标实际上没有太多的区别。

伪目标的简单使用
 1 .PHONY: cleanall cleanobj cleandiff
 2 
 3 cleanall : cleanobj cleandiff
 4 rm program
 5 
 6 cleanobj :
 7 rm *.o
 8 
 9 cleandiff :
10 rm *.diff

10 多目标

当使用多目标时,可以使用自动化变量$@,“$@”表示目标的集合,就像一个数组,“$@”依次取出目标,并执行命令。同理,也会有表示依赖目标集的自动化变量“$<”

11 静态模式

静态模式的语法:

<targets ...>: <target-pattern>: <prereq-patterns ...>
<commands>
...

targets:定义了一系列的目标文件,可以有通配符,是目标的一个集合。

target-pattern:用于过滤targets,满足pattern的目标使用后面的依赖列表。

prereq-parrterns:满足pattern的targets使用的依赖列表

例子:

1 objects = foo.o bar.o
2 
3 all: $(objects)
4 
5 $(objects): %.o: %.c
6 gcc -c $< -o $@

12 自动生成依赖性

我们可以使用C/C++编译器的“-M”或"-MM"选项,即自动找寻源文件中包含的头文件,来生成某个源文件的依赖目标。

GNU组织建议把编译器为每一个源文件的自动生成的依赖关系放到一个文件中,为每一个“name.c”的文件都生成一个“name.d”的Makefile文件,[.d]文件中就存放对应[.c]文件的依赖关系。

这里,我们给出了一个模式规则来产生[.d]文件:

1 #其中$$$$用于生成随机数字
2 %.d: %.c
3 @set -e; rm -f $@; \
4 $(CC) -M $(CPPFLAGS) $< > $@.$$$$; \
5 sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \
6 rm -f $@.$$$$

Notice:上面的代码还没有完全搞懂,以后再去搞清楚

上面这段代码完成这样的转换,如把

1 main.o : main.c defs.h

转换成

main.o main.d : main.c defs.h

13 打印make执行过程中的命令

默认情况下,make是会在终端打印执行过程中的命令,但如在命令前加“@“则不会打印命令。如:

@echo 测试隐藏命令

当使用make的-n(--just-print)选项,则只会在终端打印命令,而不会实际执行命令,这用于调试makefile。

当使用make的-s(--silent)选项,则全面禁止命令的显示。

14 命令执行

如果你要让上一条命令的结果应用在下一条命令时,应该使用分号分隔这两条命令。如:

1 exec:
2 cd /home/hchen; pwd #打印的工作目录是/home/hchen

 

15 命令出错

make执行中忽略错误的方式有三种:

  1. 在命令前加'-'来忽略该命令的错误继续执行。
  2. 如果一个规则是以“.IGNORE”作为目标的,那么这个规则中的所有命令将会忽略错误

  3. 给make加上“-i”或是“--ignore-errors”参数,那么,Makefile中所有命令都会忽略错误

Notice:make的选项"-k”或是“--keep-going”的作用是如果某条规则的命令出错,就跳过该规则继续执行其他规则

16 嵌套执行make

在一些大的工程中,我们会把我们不同模块或是不同功能的源文件放在不同的目录中,我们可以在每个目录中都书写一个该目录的Makefile,这有利于让我们的Makefile变得更加地简洁,而不至于把所有的东西全部写在一个Makefile中,这样会很难维护我们的Makefile,这个技术对于我们模块编译和分段编译有着非常大的好处。

一般地,我们会在项目的顶层目录下创建总控Makefile,如:

subsystem:
cd subdir && $(MAKE)
#或
#subsystem:
#$(MAKE) -C subdir

 

 像这样嵌套执行make,总控Makefile的变量默认是可以传递给下级Makefile的。可通过 export 变量名 方式显示声明该变量传递到下级makefile,或 unexport 变量名 方式显示声明该变量不能传递到下级makefile。如:

export variable = value
#等价于
#variable = value
#export variable

 

Notice:如果只单独给出export,则该makefile中所以的变量都可以传递到下级makefile。

Notice:make命令的'w'或'--print-directory'选项,可以打印当前make命令进入的工作目录。

17 定义命令包

可以使用define和endef来定义命令包,该命令包的包名就可以好像变量那样使用了。如:

1 define run-yacc
2 yacc $(firstword $^)
3 mv y.tab.c $@
4 endef
5 
6 foo.c : foo.y
7 $(run-yacc)

18 变量赋值

可以在变量名前加'$'来使用变量,建议以()或{}把变量括起来。

"a=$(b)":把变量b的值赋给变量a,变量b可以在后面定义。

"a:=$(b)":把变量b的值赋给变量a,变量b要在之前定义。

"a?=$(b)": 如果a未定义过,则赋值,否则不作处理。

"a+=b":往变量a追加字符b。

“$(var:a=b)”或是“${var:a=b}”,其意思是,把变量“var”中所有以“a”字串“结尾”的“a”替换成“b”字串。这里的“结尾”意思是“空格”或是“结束符”。如:

foo := a.o b.o c.o
bar := $(foo:.o=.c)
#bar的值就为a.c b.c c.c

把变量的值当作变量:

x = y
y = z
a := $($(x))
#a的值会是z

 19  override 指示符

如果有变量是通常make的命令行参数设置的,那么Makefile中对这个变量的赋值会被忽略。如果你想在Makefile中设置这类参数的值,那么,你可以使用“override”指示符。其语法是:

override <variable> = <value>

20 环境变量与makefile变量的关系

环境变量可以作为makefile的变量,如果make命令行或makefile中定义的变量名与环境变量相同,则忽略环境变量。上层makefile传递到下层makefile的变量实际上可以看作是环境变量。

21 目标变量

前面提到的变量都可以看作是“全局变量”,因为他们在整个make过程有效。但也可以定义目标变量,这些变量的作用范围是目标所在的规则以及连带规则中。

语法:

<target ...> : <variable-assignment>

例子:

prog : CFLAGS = -g

prog : prog.o foo.o bar.o
gcc $(CFLAGS) prog.o foo.o bar.o

prog.o : prog.c
gcc $(CFLAGS) prog.c

foo.o : foo.c
gcc $(CFLAGS) foo.c

bar.o : bar.c
gcc $(CFLAGS) bar.c

22 模式变量

通过上面的目标变量中,我们知道,变量可以定义在某个目标上。模式变量的好处就是,我们可以给定一种“模式”,可以把变量定义在符合这种模式的所有目标上。

如:

%.o : CFLAGS = -O

23 条件判断

makefile有4种条件判断语句:ifeq,ifneq,ifdef,ifndef。

例子:

条件判断例子
 1 libs_for_gcc = -lgnu
 2 normal_libs =
 3 
 4 ifeq ($(CC),gcc)
 5 libs=$(libs_for_gcc)
 6 else
 7 libs=$(normal_libs)
 8 endif
 9 
10 foo: $(objects)
11 $(CC) -o foo $(objects) $(libs)

24 函数的语法

#function为函数名,arguments是参数列表,参数间以','分隔。函数名与参数列表以空格分隔
$(<function> <arguments> )

 

25 字符串处理函数

$(subst <from>,<to>,<text> ) 

说明 :把<test>中的<from>字符串替换为<to>

 

$(patsubst <pattern>,<replacement>,<text> )

说明:查找<text>中的单词(单词以“空格”、“Tab”或“回车”“换行”分隔)是否符合模式<pattern>,如果匹配的话,则以<replacement>替换。这里,<pattern>可以包括通配符“%”,表示任意长度的字串。如果<replacement>中也包含“%”,那么,<replacement>中的这个“%”将是<pattern>中的那个“%”所代表的字串。

 

$(strip <string> )

说明:去掉<string>字串中开头和结尾的空字符。

 

$(findstring <find>,<in> )

说明:在字串<in>中查找<find>字串,如果找到,那么返回<find>,否则返回空字符串

 

$(filter <pattern...>,<text> )

说明:以<pattern>模式过滤<text>字符串中的单词,保留符合模式<pattern>的单词。可以有多个模式。返回符合模式<pattern>的字串

 

$(filter-out <pattern...>,<text> )

说明:与filter函数相反,返回不符合模式<pattern>的字串

 

$(sort <list> )

说明:给字符串<list>中的单词排序(升序),返回排序后的字符串

 

$(word <n>,<text> )

说明:取字符串<text>中第<n>个单词。(从一开始)返回字符串<text>中第<n>个单词。如果<n>比<text>中的单词数要大,那么返回空字符串。

 

$(wordlist <s>,<e>,<text> )

说明:从字符串<text>中取从<s>开始到<e>的单词串。<s>和<e>是一个数字。返回:返回字符串<text>中从<s>到<e>的单词字串。如果<s>比<text>中的单词数要大,那么返回空字符串。如果<e>大于<text>的单词数,那么返回从<s>开始,到<text>结束的单词串

 

$(words <text> )

说明:统计<text>中字符串中的单词个数

 

$(firstword <text> )

说明:取字符串<text>中的第一个单词

26 文件名操作函数

$(dir <names...> )

说明:从文件名序列<names>中取出目录部分。目录部分是指最后一个反斜杠(“/”)之前的部分。如果没有反斜杠,那么返回“./”。

示例:$(dir src/foo.c hacks)返回值是“src/ ./”。

 

$(notdir <names...> )

说明:从文件名序列<names>中取出非目录部分。非目录部分是指最后一个反斜杠(“/”)之后的部分。

 

$(suffix <names...> )

说明:从文件名序列<names>中取出各个文件名的后缀。返回文件名序列<names>的后缀序列,如果文件没有后缀,则返回空字串。

 

$(basename <names...> )

说明:从文件名序列<names>中取出各个文件名的前缀部分。返回文件名序列<names>的前缀序列,如果文件没有前缀,则返回空字串。

 

$(addsuffix <suffix>,<names...> )

说明:把后缀<suffix>加到<names>中的每个单词后面。返回加过后缀的文件名序列。

 

$(addprefix <prefix>,<names...> )

说明:把前缀<prefix>加到<names>中的每个单词前面。返回加过前缀的文件名序列。

 

$(join <list1>,<list2> )

说明:把<list2>中的单词对应地加到<list1>的单词后面。如果<list1>的单词个数要比<list2>的多,那么,<list1>中的多出来的单词将保持原样。如果<list2>的单词个数要比<list1>多,那么,<list2>多出来的单词将被复制到<list1>中。

 

27 foreach函数

$(foreach <var>,<list>,<text> )

说明:把参数<list>中的单词逐一取出放到参数<var>所指定的变量中,然后再执行<text>所包含的表达式。每一次<text>会返回一个字符串,循环过程中,<text>的所返回的每个字符串会以空格分隔,最后当整个循环结束时,<text>所返回的每个字符串所组成的整个字符串(以空格分隔)将会是foreach函数的返回值。所以,<var>最好是一个变量名,<list>可以是一个表达式,而<text>中一般会使用<var>这个参数来依次枚举<list>中的单词。

示例:

names := a b c d
files := $(foreach n,$(names),$(n).o)
#最后$(files)为a.o b.o c.o d.o

 

28 if函数

$(if <condition>,<then-part> ) 或 $(if <condition>,<then-part>,<else-part> )

说明:<condition>参数是if的表达式,如果其返回的为非空字符串,那么这个表达式就相当于返回真,于是,<then-part>会被计算,否则<else-part>会被计算。返回值会是整个<then-part>或<else-part>

 

29 call函数

call函数是唯一一个可以用来创建新的参数化的函数。语法:

$(call <expression>,<parm1>,<parm2>,<parm3>...)

说明:当make执行这个函数时,<expression>参数中的变量,如$(1),$(2),$(3)等,会被参数<parm1>,<parm2>,<parm3>依次取代。而<expression>的返回值就是call函数的返回值。

示例:

reverse = $(1) $(2)
foo = $(call reverse,a,b)

 

30 origin函数

$(origin <variable> )

说明:返回<variable>变量的来源。返回值有如下几个:

  • undefined:<variable>变量从来没定义过。
  • default:默认变量,如CC
  • environment:<variable>是一个环境变量
  • file:<variable>这个变量被定义在Makefile中
  • command line:<variable>这个变量是被命令行定义的
  • override:如果<variable>是被override指示符重新定义的。
  • automatic:<variable>是一个命令运行中的自动化变量

示例:

origin函数示例
ifdef bletch
ifeq "$(origin bletch)" "environment"
bletch = barf, gag, etc.
endif
endif

 

31 shell函数

顾名思义,它的参数应该就是操作系统Shell的命令。shell函数把执行操作系统命令后的输出作为函数返回。

示例:contents := $(shell cat foo)

 

32 警告/错误函数

$(error <text ...> )

$(warning <text ...> )

 

33 make的运行

33.1 make的退出码

make命令执行后有三个退出码:

0 —— 表示成功执行。
1 —— 如果make运行时出现任何错误,其返回1。
2 —— 如果你使用了make的“-q”选项,并且make使得一些目标不需要更新,那么返回2。

33.2 指定make执行的makefile文件

使用make命令的-f选项

33.3 指定目标

make命令行后跟目标名,可以指定执行的目标,如:make clean。在命令行中指定的目标会保存到变量MAKECMDGOALS中。

GNU定义了一些约定的伪目标名:

“all”:这个伪目标是所有目标的目标,其功能一般是编译所有的目标。

“clean”:这个伪目标功能是删除所有被make创建的文件。

“install”:这个伪目标功能是安装已编译好的程序,其实就是把目标执行文件拷贝到指定的目标中去。

“print”:这个伪目标的功能是例出改变过的源文件。

“tar”:这个伪目标功能是把源程序打包备份。也就是一个tar文件。

“dist”:这个伪目标功能是创建一个压缩文件,一般是把tar文件压成Z文件。或是gz文件。

“TAGS”:这个伪目标功能是更新所有的目标,以备完整地重编译使用。

“check”和“test”:这两个伪目标一般用来测试makefile的流程。

 

34 隐含规则

隐含规则指的是makefile会根据目标的后缀推导出该目标依赖及生成命令。

隐含规则中会用到一些默认的变量:

AR
函数库打包程序。默认命令是“ar”。
AS
汇编语言编译程序。默认命令是“as”。
CC
C语言编译程序。默认命令是“cc”。
CXX
C++语言编译程序。默认命令是“g++”。
CO
从 RCS文件中扩展文件程序。默认命令是“co”。
CPP
C程序的预处理器(输出是标准输出设备)。默认命令是“$(CC) –E”。
FC
Fortran 和 Ratfor 的编译器和预处理程序。默认命令是“f77”。
GET
从SCCS文件中扩展文件的程序。默认命令是“get”。
LEX
Lex方法分析器程序(针对于C或Ratfor)。默认命令是“lex”。
PC
Pascal语言编译程序。默认命令是“pc”。
YACC
Yacc文法分析器(针对于C程序)。默认命令是“yacc”。
YACCR

Yacc文法分析器(针对于Ratfor程序)。默认命令是“yacc –r”。
MAKEINFO
转换Texinfo源文件(.texi)到Info文件程序。默认命令是“makeinfo”。
TEX
从TeX源文件创建TeX DVI文件的程序。默认命令是“tex”。
TEXI2DVI
从Texinfo源文件创建军TeX DVI 文件的程序。默认命令是“texi2dvi”。
WEAVE
转换Web到TeX的程序。默认命令是“weave”。
CWEAVE
转换C Web 到 TeX的程序。默认命令是“cweave”。
TANGLE
转换Web到Pascal语言的程序。默认命令是“tangle”。
CTANGLE
转换C Web 到 C。默认命令是“ctangle”。
RM
删除文件命令。默认命令是“rm –f”。

ARFLAGS
函数库打包程序AR命令的参数。默认值是“rv”。
ASFLAGS
汇编语言编译器参数。(当明显地调用“.s”或“.S”文件时)。
CFLAGS
C语言编译器参数。
CXXFLAGS
C++语言编译器参数。
COFLAGS
RCS命令参数。
CPPFLAGS
C预处理器参数。( C 和 Fortran 编译器也会用到)。

FFLAGS
Fortran语言编译器参数。
GFLAGS
SCCS “get”程序参数。
LDFLAGS
链接器参数。(如:“ld”)
LFLAGS
Lex文法分析器参数。
PFLAGS

Pascal语言编译器参数。
RFLAGS
Ratfor 程序的Fortran 编译器参数。
YFLAGS
Yacc文法分析器参数。

35 模式规则

模式规则用于定义隐含规则。一个模式规则就好像一个一般的规则,只是在规则中,目标的定义需要有"%"字符。"%"的意思是表示一个或多个任意字符。在依赖目标中同样可以使用"%",只是依赖目标中的"%"的取值,取决于其目标。

有一点需要注意的是,"%"的展开发生在变量和函数的展开之后,变量和函数的展开发生在make载入Makefile时,而模式规则中的"%"则发生在运行时。

当一个模式匹配包含有斜杠(实际也不经常包含)的文件时,那么在进行模式匹配时,目录部分会首先被移开,然后进行匹配,成功后,再把目录加回去。在进行"茎"的传递时,我们需要知道这个步骤。例如有一个模式"e%t",文件"src/eat"匹配于该模式,于是"src/a"就是其"茎",如果这个模式定义在依赖目标中,而被依赖于这个模式的目标中又有个模式"c%r",那么,目标就是"src/car"。("茎"被传递)

36 自动化变量

$@:表示规则中的目标文件集。在模式规则中,如果有多个目标,那么,"$@"就是匹配于目标中模式定义的集合。

$%:仅当目标是函数库文件中,表示规则中的目标成员名。例如,如果一个目标是"foo.a(bar.o)",那么,"$%"就是"bar.o","$@"就是"foo.a"。如果目标不是函数库文件(Unix下是[.a],Windows下是.lib]),那么,其值为空。

$<:依赖目标中的第一个目标名字。如果依赖目标是以模式(即"%")定义的,那么"$<"将是符合模式的一系列的文件集。注意,其是一个一个取出来的。

$?:所有比目标新的依赖目标的集合。以空格分隔。

$^:所有的依赖目标的集合。以空格分隔。如果在依赖目标中有多个重复的,那个这个变量会去除重复的依赖目标,只保留一份。

$+:这个变量很像"$^",也是所有依赖目标的集合。只是它不去除重复的依赖目标。

$*:这个变量表示目标模式中"%"及'/'之前的部分,即'%'不能跨越'/'匹配。如果目标是"dir/a.foo.b",并且目标的模式是"a.%.b",那么,"$*"的值就是"dir/foo"。这个变量对于构造有关联的文件名是比较有用。如果目标中没有模式的定义,那么"$*"也就不能被推导出,但是,如果目标文件的后缀是make 所识别的,那么"$*"就是除了后缀的那一部分。例如:如果目标是"foo.c",因为".c"是make所能识别的后缀名,所以,"$*"的值就是"foo"。这个特性是GNU make的,很有可能不兼容于其它版本的make,所以,你应该尽量避免使用"$*",除非是在隐含规则或是静态模式中。如果目标中的后缀是make所不能识别的,那么"$*"就是空值。

37 使用make更新函数库文件

可以以如下格式指定函数库文件及其组成:archive(member)。一般来说,这种用法基本上就是为了"ar"命令来服务的。如:

foolib(hack.o kludge.o):hack.o kludge.o
ar cr foolib hack.o  kludge.o

 

 

 

 

posted on 2012-12-09 14:05  TimLeung  阅读(494)  评论(0编辑  收藏  举报

导航