如何通过CMake正确链接GLAD/GLFW?子目录头文件引用失败求助
折腾数日用CMake配置带OpenGL上下文的窗口,卡在路径引用问题上:src根目录可正常引用GLAD/GLFW,但子目录中无法引用。作为CMake新手,不清楚问题根源。
文件结构
├── CMakeLists.txt ├── README.md ├── build.sh ├── configure.sh ├── lib │ └── external │ ├── glad │ │ ├── CMakeLists.txt │ │ ├── include │ │ └── src │ └── glfw │ ├── CMake │ ├── CMakeLists.txt │ ├── CONTRIBUTORS.md │ ├── LICENSE.md │ ├── README.md │ ├── deps │ ├── docs │ ├── examples │ ├── include │ ├── src │ └── tests ├── run.sh └── src ├── CMakeLists.txt ├── Engine │ ├── CMakeLists.txt │ ├── gameManager.cpp │ └── gameManager.h ├── Entities ├── RenderEngine │ ├── CMakeLists.txt │ ├── displayManager.cpp │ └── displayManager.h └── main.cpp
在displayManager.h中引用GLAD/GLFW时,报错:cannot open source file "glad/glad.h"和cannot open source file GLFW/glfw3.h。
现有CMake配置
顶层CMakeLists.txt
cmake_minimum_required(VERSION 3.25.0) project(Opengl_tut VERSION 0.1.0) # For loop add subdirectories foreach (sub "src" "${GLFW_DIR}" "${GLAD_DIR}" "src/RenderEngine") add_subdirectory("${sub}") endforeach ()
lib/external/glad/CMakeLists.txt
cmake_minimum_required(VERSION 3.25.0) project(Glad) add_library(glad include/glad/glad.h src/glad.c) target_include_directories(glad PUBLIC include/)
lib/external/glfw/CMakeLists.txt
使用官方仓库的标准配置文件。
src/CMakeLists.txt
add_executable(${PROJECT_NAME} main.cpp) # Get these files target_link_libraries(${PROJECT_NAME} glfw glad )
该配置可让main.cpp正常#include <glad/glad.h>和<GLFW/glfw3.h>,因此尝试给RenderEngine配置类似内容:
src/RenderEngine/CMakeLists.txt
add_library(displayManager "displayManager.cpp" "displayManager.h") # Get these files target_link_libraries(${PROJECT_NAME} glfw glad )
需要解决的问题:
- 如何让
displayManager.h识别GLAD/GLFW? - 需在
src/Engine/gameManager.h中#include "displayManager.h",是否适用相同方案?
1. 修复RenderEngine的CMake配置
你当前src/RenderEngine/CMakeLists.txt中的target_link_libraries错误地使用了${PROJECT_NAME}(指向顶层项目Opengl_tut),正确做法是将依赖链接到displayManager库本身,并且使用PUBLIC关键字传递依赖:
add_library(displayManager "displayManager.cpp" "displayManager.h") # 将glfw和glad链接到displayManager,PUBLIC确保依赖传递 target_link_libraries(displayManager PUBLIC glfw PUBLIC glad )
PUBLIC的作用是:所有链接displayManager的目标(如主程序、gameManager)会自动继承GLFW和GLAD的包含路径,无需重复配置。
2. 主程序链接displayManager库
修改src/CMakeLists.txt,将displayManager链接到主可执行文件,确保主程序能调用displayManager的功能:
add_executable(${PROJECT_NAME} main.cpp) target_link_libraries(${PROJECT_NAME} glfw glad displayManager # 添加该行 )
3. 处理gameManager引用displayManager的情况
对于gameManager.h引用displayManager.h的需求,遵循同样的依赖传递规则:
- 修改
src/Engine/CMakeLists.txt:
add_library(gameManager "gameManager.cpp" "gameManager.h") # 链接displayManager,PUBLIC传递依赖 target_link_libraries(gameManager PUBLIC displayManager )
- 在
src/CMakeLists.txt中把gameManager链接到主程序:
target_link_libraries(${PROJECT_NAME} glfw glad displayManager gameManager # 添加该行 )
额外优化建议
顶层CMake的foreach循环可简化,改为由src目录的CMake管理子目录,结构更清晰:
- 修改顶层CMakeLists.txt:
cmake_minimum_required(VERSION 3.25.0) project(Opengl_tut VERSION 0.1.0) # 先添加外部依赖 add_subdirectory(lib/external/glfw) add_subdirectory(lib/external/glad) # 添加src目录,子目录由src的CMake管理 add_subdirectory(src)
- 在
src/CMakeLists.txt中添加子目录:
# 管理src下的子模块 add_subdirectory(RenderEngine) add_subdirectory(Engine) add_executable(${PROJECT_NAME} main.cpp) target_link_libraries(${PROJECT_NAME} glfw glad displayManager gameManager )
这种方式避免手动维护子目录列表,层级更合理。
内容的提问来源于stack exchange,提问作者ngurnard

