如何迁移根CMake的include_directories到common模块并保留完整包含路径
CMake路径迁移问题:保留完整头文件包含路径的解决方案
项目结构
project/ ├── apps │ ├── app_a │ ├── app_b │ ├── app_c │ ├── CMakeLists.txt ├── CMakeLists.txt ├── common │ ├── some_data.cpp │ ├── some_data.h │ ├── some_data_a │ ├── some_data_b │ ├── some_data_c │ └── CMakeLists.txt
需求背景
之前在根目录CMakeLists.txt中配置include_directories(${PROJECT_SOURCE_DIR}),使得app_a/src/app_a.h里可以用#include "common/some_data_a/some_data_a.h"这种完整路径包含头文件。现在需要将该include路径配置迁移到common/CMakeLists.txt中,通过target_include_directories实现,同时删除根目录的对应配置,且必须保留这种完整路径的包含方式,不能改成仅写#include "some_data_a/some_data_a.h"。
之前尝试target_include_directories(common INTERFACE ${PROJECT_SOURCE_DIR})但未生效,求解决办法。
解决方案
步骤1:正确创建common目标
首先在common/CMakeLists.txt中定义common目标,分两种场景选择:
- 若
common仅用于传递依赖(比如只有头文件,或some_data.cpp无需单独编译),创建INTERFACE库:
add_library(common INTERFACE)
- 若
common有需要编译的源码(比如some_data.cpp),创建静态/动态库:
add_library(common STATIC some_data.cpp) # 或根据需求选择 SHARED
步骤2:配置目标的include路径
根据目标类型选择对应关键字:
- 若是INTERFACE库,用
INTERFACE关键字将项目根目录设为接口包含路径:
target_include_directories(common INTERFACE ${PROJECT_SOURCE_DIR} )
- 若是带源码的STATIC/SHARED库,用
PUBLIC关键字(同时作用于库自身和依赖它的目标):
target_include_directories(common PUBLIC ${PROJECT_SOURCE_DIR} )
步骤3:让依赖的app链接common目标
这是核心环节!所有需要使用common头文件的app(比如app_a),必须在自身的CMakeLists.txt中链接common目标:
target_link_libraries(app_a PRIVATE common)
无效原因分析
- 大概率是
common目标未正确创建,或者你的app未链接common目标,导致INTERFACE的include路径未传递到app的编译配置中。 - 可通过
message(STATUS "PROJECT_SOURCE_DIR: ${PROJECT_SOURCE_DIR}")打印路径,验证${PROJECT_SOURCE_DIR}是否正确指向项目根目录。
可选优化:区分构建与安装路径
如果项目需要支持安装,推荐用CMake生成器表达式区分构建和安装阶段的路径,更规范:
target_include_directories(common INTERFACE $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}> # 若安装后头文件放在include目录,添加此行 # $<INSTALL_INTERFACE:include> )
内容的提问来源于stack exchange,提问作者a.wise
相关产品推荐
相关产品推荐

