递归制造 - 朋友还是敌人?

时间:2008-11-26 04:47:05

标签: recursion makefile

我在我的项目中使用(GNU)Make。我目前正在为每个目录放置一个makefile,并使用SUBDIRS指定子目录。 有人向我建议,这不是使用make的理想方式,即使用一个顶级make文件(或几个,使用include拆分)。我过去曾尝试迁移/使用此布局,但在我看来,这是不必要的复杂。

使用递归makefile的好处/缺点是什么?

8 个答案:

答案 0 :(得分:22)

你应该记住的第一件事(只是为了消除任何误解)是我们不是在讨论单个和多个makefile。在任何情况下,将每个子目录中的makefile拆分为一个好主意。

递归makefile很糟糕主要是因为你将依赖树分割成了几棵树。这可以防止正确表达make实例之间的依赖关系。这也会导致(部分)依赖树的多次重新计算,这最终会导致性能问题(尽管通常不是很大)。

为了正确使用单一制作方法,您需要使用一些技巧,尤其是当您拥有大量代码库时:

首先,使用GNU make(你已经这样做了,我看到了)。 GNU make具有许多简化功能的功能,您不必担心兼容性。

其次,使用特定于目标的变量值。例如,这将允许您为不同的目标设置不同的CFLAGS值,而不是强迫您在整个make中使用单个CFLAGS:

 main: CFLAGS=-O2
 lib: CFLAGS=-O2 -g

第三,确保在GNU make支持的完整范围内使用VPATH / vpath。

您还希望确保没有多个具有相同名称的源文件。 VPATH的一个限制是,它不允许你有具体的目标VPATH的定义,所以你的源文件的名称必须共存于一个单一的“VPATH命名空间”。

答案 1 :(得分:18)

可在此处找到一篇名为“Recursive Make Considered Harmful”的文章:http://miller.emu.id.au/pmiller/books/rmch/?ref=DDiyet.Com。 (或者在SourceForge的Aegis项目。)

它探讨了递归makefile的问题,并推荐了单一的makefile方法。

答案 2 :(得分:6)

我广泛使用递归。每个叶子节点都有自己的makefile,请考虑:

$LIBS = libfoo libbar
$(LIBS):
    cd $@ && $(MAKE)

在大型系统上,没有这种结构将是一个很大的挑战。人们谈论“递归使被认为有害”是一个准确的评估。我认为每种情况都有所不同,我们会做出一些妥协。

答案 3 :(得分:4)

运行,不要走路,到cmake.org并获得Cmake,这是最好的构建工具之一。

你仍然会使用GNU make,但在这种情况下,CMake会为你生成makefile。

我无法保证100%,但我还没有遇到过这样一种情况:它没有正确处理子目录之间的依赖关系(即困扰递归make的问题)。至少维护Cmakefiles要比makefile容易得多。强烈推荐。

不要使用GNU autotools - 这就是疯狂的谎言!

答案 4 :(得分:1)

Makepp是你的朋友。

http://makepp.sourceforge.net/

  • 向后兼容make
  • 自动扫描标头依赖关系
  • 目录树的优雅处理

答案 5 :(得分:0)

我过去从中获得的好处是,在单个子目录中构建文件更容易。你可以用依赖关系做到这一点,但要保持所有目标的直接性还有一些工作要做。基本上,这使得更容易进行更改和测试一个库,而无需处理大型项目的完整复杂性。

答案 6 :(得分:0)

要使用第三个选项,您可以使用GNU Autotools。 主要用于其他原因,但也可能有助于组织多目录构建。

http://www.lrde.epita.fr/~adl/autotools.html

但必须注意,结果是递归版本。

答案 7 :(得分:-1)

递归make的问题是评估所有不同的make文件与评估一个大型make文件的时间开销。部分原因只是产生过程,而且(IIRC)您倾向于假设其他人使文件做了某些事情并在您不需要时重建。

我对它的看法是每个“单元”有一个make文件,或多或少相当于你希望它可以在它自己使用的每个代码块上都有一个make文件(例如作为一个独立的库)

OTOH我当前的项目在整个地方打破了这个,因为我在构建期间生成make文件。是b