6

我正在寻找建议以在递归makefile系统中正确处理单独的调试和发布构建子目录,该系统使用gnumake手册中记录的$(SUBDIRS)目标将make目标应用于(源代码)子目录。

具体来说,我对实现“all”、“clean”、“realclean”等目标的可能策略感兴趣,这些目标要么假设其中一棵树,要么应该在两棵树上工作,这会导致问题。

我们当前的 makefile 使用一个 COMPILETYPE 变量,该变量设置为 Debug(默认)或 Release('release' 目标),它可以正确地进行构建,但清理并使所有内容仅在默认的 Debug 树上工作。传递 COMPILETYPE 变量会变得笨拙,因为是否以及如何这样做取决于实际目标的值。

4

2 回答 2

0

一种选择是在每个构建类型的子目录中都有特定的目标。因此,如果您在顶层执行“make all”,它会查看 COMPILETYPE 并酌情调用“make all-debug”或“make all-release”。

或者,您可以在顶层设置一个 COMPILETYPE 环境变量,并让每个子 Makefile 处理它。

真正的解决方案是不进行递归生成,而是将生成文件包含在顶级文件的子目录中。这将使您可以轻松地在与源代码所在的目录不同的目录中构建,因此您可以拥有build_debugbuild_release目录。它还允许并行 make 工作(make -j)。有关完整说明,请参阅Recursive Make Considered Harmful

于 2009-02-13T13:30:05.497 回答
0

如果您在 Makefile 中对使用 $(COMPILETYPE) 变量在所有规则中引用适当的构建目录(从生成目标文件的规则到 clean/dist/etc 的规则)进行了规范,那么您应该没问题。

在我从事的一个项目中,我们有一个 $(BUILD) 变量被设置为(相当于)build-(COMPILETYPE),这使得规则更容易一些,因为所有规则都可以引用 $(BUILD),例如,clean 将 rm -rf $(BUILD)。

只要您使用 $(MAKE) 来调用子制作(并使用 GNU make),您就可以自动将 COMPILETYPE 变量导出到所有子制作,而无需执行任何特殊操作。有关详细信息,请参阅GNU make 手册的相关部分

其他一些选项:

  • 当编译器标志更改时强制重新构建,方法是在跟踪最后使用的编译器标志集的元文件上添加所有对象的依赖项。例如,参见Git 如何管理目标文件
  • 如果您使用的是 autoconf/automake,您可以轻松地为不同的构建类型使用单独的构建异地构建目录。例如,cd /scratch/build/$COMPILETYPE && $srcdir/configure --mode=$COMPILETYPE && make这会将构建类型从 Makefiles 中取出并放入配置中(您必须添加一些支持以根据您的值指定所需的构建--mode标志configure.ac

如果你给出一些更具体的例子来说明你的实际规则,也许你会得到一些更具体的建议。

于 2009-02-13T16:59:41.733 回答