子makefile并向上传递变量

And*_*rew 6 makefile gnu-make

我有一个项目涉及子目录与子makefile.我知道我可以使用export命令通过环境将变量从父makefile传递到子makefile.有没有办法将变量从子makefile传递给它的调用makefile?即可以反过来出口工作?我试过这个没有成功.我猜测一旦子make完成它的shell就会被破坏,同时它的环境变量也会被破坏.还有另一种向上传递变量的标准方法吗?

Bri*_*erg 2

您的问题的简短答案是:不,您不能[直接]执行您想要的递归构建操作(请参阅下面的非递归构建)。

Make 像任何其他命令一样将子 make 进程作为配方行执行。它的 stdout/stderr 像任何其他进程一样打印到终端。一般来说,子进程不能影响父进程的环境(显然我们不是在这里讨论环境,但同样的原则适用)——除非你故意在父进程中构建类似的东西,但你会使用IPC 机制来实现这一目标。

我可以想象多种方法来实现这一目标,所有这些听起来都是一件可怕的事情。例如,您可以写入一个文件并使用以下include指令(注意:未经测试)获取它eval

some_target:
  ${MAKE} ${MFLAGS} -f /path/to/makefile

some_other_target : some_target
  $(eval include /path/to/new/file)
Run Code Online (Sandbox Code Playgroud)

...尽管它必须位于上面所写的单独目标中,因为所有内容$(macro statements)都会在配方开始执行之前进行评估,即使宏位于配方的后面一行。

gmake v4.x 有一个新功能,允许您直接从 makefile 指令写入文件。文档中的示例:

如果该命令要求每个参数位于输入文件的单独行上,您可以像这样编写您的配方:

program: $(OBJECTS)
        $(file >$@.in) $(foreach O,$^,$(file >>$@.in,$O))
        $(CMD) $(CMDFLAGS) @$@.in
        @rm $@.in
Run Code Online (Sandbox Code Playgroud)

(gnu.org)

...但是您仍然需要$(eval include ...)在单独的配方中使用宏来使用文件内容。

我对$(eval include ...)在食谱中使用非常谨慎;在并行构建中,包含的文件可能会影响 make 变量,并且包含发生的时间对于并行构建的其他目标而言可能是不确定的。

找到更自然的解决方案来解决您的问题会更好。首先我会退一步问自己“我想解决什么问题,其他人是如何解决这个问题的?” 如果你没有找到有人试图解决这个问题,很可能是因为他们没有走你正在走的路。


编辑可以对非递归构建执行您想要的操作。例如:

# makefile1
include makefile2

my_tool: ${OBJS}


# makefile2
OBJS := some.o list.o of.o objects.o
Run Code Online (Sandbox Code Playgroud)

...尽管我警告你对此要非常小心。我维护的构建非常大(大约 250 个 makefile)。每个级别都包含如下声明:

include ${SOME_DIRECTORY}/*/makefile
Run Code Online (Sandbox Code Playgroud)

这里的危险是你不希望人们在一棵树上依赖于另一棵树的变量。在短期内,有一些地方我必须做一些类似于您想要的事情:子 makefile 附加到变量,然后该变量在父 makefile 中使用。从长远来看,这种情况将会消失,因为它很脆弱/不安全,但目前我不得不使用它。

我建议您阅读论文《Recursive Make Been Harmful》(如果该链接不起作用,只需谷歌搜索该论文的名称)。

  • 你在很多点上都是对的。我想这个问题不会出现,因为我一开始就走错了路。我决定在子 makefile 中创建目标文件的存档,并在顶级 makefile 中链接到它。这样,顺序和依赖关系就得以保留。 (3认同)