假设源树在这个结构中:

/
 |- 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

认为:
  • lib1 有函数 f();
  • lib2 具有使用 f() 的函数 g();
  • app/src.cpp 使用函数 g();
  • 没有人使用 lib3。

  • 我想:

    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等。
  • 由于没有人使用 lib3,它甚至不会被构建。这需要自动完成。因此,为 lib1 和 lib2 而不是 lib3 手动 add_subdirectory 不是一个聪明的方法。您可以想象一下,如果我们有一个非常大的源代码树,它具有复杂的树结构和依赖关系以及数百个不同子目录中的数百个可执行文件。如果我只想构建其中的几个,那么我根本不想费心构建未使用的库。

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

    谢谢。

    最佳答案

    对于第一个问题:

    lib2/CMakeLists.txt 你应该把这个:

    target_link_libraries(lib2 lib1)
    

    在 app/CMakeLists.txt 中:
    target_link_libraries(app lib2)
    

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

    对于第二个问题:

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

    另一种方式 - 在 lib3/CMakeLists.txt 中:
    add_library(lib3 ${SRCS} EXCLUDE_FROM_ALL)
    

    这将使 CMake 不将 lib3 目标添加到 all 目标中。如果您尝试根据它构建某些东西,或者手动发出 make lib3,则仍将构建此目标。

    关于c++ - 在cmake中,如何以可扩展的方式指定子目录的依赖关系?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/9439865/

    10-13 08:05