使用target_sources文件集定义私有/公有头文件时遇作用域错误,求解答
解决CMake中target_sources文件集定义私有/公有头文件的错误
错误原因
你遇到的错误核心问题是:同一CMake目标下,文件集的名称必须唯一。你先后用HEADERS这个名称定义了PRIVATE和PUBLIC作用域的文件集,CMake会认为你在修改已定义的HEADERS文件集的作用域——但文件集的作用域在首次创建后就无法更改,因此触发错误。
正确解决方案
给私有头文件集指定一个独特的名称(比如PRIVATE_HEADERS),与公有头文件集的HEADERS区分开,分别定义:
## 虽然不推荐但因图省事使用通配符匹配 file(GLOB_RECURSE LIB_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp") file(GLOB_RECURSE LIB_PRV_HEADERS "${CMAKE_CURRENT_SOURCE_DIR}/src/*.h") file(GLOB_RECURSE LIB_PUB_HEADERS "${CMAKE_CURRENT_SOURCE_DIR}/include/*.h") ## 定义头文件与源文件 target_sources(mm_cpp_lib PRIVATE ${LIB_SOURCES} PRIVATE FILE_SET PRIVATE_HEADERS TYPE HEADERS FILES ${LIB_PRV_HEADERS} PUBLIC FILE_SET HEADERS TYPE HEADERS BASE_DIRS "include" # 头文件将安装在include/目录下 FILES ${LIB_PUB_HEADERS} )
对官方文档的正确理解
文档中提到的PRIVATE/PUBLIC/INTERFACE作用域,是针对单个文件集的作用域设置,并非允许创建多个同名不同作用域的文件集:
- 若一个
HEADERS类型的文件集设为PRIVATE,它的BASE_DIRS会被包裹在$<BUILD_INTERFACE>中,添加到目标的INCLUDE_DIRECTORIES属性(仅当前目标编译可见) - 若设为
PUBLIC,则同时添加到INCLUDE_DIRECTORIES和INTERFACE_INCLUDE_DIRECTORIES属性(当前目标和依赖该目标的其他目标编译可见) - 若设为
INTERFACE,仅添加到INTERFACE_INCLUDE_DIRECTORIES属性(仅依赖该目标的其他目标编译可见)
额外说明
- 关于GLOB_RECURSE的弊端:CMake不会自动检测通配符匹配新增的文件,每次添加新文件后需要手动重新运行CMake,官方更推荐手动列出所有源文件和头文件。
- 公有头文件安装:如果需要将公有头文件安装到系统路径,可添加以下命令:
install(TARGETS mm_cpp_lib FILE_SET HEADERS DESTINATION include)
内容的提问来源于stack exchange,提问作者glades
相关产品推荐
相关产品推荐

