You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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属性(仅依赖该目标的其他目标编译可见)

额外说明

  1. 关于GLOB_RECURSE的弊端:CMake不会自动检测通配符匹配新增的文件,每次添加新文件后需要手动重新运行CMake,官方更推荐手动列出所有源文件和头文件。
  2. 公有头文件安装:如果需要将公有头文件安装到系统路径,可添加以下命令:
install(TARGETS mm_cpp_lib
        FILE_SET HEADERS DESTINATION include)

内容的提问来源于stack exchange,提问作者glades

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 15:18:23