第七篇 变量的高级主题(下)
环境变量在任何系统同都会存在,它就是系统中预定义的一些键值对,在makefile中可以直接使用系统环境变量的值,但是makefile中若定义了同名的全局变量,那么环境变量将被覆盖,运行make时若指定-e选项,则优先使用环境变量。在makefile中使用环境变量有以下优劣:
如果在多个makefile文件中要共享同一个变量,使用环境变量可以很方便的完成这项任务,但是过多的使用环境变量会使移植性降低。
变量可以在不同的makefile之间传递,其传递方式有以下几种:
其中在外部定义环境变量是不推荐的,因为这将依赖于系统,导致了makefile的移植性问题,特别是当使用了大量的环境变量时。
使用export定义的变量是一个临时的环境变量,这是在makefile文件内部定义的,所以不存在移植性问题。使用make调用其它的makefile时,可以在命令行定义变量并将其传递过去,这也是比较推荐的做法。
编写如下的makefile:
执行make,输出如下:
可见当前系统中的环境变量JAVA_HOME的值/home/delphi/program/java/jdk1.6.0_21,在makefile中我们将该环境变量的值改为了java_home,这个值将系统的值覆盖了,所以运行make时输出java_home。
再次修改makefile,内容如下:
这个makefile调用了makefile.2,makefile.2的内容如下:
执行make,输出结果如下:
因为make在解析makefile时,遇到JAVA_HOME=java_home,即临时的将系统环境变量改写为了java_home,因此,这个值也传递到了其它的makefile,在makefile.2执行时输出JAVA_HOME的值为java_home也就不足为奇了。
而var的作用域只在makefile中,它也不是系统变量,无法传递到makefile.2文件中,只在makefile文件中有效。因此,makefile.2中的var输出为空值。
那么,怎么样将var的值传递到makefile.2文件中呢?正如上面讲到的一样,我们可以使用export关键字修饰var变量,使它成为一个临时环境变量,这样就可以传递到makefile.2中了,修改后执行make的结果如下:
下面我们演示命令行传递变量的方式,修改makefile和makefile.2文件如下:
执行make后输出结果如下:
可见,在第一次解析makefile.2时没有传入命令行参数,这时new的值为空,第二次传入了new的值,在执行makefile.2时输出了TDelphi。
下面介绍makefile中的目标变量,其地位相当于C语言中的局部变量,其作用域由下图给出:
上图中test:var := test-var,即定义了目标变量var,此时这个变量的值test-var在test目标及其连带规则中有作用,而在其它地方,var变量的值仍然为D.T.Software,这个变量值得作用域为整个文件。
再次修改makefile文件如下:
执行make,输出结果如下:
再次修改makefile,并执行make,结果如下:
another目标对应的规则是test的连带规则,所以,在another中输出的var的值也是test-var,即目标变量的值。
将makefile再次修改,输出结果如下:
此时,another目标对应的规则不再是test的连带规则,所以,其var的值是这个makefile文件的全局变量var对应的值D.T.Software。
模式变量是目标变量的扩展,其具体解释如下:
模式的范围更宽,只要符合模式,这个变量的值就有效。
再次修改makefile,并执行make,结果如下:
test并不符合%e这个模式,因此,test中的new输出为TDelphi。
修改makefile如下:
执行make test rule,输出结果如下:
rule目标对应的规则符合%e模式,因此,rule规则中的new输出为test-new,即模式变量,而test规则中的new对应全局的var,作用域为该文件。
执行make test rule new:=cmd-new,结果如下:
模式变量中的new被override修饰了,不会被命令行的变量覆盖,而全局的new没有被override修饰,因此,被命令行的new变量的值覆盖了。