在cmake中,如何以可扩展的方式指定子目录的依赖关系?

Kan*_* Li 5 c++ build-automation cmake

假设源树的结构如下:

/
 |- lib1
 |  |- src.cpp
 |  |- lib1.h
 |  |- CMakeLists.txt
 |
 |- lib2
 |  |- src.cpp
 |  |- lib2.h
 |  |- CMakeLists.txt
 |
 |- lib3
 |  |- src.cpp
 |  |- lib3.h
 |  |- CMakeLists.txt
 |
 |- app
 |  |- src.cpp
 |  |- CMakeLists.txt
 |
 |- CMakeLists.txt
Run Code Online (Sandbox Code Playgroud)

认为:

  1. lib1 有函数 f();
  2. lib2 有函数 g(),它使用 f();
  3. app/src.cpp 使用函数 g();
  4. 没有人使用 lib3。

我想:

  1. 在 app/CMakeLists.txt 中,它仅链接到 lib2。这里的逻辑是,app/src.cpp只使用了g(),所以在编写app/src.cpp时,我们不能指定对lib1的依赖,因为它是lib2的实现细节。所以根据这个逻辑,在app/CMakeLists.txt中,它不能有任何与lib1相关的东西,即它既不是lib1的include_directories,lib1的add_subdirectory,也不是lib1的target_link_libraries等。
  2. 由于没有人使用 lib3,它甚至不会被构建。这需要自动完成。因此,手动为 lib1 和 lib2 添加子目录,但不为 lib3 添加子目录,这并不是一个聪明的方法。您可以想象,如果我们有一个非常大的源代码树,具有复杂的树结构和依赖关系,以及数百个不同子目录中的数百个可执行文件。如果我只想构建其中几个,那么我根本不想构建未使用的库。

所以我的问题是:有没有办法以可扩展的方式编写CMakeLists.txt文件来满足上述要求?如果没有的话,有没有类似的工具可以做到这一点?

谢谢。

arr*_*owd 4

对于1个问题:

lib2/CMakeLists.txt应该把这个:

target_link_libraries(lib2 lib1)
Run Code Online (Sandbox Code Playgroud)

在 app/CMakeLists.txt 中:

target_link_libraries(app lib2)
Run Code Online (Sandbox Code Playgroud)

现在,如果您尝试构建应用程序,CMake 将检查 lib2 是否是最新的,如果不是,则重建 lib1 和 lib2。

对于2个问题:

您可以使用基于变量的块add_subdirectory(lib3)来保护调用。if()option()

另一种方式 - 在 lib3/CMakeLists.txt 中:

add_library(lib3 ${SRCS} EXCLUDE_FROM_ALL)
Run Code Online (Sandbox Code Playgroud)

这将使 CMake 不将lib3目标添加到all目标中。如果您尝试构建依赖于它的东西,或者make lib3手动发出问题,仍然会构建该目标。

  • 您可以按任何顺序调用“add_subdirectory()”,而无需关心 deps。无论如何,你都需要 `target_link_libraries()` 。或者你要完全摆脱根 CMakeFiles.txt 吗? (2认同)