嵌套执行make

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

例如,我们有一个子目录叫subdir,这个目录下有个Makefile文件,来指明了这个目录下文件的编译规则。那么我们总控的Makefile可以这样书写:

  1. subsystem:
  2. cd subdir && $(MAKE)

其等价于:

  1. subsystem:
  2. $(MAKE) -C subdir

定义$(MAKE)宏变量的意思是,也许我们的make需要一些参数,所以定义成一个变量比较利于维护。这两个例子的意思都是先进入“subdir”目录,然后执行make命令。

我们把这个Makefile叫做“总控Makefile”,总控Makefile的变量可以传递到下级的Makefile中(如果你显示的声明),但是不会覆盖下层的Makefile中所定义的变量,除非指定了 -e 参数。

如果你要传递变量到下级Makefile中,那么你可以使用这样的声明:

  1. export <variable ...>;

如果你不想让某些变量传递到下级Makefile中,那么你可以这样声明:

  1. unexport <variable ...>;

如:

示例一:

  1. export variable = value

其等价于:

  1. variable = value
  2. export variable

其等价于:

  1. export variable := value

其等价于:

  1. variable := value
  2. export variable

示例二:

  1. export variable += value

其等价于:

  1. variable += value
  2. export variable

如果你要传递所有的变量,那么,只要一个export就行了。后面什么也不用跟,表示传递所有的变量。

需要注意的是,有两个变量,一个是 SHELL ,一个是 MAKEFLAGS ,这两个变量不管你是否export,其总是要传递到下层 Makefile中,特别是 MAKEFLAGS 变量,其中包含了make的参数信息,如果我们执行“总控Makefile”时有make参数或是在上层 Makefile中定义了这个变量,那么MAKEFLAGS 变量将会是这些参数,并会传递到下层Makefile中,这是一个系统级的环境变量。

但是make命令中的有几个参数并不往下传递,它们是 -C , -f , -h, -o-W (有关Makefile参数的细节将在后面说明),如果你不想往下层传递参数,那么,你可以这样来:

  1. subsystem:
  2. cd subdir && $(MAKE) MAKEFLAGS=

如果你定义了环境变量 MAKEFLAGS ,那么你得确信其中的选项是大家都会用到的,如果其中有-t , -n-q 参数,那么将会有让你意想不到的结果,或许会让你异常地恐慌。

还有一个在“嵌套执行”中比较有用的参数, -w 或是 —print-directory 会在make的过程中输出一些信息,让你看到目前的工作目录。比如,如果我们的下级make目录是“/home/hchen/gnu/make”,如果我们使用 make -w 来执行,那么当进入该目录时,我们会看到:

  1. make: Entering directory `/home/hchen/gnu/make'.

而在完成下层make后离开目录时,我们会看到:

  1. make: Leaving directory `/home/hchen/gnu/make'

当你使用 -C 参数来指定make下层Makefile时, -w 会被自动打开的。如果参数中有-s—slient )或是 —no-print-directory ,那么, -w 总是失效的。