CMake添加两个子目录后实现互相调用头文件的配置问题
问题根源
你当前仅在顶层CMake中为最终生成的tunersa库配置了两个子目录的头文件搜索路径,而HelloOboeEngine和SoundGenerator两个子库作为独立的编译目标,没有配置对应的头文件搜索路径,因此互相无法识别对方的头文件。
核心原理
- CMake的头文件搜索路径是目标隔离的,每个编译目标的路径配置默认互不影响,全局
include_directories会污染所有目标,不推荐使用。 target_include_directories的三个作用域说明:- PRIVATE:配置的路径仅当前目标自身编译时生效,依赖该目标的其他目标无法继承
- INTERFACE:配置的路径仅提供给依赖该目标的其他目标使用,当前目标自身编译时不生效
- PUBLIC:同时对当前目标和依赖它的目标生效
- 当使用
target_link_libraries链接一个CMake目标时,被链接目标的INTERFACE/PUBLIC类型头路径会自动添加到当前目标的搜索路径中,无需手动配置绝对路径。
推荐解决方案(符合现代CMake规范)
步骤1:修改两个子库的CMake配置,声明自身的公开头目录
修改HelloOboeEngine/CMakeLists.txt:
SET(SOURCE_FILES "HelloOboeEngine.cpp") SET(HEADER_FILES "HelloOboeEngine.h") add_library(HelloOboeEngine SHARED ${SOURCE_FILES} ${HEADER_FILES}) # 声明本库的公开头目录,所有依赖本库的目标会自动获得该搜索路径 target_include_directories(HelloOboeEngine INTERFACE ${CMAKE_CURRENT_SOURCE_DIR})
修改SoundGenerator/CMakeLists.txt:
SET(SOURCE_FILES "SoundGenerator.cpp") SET(HEADER_FILES "SoundGenerator.h") add_library(SoundGenerator SHARED ${SOURCE_FILES} ${HEADER_FILES}) # 声明本库的公开头目录,所有依赖本库的目标会自动获得该搜索路径 target_include_directories(SoundGenerator INTERFACE ${CMAKE_CURRENT_SOURCE_DIR})
步骤2:为两个子库配置头路径/依赖关系,分两种场景
场景A:仅头文件互相引用,没有互相调用对方的函数实现
直接给两个子库添加对方的头路径即可:
在HelloOboeEngine/CMakeLists.txt末尾添加:
target_include_directories(HelloOboeEngine PRIVATE ${PROJECT_SOURCE_DIR}/SoundGenerator)
在SoundGenerator/CMakeLists.txt末尾添加:
target_include_directories(SoundGenerator PRIVATE ${PROJECT_SOURCE_DIR}/HelloOboeEngine)
场景B:不仅引用头文件,还会互相调用对方的函数实现
因为两个是动态库,NDK平台支持动态库循环依赖,直接互相链接目标即可,CMake会自动传递头路径,不需要手动写路径:
在HelloOboeEngine/CMakeLists.txt末尾添加:
target_link_libraries(HelloOboeEngine PRIVATE SoundGenerator)
在SoundGenerator/CMakeLists.txt末尾添加:
target_link_libraries(SoundGenerator PRIVATE HelloOboeEngine)
步骤3(可选):清理顶层CMake的冗余配置
因为两个子库已经声明了自身的公开头目录,顶层tunersa链接两个子库后会自动获得头路径,所以可以删除顶层CMake中以下冗余配置:
include_directories(${PROJECT_SOURCE_DIR}/HelloOboeEngine) include_directories(${PROJECT_SOURCE_DIR}/SoundGenerator) # 以及target_include_directories(tunersa PUBLIC)中以下两行 ${PROJECT_SOURCE_DIR}/HelloOboeEngine ${PROJECT_SOURCE_DIR}/SoundGenerator
内容的提问来源于stack exchange,提问作者Santiago Alejandro Torres Arag
相关产品推荐
相关产品推荐

