18

能够预先编译依赖项的 C++ Buildsystem

Java 有 Maven,使用起来很愉快,只需指定已经编译的依赖项,并存放到 Maven标准目录,这意味着依赖项的位置是标准化的,而不是经常使用的具有多个位置的方式(给我一个break,就像任何人都记得 C/C++ 依赖项的特定 deps 的默认安装目录一样。

对于每个必须经常查找、阅读、熟悉配置选项/构建并最终为每个依赖项编译以简单地构建项目的个体开发人员来说,这是非常低效的。

没有实施的理论原因是什么?

为什么很难以类似 Maven 的声明格式提供以下选项的包?

version
platform (windows, linux)
src/dev/bin
shared/static
equivalent set of Boost ABI options when applicable

不得不手动访问网站并在 2013 年搜索最古老的主要编程语言的依赖项是荒谬的。

4

3 回答 3

21

没有任何理论上的原因。有很多实际原因。在 C++ 世界中有太多不同的处理方式来轻松标准化依赖系统:

  • 实现差异 - C++ 是一门复杂的语言,不同的实现在历史上对它的支持程度(它们正确处理各种中高级 C++ 代码的能力)存在差异。因此,不能保证可以在特定实现中构建库。
  • 平台差异 - 某些平台可能不支持异常。标准库有不同的实现,各有利弊。与 Java 的标准化库不同,Windows 和 POSIX API 可能完全不同。文件系统甚至不是标准 C++ 的一部分。
  • 编译差异 - 静态还是共享?调试还是生产构建?是否启用可选依赖项?与具有非常稳定的字节码的 Java 不同,C++ 缺乏标准 ABI 意味着代码可能无法正确链接,即使是由相同的编译器为相同的平台构建。
  • 构建系统差异 - Makefiles?(如果是这样,GNU Make,还是别的什么?) Autotools?制作?Visual Studio 项目文件?还有什么?
  • 历史问题 - 由于 C 和 C++ 的时代,像 zlib 这样的流行库比像 Maven 这样的构建系统早了很多。当 zlib 正在做的工作时,为什么要切换到一些假设的 C++ 构建系统?如果一个更新的、更高级别的库依赖于像 zlib 这样的库,它如何切换到某个假设的构建系统?

两个额外的因素使事情复杂化:

  • 在 Linux 中,发行版打包系统确实提供了开发库头二进制文件的标准化存储库,具有(通常)标准化的 ABI 和指定项目构建依赖项的简单方法。这些(特定于平台的)解决方案的存在降低了跨平台解决方案的动力。
  • 由于所有这些复杂因素和预先存在的方法,任何建立标准构建系统的尝试都将遇到 XKCD 的“标准”中描述的问题:
    情况:有 14 个竞争标准。
    “14?可笑!我们需要制定一个涵盖每个人用例的通用标准。”
    很快:有 15 个相互竞争的标准。

综上所述:

对未来有一些希望。例如,CMake 似乎正在逐渐取代其他构建系统。一些 Boost 开发人员已经开始Ryppl,尝试做你所描述的事情。

于 2013-01-10T17:32:22.563 回答
3

(也发布在链接的问题中)

现在,我正在开发一种工具,该工具能够自动安装具有确切版本要求的 C/C++ 应用程序的所有依赖项:

  • 编译器
  • 工具(cmake、autotools)

现在它适用于我的应用程序。(以正确的顺序安装 UnitTest++、Boost、Wt、sqlite、cmake)

该工具名为 «C++ 版本管理器»(灵感来自优秀的 ruby​​ 版本管理器)以 bash 编码并托管在 github 上:https ://github.com/Offirmo/cvm

欢迎任何意见和建议。

于 2013-01-10T17:44:53.400 回答
1

好吧,首先,解决所有依赖关系的系统默认情况下不会使您高效,它可能会使您的生产力更低。

关于语言之间的差异,我会说在 Java 中你有包,当你必须组织并为你的代码提供有限的视野时,这些包很方便,在 C++ 中你没有等效的概念。在 C++ 中,所有可以解决符号的库对于编译器来说都足够好,库的唯一真正要求是具有一定的 ABI 并解决所需的符号,没有自动化的方法可以让您选择正确的库,还解决了一个符号,这只是将您的函数链接到实际实现的问题,这甚至不授予您正确的链接阶段将使您的应用程序工作。

为此,您可以添加重要的变量,例如库版本、同一库的不同实现以及具有相同方法名称的不同库。

一个例子是 Mesa 库 VS 来自官方驱动程序的 opengl 库,或者您想要提供多个版本的任何库,每个库都可以解决所有符号,但可能有一个版本比其他版本更成熟,您可以询问编译器选择正确的一个,因为它们对于自己的目的都是一样的。

于 2013-01-10T17:34:02.617 回答