##4. 变量中的变量
变量中的变量
先看第一种方式,也就是简单的使用“=”号,在“=”左側是变量,右側是变量的值,右側变量的值能够定义在文件的不论什么一处,也就是说,右側中的变量不一定非要是已定义好的值,其也能够使用后面定义的值。如:
##5. 条件表达式
条件表达式的语法为:
endif
假设变量的值非空,那到表达式为真。否则,表达式为假。当然,相同能够是一个函数的返回值。注意,ifdef仅仅是测试一个变量是否有值,其并不会把变量扩展到当前位置。还是来看两个样例:
在这一行上,多余的空格是被同意的,可是不能以[Tab]键做为开始(不然就被觉得是命令)。而凝视符“#”相同也是安全的。“else”和“endif”也一样,仅仅要不是以[Tab]键开始就可以了。
特别注意的是,make是在读取Makefile时就计算条件表达式的值,并依据条件表达式的值来选择语句,所以,你最好不要把自己主动化变量(如“$@”等)放入条件表达式中,由于自己主动化变量是在运行时才有的。
假设变量之前未定义过,那么,“+=”会自己主动变成“=”,假设前面有变量定义,那么“+=”会继承于前次操作的赋值符。假设前一次的是“:=”,那么“+=”会以“:=”作为其赋值符,如:
由于前次的赋值符是“=”,所以“+=”也会以“=”来做为赋值,那么岂不会发生变量的递补归定义,这是非常不好的,所以make会自己主动为我们解决问题,我们不必操心这个问题。
在一些大的工程中,有大量的源文件,我们通常的做法是把这很多的源文件分类,并存放在不同的文件夹中。所以,当make须要去找寻文件的依赖关系时,你能够在文件前加上路径,但最好的方法是把一个路径告诉make,让make在自己主动去找。
Makefile文件里的特殊变量“VPATH”就是完成这个功能的,假设沒有指明这个变量,make仅仅会在当前的文件夹中去找寻依赖文件和目标文件。假设定义了这个变量,那么,make就会在当当前文件夹找不到的情况下,到所指定的文件夹中去找寻文件了。
VPATH = src:…/headers
上面的的定义指定两个文件夹,“src”和“…/headers”,make会依照这个顺序进行搜索。文件夹由“冒号”分隔。(当然,当前文件夹永远是最高优先搜索的地方)
另一个设置文件搜索路径的方法是使用make的“vpath”keyword(注意,它是全小写的),这不是变量,这是一个make的keyword,这和上面提到的那个VPATH变量非常相似,可是它更为灵活。它能够指定不同的文件在不同的搜索文件夹中。这是一个非常灵活的功能。它的使用方法有三种:
1、vpath
为符合模式的文件指定搜索文件夹。
2、vpath
清除符合模式的文件的搜索文件夹。
3、vpath
清除全部已被设置好了的文件搜索文件夹。
vapth使用方法中的须要包括“%”字符。“%”的意思是匹配零或若干字符,比如,“%.h”表示全部以“.h”结尾的文件。指定了要搜索的文件集,而则指定了的文件集的搜索的文件夹。比如:
vpath %.h …/headers
该语句表示,要求make在“…/headers”文件夹下搜索全部以“.h”结尾的文件。(假设某文件在当前文件夹沒有找到的话)
我们能够连续地使用vpath语句,以指定不同搜索策略。假设连续的vpath语句中出现了相同的,或是被反复了的,那么,make会依照vpath语句的先后顺序来运行搜索。如:
vpath %.c foo
vpath % blish
vpath %.c bar
其表示“.c”结尾的文件,先在“foo”文件夹,然后是“blish”,最后是“bar”文件夹。
vpath %.c foo:bar
vpath % blish
而上面的语句则表示“.c”结尾的文件,先在“foo”文件夹,然后是“bar”文件夹,最后才是“blish”文件夹。
###5.5 变量高级使用方法
这里介绍两种变量的高级使用方法,第一种是变量值的替换。
我们能够替换变量中的共同拥有的部分,其格式是“
(var:a=b)”或是“{var:a=b}”,其意思是,把变量“var”中全部以“a”字串“结尾”的“a”替换成“b”字串。这里的“结尾”意思是“空格”或是“结束符”。
还是看一个演示例子吧:
foo := a.o b.o c.o
bar := $(foo:.o=.c)
这个演示例子中,我们先定义了一个“
(foo)”变量,而第二行的意思是把“(foo)”中全部以“.o”字串“结尾”全部替换成“.c”,所以我们的“$(bar)”的值就是“a.c b.c c.c”。
第二种变量替换的技术是以“静态模式”(參见前面章节)定义的,如:
foo := a.o b.o c.o
bar := $(foo:%.o=%.c)
这依赖于被替换字串中的有相同的模式,模式中必须包括一个“%”字符,这个样例相同让$(bar)变量的值为“a.c b.c c.c”。
第二种高级使用方法是——“把变量的值再当成变量”。先看一个样例:
x = y
y = z
a :=
(x)的值是“variable1”,subst函数把“variable1”中的全部“1”字串替换成“2”字串,于是,“variable1”变成“variable2”,再取其值,所以,终于,
(x)的值是“variable1”,subst函数把“variable1”中的全部“1”字串替换成“2”字串,于是,“variable1”变成“variable2”,再取其值,所以,终于,(a)的值就是$(variable2)的值——“Hello”。(喔,好不easy)
在这样的方式中,或要能够使用多个变量来组成一个变量的名字,然后再取其值:
first_second = Hello
a = first
b = second
all =
(a_$b)
这里的“KaTeX parse error: Expected group after '_' at position 2: a_̲b”组成了“first_second”,于是,$(all)的值就是“Hello”。
再来看看结合第一种技术的样例:
a_objects := a.o b.o c.o
1_objects := 1.o 2.o 3.o
sources :=
(a1)的值是“1”,那么(sources)的值是“1.c 2.c 3.c”。
再来看一个这样的技术和“函数”与“条件语句”一同使用的样例:
ifdef do_sort
func := sort
else
func := strip
endif
bar := a d b g q c
foo :=
(sortadbgqc),于是(foo)的值就是“a b c d g q”,而假设未定义“do_sort”,那么:foo := $(sort a d b g q c),调用的就是strip函数。
当然,“把变量的值再当成变量”这样的技术,相同能够用在操作符的左边:
dir = foo
$(dir)_sources := $(wildcard $(dir)/*.c)
define $(dir)_print
lpr
((dir)_sources)
endef
这个样例中定义了三个变量:“dir”,“foo_sources”和“foo_print”。
###5.6 makefile中的@
Makefile中的@通常,make会把其要执行的命令行在命令执行前输出到屏幕上。当我们用“@”字符在命令行前,那么,这个命令将不被make显示出来,最具代表性的例子是,我们用这个功能来像屏幕显示一些信息。如:
@echo 正在编译XXX模块......
当make执行时,会输出“正在编译XXX模块…”字串,但不会输出命令,如果没有“@”,那么,make将输出:
echo 正在编译XXX模块......
正在编译XXX模块......
###5.7 makefile中的-
每当命令运行完后,make会检测每一个命令的返回码,假设命令返回成功,那么make会运行下一条命令,当规则中全部的命令成功返回后,这个规则就算是成功完成了。假设一个规则中的某个命令出错了(命令退出码非零),那么make就会终止运行当前规则,这将有可能终止全部规则的运行。
有些时候,命令的出错并不表示就是错误的。比如mkdir命令,我们一定须要建立一个文件夹,假设文件夹不存在,那么mkdir就成功运行,万事大吉,假设文件夹存在,那么就出错了。我们之所以使用mkdir的意思就是一定要有这样的一个文件夹,于是我们就不希望mkdir出错而终止规则的运行。
为了做到这一点,忽略命令的出错,我们能够在Makefile的命令行前加一个减号“-”(在Tab键之后),标记为无论命令出不出错都觉得是成功的。
clean:
-rm -f *.o
###5.8 $<和 $@
$ < 表示依赖集, $@表示目标集
objects = foo.o bar.o
all: $(objects)
$(objects): %.o: %.c
$(CC) -c $(CFLAGS) $< -o $@
上面的样例中,指明了我们的目标从$object中获取,"%.o"表明要全部以".o"结尾的目标,也就是"foo.o bar.o”,也就是变量
object集合的模式,而依赖模式“%.c”则取模式“%.o”的“%”,也就是“foo bar”,并为其加下“.c”的后缀,于是,我们的依赖目标就是“foo.c bar.c”。而命令中的“
object集合的模式,而依赖模式“<”和“
@”则是自己主动化变量,“<”表示全部的依赖目标集(也就是“foo.c bar.c”),“$@”表示目标集(也就是“foo.o bar.o”)。于是,上面的规则展开后等效于以下的规则:
foo.o : foo.c
$(CC) -c $(CFLAGS) foo.c -o foo.o
bar.o : bar.c
$(CC) -c $(CFLAGS) bar.c -o bar.o
试想,假设我们的“%.o”有几百个,那种我们仅仅要用这样的非常easy的“静态模式规则”就能够写完一堆规则,实在是太有效率了。
makefile类似于windows下的Visual Studio等IDE。工程中由于源文件很多,可能存放于不同文件夹,因此makefile定义了一些规则,哪些文件先编译,哪些文件后编译等等其他复杂操作。makefile类似shell脚本,可以运行操作系统命令。当makefile写好后,只需要一个make命令,整个工程会自动编译,能极大提高开发效率。make是一个能解释makefile指令的命令...
system:centos
我们知道在vs中开发一个项目可以建立很多的文件包括各种头文件和.c 文件,编译的时候程序会自动编译链接。然而在linux下开发程序,当项目较大,文件又多时,我们需要将这些文件组织起来进行编译链接,这就需要用到make工具和makefile文件了;
make:
make是linux中的一个常用命令,在当前目录下,输入make,系统会自动在当前目录中寻找名为Makef
make/makefile是什么?
make是一条命令。makefile是一个文件,makefile包含了依赖关系和依赖方法。两个搭配使用,完成项目自动化构建,达到形成可执行程序的目的。
make/makefile使用详情
我们创建一个Makefile文件(makefile也行)
如何vim编辑makefile文件
依赖关系的另一种写法:$@代表目标文件、 $^代表源文件
注意:伪目标不需要依赖关系,只需要依赖方法
makefile自顶向下扫描命令,默认执行第一个命令,所有我们直接make,执行的就