1.Makefile通过export传递变量
在上一节中,我们通过命令行的形式给一个Makefile传递变量,除此之外,我们还可以通过export命令给Makefile传递变量:
.PHONY:all
all: @echo "WEB = $(WEB)"
在上面的Makefile中,在命令行中打印变量WEB的值,但WEB在Makefile中并没有定义,但我们可以通过export传递给它:
wit@pc:/home/makefile/demo# makeWEB =wit@pc:/home/makefile/demo# export WEB=zixue.comwit@pc:/home/makefile/demo# makeWEB = zixue.com
在shell环境下使用export命令,就相当于将WEB变量声明为系统环境变量。当make解析Makefile时,会自动引入系统环境变量,包括刚刚声明的WEB,所以我们就可以在Makefile中看到WEB变量的打印值了。
2.Makefile递归执行
在实际工程项目中,各个源文件通常存放在各个不同的目录中,make在编译工程项目时,会依次遍历各个不同的子目录,编译每个子目录下的源文件,这是如何做到的呢?很简单,使用下面的命令就可以了:
# make -C subdir1 subdir2 subdir3 ...
make会依次到subdir1、subdir2、subdir3子目录下去执行make程序。上面的make 命令就等价于:
# cd subdir1 && $(MAKE)# cd subdir2 && $(MAKE)# cd subdir3 && $(MAKE)
当然,在subdir1、subdir2、subdir3子目录下,也得有对应的Makefile文件,否则make就会运行报错。为了给大家演示下make是如何遍历各个子目录的,我们新建一个工程如下:
wit@pc:/home/makefile/demo# tree.├── makefile├── subdir1│ └── makefile├── subdir2│ └── makefile└── subdir3 └── makefile3 directories, 4 files
这个项目有3个子目录,每个子目录下分别有对应的源文件和Makefile,为了简化,我们只添加了Makefile文件,每个Makefile文件的内容如下:
#subdir1/makefile:all: echo "make in subdir1"#subdir2/makefile:all: echo "make in subdir2"#subdir3/makefile:all: echo "make in subdir3"
项目底层目录的Makefile文件内容如下:
.PHONY:allall: @echo "make start" make -C subdir1 make -C subdir2 make -C subdir3 @echo "make done"
在项目根目录下执行make命令,可以看到make的顺序如下:
wit@pc:/home/makefile/demo# makemake startmake -C subdir1make[1]: Entering directory '/home/makefile/demo/subdir1'echo "make in subdir1"make in subdir1make[1]: Leaving directory '/home/makefile/demo/subdir1'make -C subdir2make[1]: Entering directory '/home/makefile/demo/subdir2'echo "make in subdir2"make in subdir2make[1]: Leaving directory '/home/makefile/demo/subdir2'make -C subdir3make[1]: Entering directory '/home/makefile/demo/subdir3'echo "make in subdir3"make in subdir3make[1]: Leaving directory '/home/makefile/demo/subdir3'make done
通过打印信息我们看到,make通过 -C subdir参数,会分别到各个子目录下去执行,解析各个子目录下的Makefile并运行,遍历完所有的子目录,make最后才会退出。
3.Makefile递归传递变量
当make依次遍历到各个子目录下解析新的 Makefile 时,项目顶层目录的主 Makefile 定义的一些变量,是如何传递到子目录的 Makefile 文件中的呢?我们还是以上面的 Makefile 为例,在项目顶层目录的 Makefile 中,定义了一个变量:WEB=zixue.com
.PHONY:allWEB =zixue.comall: @echo "make start" @echo "WEB = $(WEB)" make -C subdir1 make -C subdir2 make -C subdir3 @echo "make done"
然后在各个子目录的 Makefile 下面分别打印这个WEB变量的值:
#subdir1/makefile:all: @echo "make in subdir1" @echo "sundir1:WEB = $(WEB)"
在工程项目的顶层目录执行make命令,可以看到WEB变量在各个子目录下的打印值:
wit@pc:/home/makefile/demo# makemake startWEB = zixue.comcmake -C subdir1make[1]: Entering directory '/home/makefile/demo/subdir1'make in subdir1sundir1:WEB =make[1]: Leaving directory '/home/makefile/demo/subdir1'make -C subdir2make[1]: Entering directory '/home/makefile/demo/subdir2'make in subdir2sundir2: WEB =make[1]: Leaving directory '/home/makefile/demo/subdir2'make -C subdir3make[1]: Entering directory '/home/makefile/demo/subdir3'make in subdir3sundir3: WEB =make[1]: Leaving directory '/home/makefile/demo/subdir3'make done
通过打印值我们可以看到:除了在顶层目录中WEB的变量是zixue.com,在其他三个子目录中WEB变量的值都是为空,这说明底层目录 Makefile 中的变量并没有传递到各个子目录中。
修改顶层目录的主 Makefile ,讲变量WEB使用export声明为环境变量:
.PHONY:allexport WEB = zixue.comcall: @echo "make start" @echo "WEB = $(WEB)" make -C subdir1 make -C subdir2 make -C subdir3 @echo "make done"
再次运行make命令,通过各个子目录下的打印值可以看到:在主 Makefile 通过export声明的变量WEB已经正确地传递到各个子目录的 Makefile 中。
wit@pc:/home/makefile/demo# makemake startWEB = zixue.commake -C subdir1make[1]: Entering directory '/home/makefile/demo/subdir1'make in subdir1sundir1:WEB = zixue.commake[1]: Leaving directory '/home/makefile/demo/subdir1'make -C subdir2make[1]: Entering directory '/home/makefile/demo/subdir2'make in subdir2sundir2: WEB = zixue.commake[1]: Leaving directory '/home/makefile/demo/subdir2'make -C subdir3make[1]: Entering directory '/home/makefile/demo/subdir3'make in subdir3sundir3: WEB = zixue.commake[1]: Leaving directory '/home/makefile/demo/subdir3'make done