【问题标题】:ant+cpptasks vs. scons vs. makeant+cpptasks vs. scons vs. make
【发布时间】:2010-11-05 06:28:32
【问题描述】:
我正在研究scons,我只是想确保我知道替代方案是什么,然后再将一大块脑细胞投入到完全不同的东西中。我过去一直在使用 GNU make,但从未对它特别满意。
特别是:为什么在 C/C++ 项目中不经常使用 Ant? (鉴于有ant cpptasks)我读过一些帖子说Ant 更面向Java(显然),但是这样做有什么缺点?为什么 scons 比 make 好那么多?
我正在使用 TI DSP 的交叉编译器,通常一个项目中有 20-50 个 cpp 文件。看起来构建管理中最难的部分是自动依赖检查。其他一切只是将文件列表与编译器选项集映射在一起。
edit: 为什么交叉编译会改变什么?它是一个编译器,运行方式与 gcc 相同,只是它生成的目标文件/可执行文件无法在我的 PC 上运行。
【问题讨论】:
标签:
ant
build-process
makefile
scons
【解决方案1】:
对于交叉编译,我认为您的最佳选择是CMake 或Autotools。特别是如果您可以为多个架构/平台编译代码。我通常在本机机器上编译我的代码子集以进行单元测试,并将所有代码都用于目标平台。 CMake 处理得特别好,因为它允许您指定交叉编译库的位置。因此,与其在 /usr/lib 中搜索交叉编译的 libpng,不如在 /opt/arm-eabi-gcc/ 或构建机器上安装了工具链库的任何地方进行查找。您可以为不同的变体创建多个构建目录,并使用 make 手动编译每个变体,或者使用脑残的手动递归 make 来触发该批次。
Ant 的缺点是它基本上与 vanilla Make 一样好或一样坏,另外一个缺点是您使用的东西对于 C 或 C++ 来说不是特别主流。您必须处理所有自己的依赖项——包括内部依赖项,例如 C 文件到头文件到库或可执行文件,以及外部依赖项,例如必须与 3rd 方库链接。另外,我认为 Ant C 任务并没有真正维护那么多。我见过的所有使用 Ant for C 的人都提倡使用 exec 任务调用 GCC。
SCons 更好,但交叉编译不是它的强项。它也不是像 CMake 或 Autotools 这样的“构建系统”,它只是一个构建工具。正如他们的 wiki 上所说,it is pretty much "Make in Python"。不过,它确实内置了对依赖项的处理,这意味着您不必在其中使用“gcc -MM -MD”或其他任何东西来滚动自己,因此这比 Make 更有优势。 SCons 还支持检测已安装的 3rd 方库,但通常执行的方式会大大增加您的构建时间。与其他系统不同,SCons 每次运行时都会运行检查阶段,尽管大多数结果都会被缓存。 SCons 也因其较长的构建时间而臭名昭著,尽管对于 50 个文件来说这不是问题。 SCons 中的交叉编译支持不存在 - 你必须推出自己的 as discussed on this thread on the mailing list。通常,您强制构建类似于 Unix 平台,然后覆盖 C 编译器的名称。构建多个变体或将构建目录与源目录分开充满了陷阱,这使得它不太适合交叉和本地编译代码。
CMake 和 Autotools 的依赖问题解决得很好,autotools 的交叉编译支持也很成熟。 CMake 自 2008 年 4 月发布的 2.6.0 版以来就进行了交叉编译。您可以免费获得这些功能,以及打包和运行单元测试(“make check”或类似目标)等其他功能。这两种工具的缺点是它们需要引导。对于 CMake,您需要安装 CMake 二进制文件以创建 Makefile 或 Visual Studio 解决方案文件。在 Autotools 的情况下,它稍微复杂一些,因为不是每个编译软件的人都需要安装 automake 和 autoconf,只有那些需要更改构建系统的人(添加新文件被视为更改构建系统)。 2 阶段引导(configure.ac -> configure、configure + Makefile.in -> Makefile)在概念上有点难以理解。
对于编辑:交叉编译在构建系统中是一个额外的麻烦,因为它增加了程序和库的自动检测的复杂性。 SCons 不处理这个问题,它留给你来解决。 Ant 同样什么也不做。 Autoconf 在 autotools 的情况下会处理这个问题,但是当您在链接阶段尝试使用 /usr/lib 时,您可能必须在配置时在命令行上提供“--with-libfoobar=/some/path”,否则会遇到断开的链接. CMake 的方法是使用工具链文件更重一些,但这意味着您不必指定所有工具和库(CC、CXX、RANLIB、--with-ibfoo= 等),因为它们是从一个标准的约定。理论上,您可以在多个项目中重用适当制作的 CMake 工具链文件来交叉编译它们。在实践中,CMake 的普及程度不足以让普通黑客方便使用,但如果您正在创建多个专有项目,它可能会很有用。
【解决方案2】:
几年前我大量使用 Ant+CppTasks 构建非常大的代码库并通过 JNI 集成到新的 Java 代码中,并且对非常可靠的 C++ 代码增量构建的结果非常满意,良好的灵活性(在构建文件,或通过调整代码)。但是,CppTasks 是一个没有社区的项目,维护者(Curt Arnold)很长一段时间都没有对它做任何事情。它仍然非常好和有用,但请注意,很少有人知道或使用 CppTasks(例如,当我需要 C 文件的特定编译器时,编译器“投标”文件的方式会咬我一口,而不同的 C++ 编译器正在挑选这些文件)而是)。
CppTasks 跟踪编译选项并动态扫描源头文件依赖项的方式,始终足够快(有一些依赖项缓存),这意味着我使用过的唯一一个具有准确增量构建的系统,一些在构建非常大的代码库时非常重要。
所以正如我在 Ant 用户/开发者列表中所说的,如果你有很多 Java 的东西并且已经在 Ant 上进行了投资,并且不怕潜入doc 和 CppTasks的代码,现在需要构建JNI“glue”代码,和/或glue代码公开的“legacy”本机库,它是一个有价值的竞争者,奖励可以是很棒。
我很容易为 Windows dll 集成 以添加完整的版本信息,例如,编写一个小 Ant 任务来正确格式化 .res 文件。它对我有用,但 Ant+CppTasks 绝对更适合“高级”Ant 用户/开发人员恕我直言。
我希望这会有所帮助。 --DD
【解决方案3】:
我想推荐 terp 从 ANT 构建 C++ 项目。我们开发 terp 是因为 ANT 是我们选择的构建工具,而 CppTasks 有点长,而且我们想在不同的抽象级别上工作。 terp 支持很多不同的编译器,它由我们公司提供支持。但对于大多数项目来说,它不是免费的。
我们设计的 terp 主要用于完全重建,而不是用于依赖分析的增量构建。我们正在到达那里,但它还没有到达那里。 terp 的最佳选择是在多平台、多procarch、多编译器版本中,您不想为所有组合维护n 个不同的配置。目前(2009 年 7 月)它处于公开测试阶段,但很快就会发布。
【解决方案4】:
在过去的五年里,我一直在从事一个使用 ant 进行 x86 和 arm 构建的项目。为了我们的目的,我们调整了 cpptasks 以生成一个通用编译器,我们只需将前缀传递给......例如 arm-gum-linux-gnueabi- 然后将其添加到实际工具(例如 g++ 或 ar 或其他)之前。没有前缀意味着您获得了开发平台构建工具。用于交叉编译的工具链在其构建工具二进制文件中具有这些前缀。使用 Ant 而不是任何基于 make 的东西的几乎全部原因是 cpptasks 能够进行非必要的构建,以及为了让 autoconf 满意而必须发生的大量事情。我们能够支持几乎任何源文件,尤其是库集的文件夹树结构中的源文件的范例,可以创建/重命名/删除,并且不需要对构建文件进行编辑。一个小缺点是链接文件会以一种会导致不必要的重建的方式更新属性。
<target name="lib.cvp">
<fetch.and.log.version
svnvers.target="common/cvp"
svnvers.property="libcvp.version"/>
<cc objdir="${obj.dir}/common/cvp"
commandPrefix="${command.prefix}"
compilerName="${compiler.name}"
outfile="${lib.dir}/cvp" outtype="static">
<compiler extends="base.compiler"/>
<compilerarg
value="-D__CVP_LIB_BUILD_VERSION__="${libcvp.version}""/>
<compilerarg
value="-D__BUILD_NOTES__="${libcvp.toolversion}""/>
<compilerarg if="is.x86" value="-DARCH_X86"/>
<linker extends="base.linker"/>
<includepath refid="common.inc"/>
<fileset dir="${project.home}/common/cvp">
<include name="*.c"/>
<include name="*.cpp"/>
</fileset>
</cc>
</target>
【解决方案5】:
Ant 拥有大量 Java 用户群(出于自然原因)。 Ant 在更广泛的环境中非常有用的事实是大多数非 Java 开发人员不知道的。因此,如果您使用 Ant 来构建您的 C/C++ 代码,那么如果您使用具有更大用户群(CMake 或 SCons)的系统,那么您自己构建的代码要多得多。
我个人对 CMake 非常满意,主要是因为它是唯一可以生成真正的 Visual Studio 项目的构建系统。 SCons 也可以,但它们只对 SCons 进行外部调用,而 CMake 生成使用 Visual Studio 自己的构建引擎的项目。如果您与习惯于 Visual Studio 的人一起工作,这将非常有用。
我不确定我是否会将 CMake 对交叉编译的支持称为“成熟”,因为它还很年轻。但是 CMake 的人对此很认真,所以我会毫不犹豫地尝试一下。