CMake 不包含子模块 B 中子模块 A 的头目录

Eth*_*n T 3 c++ cmake

我有一个 CMake 项目,如下所示:

project/
  CMakeLists.txt
  subprojectA/
    CMakeLists.txt
    include/
      headerA.hpp
    src/
      libraryA.cpp
  subprojectB/
    CMakeLists.txt
    src/
      mainB.cpp
Run Code Online (Sandbox Code Playgroud)

“库”子项目 A 被编译为静态库,成为 libsubprojectA.a。“主”项目 B 被编译为二进制文件并依赖于库。mainB.cpp 包含对 headerA.hpp 的引用。

这是 subprojectA/CMakeLists.txt:

project(SubProjectA)
include_directories(include)
add_library(subprojectA STATIC src/libraryA.cpp)
set(${PROJECT_NAME}_INCLUDE_DIRS
    ${PROJECT_SOURCE_DIR}/include
    CACHE INTERNAL "${PROJECT_NAME}: Include Directories" FORCE)
Run Code Online (Sandbox Code Playgroud)

这是 subprojectB/CMakeLists.txt:

project(SubProjectB)
include_directories(${SubProjectA_INCLUDE_DIRS})
add_executable(mainBinary src/mainB.cpp)
target_link_libraries(mainBinary subprojectA)
Run Code Online (Sandbox Code Playgroud)

主项目 CMakeLists.txt 如下所示:

project(Project)
add_subdirectory(subprojectB)
add_subdirectory(subprojectA)
Run Code Online (Sandbox Code Playgroud)

请注意,主项目 subprojectB 列在 subprojectA之前

问题就在这里。当我第一次在此项目上运行“cmake”时,${SubProjectA_INCLUDE_DIRS}未在 SubProjectB 中设置。

我认为正在发生的事情是 SubProjectB 的 CMakeLists 在${SubProjectA_INCLUDE_DIRS}尚未设置时首先加载。结果,它将自己的包含路径设置为空字符串。然而,即使libsubprojectA.a之前构建成功mainBinary,包含路径也已预先设置为空。结果,我在尝试执行以下操作时收到此错误mainBinary

subprojectB/src/mainB.cpp:1:23: fatal error: headerA.hpp: No such file or directory
#include "headerA.hpp"
                      ^
Run Code Online (Sandbox Code Playgroud)

在 CMake 的声明性世界中,将主项目 CMakeLists 中的 subprojectA 放在 subprojectB 之前是一种解决方法。我真正想要的是知道向 CMake 指示该include_directories(${SubProjectA_INCLUDE_DIRS})取决于SubProjectA 的 CMakeLists 中存在的定义的正确方法。有一个更好的方法吗?

Tsy*_*rev 5

如果要表示包含目录subprojectA/include是库subprojectA的接口,请使用target_include_directories命令将此属性附加到目标:

子项目A/CMakeLists.txt

project(SubProjectA)
add_library(subprojectA STATIC src/libraryA.cpp)
# PUBLIC adds both:
#     1) include directories for compile library and
#     2) include directories for library's interface
target_include_directories(subprojectA PUBLIC include)
Run Code Online (Sandbox Code Playgroud)

因此与subprojectA链接的任何可执行文件(或其他库)将自动具有此包含目录:

子项目B/CMakeLists.txt

project(SubProjectB)
add_executable(mainBinary src/mainB.cpp)
target_link_libraries(mainBinary subprojectA)
Run Code Online (Sandbox Code Playgroud)

当然,为了正确使用最后一个命令,您需要在可执行文件之前处理带有库的目录:

CMakeLists.txt

project(Project)
add_subdirectory(subprojectA)
add_subdirectory(subprojectB)
Run Code Online (Sandbox Code Playgroud)