CMake如何配置自有静态库自动关联glad、glfw等依赖
CMake实现静态库自动传递依赖配置方案
现有项目结构
|-- CMakeLists.txt |-- build |-- include |-- libs | |-- glad | | |-- include | | | `-- glad | | | `-- glad.h | | `-- src | | `-- glad.c | `-- glfw | `-- include | `-- GLFW | `-- glfw3.h |-- sandbox | |-- CMakeLists.txt | |-- build | `-- main.cpp `-- src
核心目标
- 根目录luna项目编译为静态库
- sandbox程序仅需链接luna静态库,无需单独配置glad、glfw的头文件路径、链接规则,自动完成所有依赖的编译与链接
现有配置问题
- 根CMake通过
find_package查找系统安装的glfw,没有使用项目内libs目录下的glfw资源,无法实现依赖随库一起编译,部署到没有预装glfw的环境会直接编译失败 - sandbox目录独立声明项目、独立查找glfw依赖,没有和luna库建立依赖传递关系,必须手动重复配置依赖
- 硬编码绝对路径链接静态库的方式兼容性极差,修改编译输出目录、换设备编译都会直接失效
- glad源码直接混入主库编译逻辑,后续升级、替换第三方依赖时修改成本高
注意:当前libs/glfw目录仅存放了头文件,缺少glfw源码,需要将glfw官方源码包完整解压到该目录,才能实现项目自包含编译
推荐优化方案
优化后项目结构
将第三方依赖配置和主库逻辑拆分,统一管理编译选项,避免重复配置:
|-- CMakeLists.txt # 根配置入口,统一管理全局编译参数、主库目标 |-- build # 全局编译输出目录,删除sandbox下的独立build目录,统一在根目录编译所有目标 |-- include | `-- luna # 主库公开头文件统一放入luna子目录,避免和第三方库头文件命名冲突 |-- libs | |-- CMakeLists.txt # 第三方依赖统一配置入口 | |-- glad | | |-- include | | | `-- glad | | | `-- glad.h | | `-- src | | `-- glad.c | `-- glfw # 存放glfw完整源码 |-- sandbox | |-- CMakeLists.txt # 沙箱程序配置 | `-- main.cpp `-- src # 主库私有源码
对应CMake配置
1. 根目录CMakeLists.txt
cmake_minimum_required(VERSION 3.10) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) # 开启全局位置无关代码选项,避免静态库链接时报fPIC相关错误 set(CMAKE_POSITION_INDEPENDENT_CODE ON) project(luna) # 先加载第三方依赖配置 add_subdirectory(libs) # 收集主库源码 file(GLOB_RECURSE SRC_FILES src/*.cpp) # 声明luna静态库目标 add_library(luna STATIC ${SRC_FILES}) # PUBLIC修饰的依赖会自动传递给所有链接luna的目标,不需要下游重复配置 target_link_libraries(luna PUBLIC glad glfw) target_include_directories(luna PUBLIC ${PROJECT_SOURCE_DIR}/include ) # 可选:把sandbox作为子项目加入构建,一次编译所有目标 add_subdirectory(sandbox)
2. libs目录新建CMakeLists.txt
# 配置glad静态库 add_library(glad STATIC glad/src/glad.c ) target_include_directories(glad PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/glad/include ) # 配置glfw静态库,关闭不需要的编译目标减少编译耗时 set(GLFW_BUILD_DOCS OFF CACHE BOOL "" FORCE) set(GLFW_BUILD_TESTS OFF CACHE BOOL "" FORCE) set(GLFW_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE) add_subdirectory(glfw)
3. sandbox目录CMakeLists.txt
# 兼容两种编译模式:既可以作为根项目的子模块统一编译,也可以在单独编译时自动查找已安装的luna库 if(NOT TARGET luna) cmake_minimum_required(VERSION 3.10) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) project(sandbox) find_package(luna REQUIRED) endif() add_executable(sandbox main.cpp) # 仅需链接luna库,glad、glfw的头文件路径、链接规则会自动传递 target_link_libraries(sandbox PRIVATE luna)
使用说明
- 推荐在根目录build下执行
cmake .. && make,会自动按顺序编译glad、glfw、luna静态库、sandbox可执行文件,全程不需要额外配置依赖 - 如果坚持用直接链接静态库文件的方式,只要按照上面的配置用
PUBLIC修饰luna的依赖,就算直接写libluna.a的路径,CMake也会自动把glad、glfw的头文件搜索路径、链接要求传递给sandbox目标,不需要单独配置。但这种硬编码路径的方式不推荐,用target名称链接的方式会自动定位库文件位置,跨平台、跨编译目录的兼容性更好。
内容的提问来源于stack exchange,提问作者m100re
相关产品推荐
相关产品推荐

