CMake:如何最好地构建多个(可选)子项目?

时间:2011-06-23 19:39:44

标签: build cmake modularity

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

  • 基本
  • IO
  • 网络
  • APP-一个
  • 应用-B
  • 应用-C

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

我应该如何进行设置,以便我可以构建这三个应用,如果每个应用都是可选的,并且可能在构建时不存在?

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

  • 当你只说make时,显然CMake不会重新发送,所以如果你添加一个新应用,你必须再次运行cmake
  • 它对进行构建的人施加了特定的结构。
  • 不清楚如何制作单个应用程序的两个克隆并将它们分别针对相同的库构建进行构建。

一般概念就像传统的递归CMake项目,但是较低级别的模块不一定事先知道哪些更高级别的模块将使用它们。但是,我不想要求用户在固定位置安装较低级别的库(例如/usr/local/lib)。但是我想要make的单个调用来注意整个项目中已更改的依赖项,这样如果我正在构建一个应用程序但是已经更改了其中一个低级库,那么所有内容都将重新编译。

6 个答案:

答案 0 :(得分:4)

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

basicioweb以及一个引用这些内容的CMakeLists.txt创建一个CMakeLists.txt。然后,您可以使用CMake 导出功能导出这些目标,然后应用程序项目可以导入 CMake目标。

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

当这样做时,应用程序项目中的make将不会在库项目中执行make,您必须自己处理这个问题。

答案 1 :(得分:2)

拥有多个CMakeLists.txt。

许多开源项目采用此appraoch(LibOpenJPEG,LibPNG,poppler& etc等)。看看他们的CMakeLists.txt,了解他们是如何做到的。

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

答案 2 :(得分:1)

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

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

答案 3 :(得分:1)

您可以为此使用ADD_SUBDIRECTORY

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

答案 4 :(得分:0)

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

答案 5 :(得分:-1)

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

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