【问题标题】:CMake: how best to build multiple (optional) subprojects?CMake:如何最好地构建多个(可选)子项目?
【发布时间】:2011-09-21 12:40:06
【问题描述】:

想象一个包含多个组件的整体项目:

  • 基本
  • io
  • 网络
  • app-a
  • app-b
  • app-c

现在,假设 web 依赖于依赖于 basic 的 io,所有这些东西都在一个 repo 中,并且有一个 CMakeLists.txt 来将它们构建为共享库。

如果这三个应用程序都是可选的并且在构建时可能不存在,我应该如何设置才能构建这三个应用程序?

一个想法是在主仓库中有一个空的“apps”目录,我们可以将我们想要的任何应用程序仓库克隆到其中。我们的主要 CMakeLists.txt 文件可以使用 GLOB 查找所有应用程序目录并构建它们(事先不知道会有多少)。这种方法的问题包括:

  • 显然,当您只说 make 时,CMake 不会重新 glob,因此如果您添加一个新应用程序,您必须再次运行 cmake
  • 它将特定结构强加给进行构建的人员。
  • 目前尚不清楚如何制作单个应用程序的两个克隆并针对同一个库构建分别构建它们。

一般概念类似于传统的递归 CMake 项目,但较低级别的模块不一定事先知道哪些较高级别的模块将使用它们。但是,我不想要求用户将低级库安装在固定位置(例如/usr/local/lib)。但是,我确实希望一次调用 make 以注意到整个项目中更改的依赖项,这样如果我正在构建一个应用程序但更改了其中一个低级库,那么一切都会正确地重新编译。

【问题讨论】:

  • 好问题。我正在寻找相同问题的解决方案。
  • 检查this solution。是否切中要害?
  • @Antonio:我不知道......我使用下面我的答案中解释的解决方案自己解决了这个问题。你的那个链接似乎有点相关,但可能与我原来的问题有点不同。不管怎样,它现在已经落后我很久了。 :)

标签: build cmake modularity


【解决方案1】:

我的第一个想法是使用 CMake 导入/导出目标 功能。

有一个用于basicioweb 的 CMakeLists.txt 和一个引用这些的 CMakeLists.txt。然后,您可以使用 CMake export 功能导出这些目标,然后应用程序项目可以import CMake 目标。

当您首先构建库项目时,应用程序项目应该能够自动找到已编译的库(无需将库安装到 /usr/local/lib)否则总是可以设置正确的 CMake 变量以指示正确的目录.

如果这样做,应用程序项目中的make 不会在库项目中执行make,您必须自己处理。

【讨论】:

【解决方案2】:

有多个 CMakeLists.txt。

许多开源项目都采用这种方法(LibOpenJPEG、LibPNG、poppler 等)。查看他们的 CMakeLists.txt 以了解他们是如何做到这一点的。

基本上允许您根据需要切换功能。

【讨论】:

  • “看看 X 不是答案。”
【解决方案3】:

我看到了另外两种方法。一种是简单地将 basic、io 和 web 作为每个应用程序的子模块。是的,存在代码重复和磁盘空间浪费,但实现起来非常简单,并保证每个应用程序的不同编译器设置不会在共享库中相互干扰。我想这使得库不再被共享,但也许这在 2011 年不需要成为什么大问题。RAM 和磁盘变得更便宜,但工程时间却没有,而且源共享可以说比共享更便携二进制文件。

另一种方法是在问题中指定布局,并在每个子目录中都有 CMakeLists.txt 文件。 basic、io 和 web 中的 CMakeLists.txt 文件生成独立的共享库。每个应用程序目录中的 CMakeLists.txt 文件使用 add_subdirectory() 命令拉入每个共享库。然后,您可以下拉所有库目录和您想要的任何应用程序,并从每个应用程序目录中启动构建。

【讨论】:

  • 我同意共享源代码很重要,所以让我们明确一点:您是否建议在 repos 之间复制/粘贴代码?
  • 远非如此,@John Zwinck。我建议每个应用程序都有三个子模块,每个库(basic、io、web)一个子模块,并且每种类型的子模块都从其相应的遥控器中提取。一般来说,我认为复制和粘贴源代码违反了“不要重复自己”的格言,但如果复制由 git 之类的 VCS 管理,它会变得更安全,因为 VCS 有助于传播更改。这是我们首先使用版本控制系统的主要原因之一。
【解决方案4】:

您可以为此使用ADD_SUBDIRECTORY

https://cmake.org/cmake/help/v3.11/command/add_subdirectory.html

【讨论】:

    【解决方案5】:

    我最终做了我在问题中概述的事情,即检查一个空目录(包​​含一个忽略所有内容的 .gitignore 文件)并告诉 CMake 到 GLOB 任何目录(由用户放入其中)。然后我可以说 cmake myrootdir 它确实找到了所有不同的组件。这或多或少都可以。不过,它确实有一些缺点,例如一些第三方工具(如 BuildBot)期望采用更传统的项目结构,这使得将其他工具与这种安排相集成的工作量更大。

    【讨论】:

      【解决方案6】:

      CMake BASIS 工具提供实用程序,您可以在其中创建项目的独立模块并使用 ccmake 命令选择性地启用和禁用它们。

      全面披露:我是该项目的开发人员。

      【讨论】:

      • CMake 已经有了嵌套项目的工具,所以这似乎不是最好的解决方案
      • @monokrome 嵌套项目有什么工具?当我写答案时,这些工具是否存在于 2014 年?如果不是,请发表评论,不要对撰写本文时准确的答案投反对票。谢谢! :-)
      猜你喜欢
      • 2012-09-17
      • 1970-01-01
      • 1970-01-01
      • 2015-04-08
      • 1970-01-01
      • 1970-01-01
      • 2023-01-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多