使用CMake链接ImGui、SDL2到项目时的依赖链接错误排查
SDL2+OpenGL3项目ImGui链接错误修复方案
错误根因
三个错误分别对应CMake配置的三类典型问题:
- 未定义ImGui引用错误:
UserInterface源码直接调用ImGui接口,但未声明对imgui目标的链接依赖,链接器处理UserInterface时无法解析对应符号。 - 共享库重定位错误:默认编译的静态库不带位置无关代码(-fPIC),当静态库被链接到动态库时,会触发PC32重定位错误。
- libdl DSO缺失错误:静态库依赖不会自动传递,且原配置将
libdl放在链接列表最前端,链接器按顺序处理符号时无法匹配后续imgui对dl相关函数的引用,触发缺失错误。
修复步骤
1. 给imgui静态库开启位置无关代码支持
不管后续将子模块编译为静态库还是动态库,提前开启PIC可以避免重定位错误,不需要全局加-fPIC编译选项,只需要针对imgui目标设置即可。
2. 按谁使用谁声明的原则配置依赖传递
不要把所有库都直接链接到主可执行文件,直接调用依赖的模块自己声明链接关系,使用PUBLIC/PRIVATE/INTERFACE控制依赖传递范围:
- 模块源码内部调用的依赖用
PRIVATE,不会传递给上层模块 - 模块头文件暴露的依赖用
PUBLIC,会自动传递给链接当前模块的上层目标
3. 修正链接顺序
将每个库的直接依赖绑定到库自身的配置上,CMake会自动按正确的链接顺序排布,不需要手动调整链接列表顺序。
修改后完整CMake配置
顶层CMakeLists.txt
cmake_minimum_required(VERSION 3.20) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) project(digitus) set(CMAKE_MODULE_PATH "/usr/local/lib/cmake") find_package(OpenGL REQUIRED) find_package(SDL2 REQUIRED) find_package(GLEW REQUIRED) find_package(glm REQUIRED) add_subdirectory(src)
src目录下CMakeLists.txt
SET(SOURCES main.cpp ApplicationManager.cpp ApplicationManager.h [...] ) SET(IMGUISOURCE imconfig.h imgui_demo.cpp imgui_draw.cpp imgui_impl_opengl3_loader.h imgui_impl_opengl3.cpp imgui_impl_opengl3.h imgui_impl_sdl.cpp imgui_impl_sdl.h imgui_internal.h imgui_tables.cpp imgui_widgets.cpp imgui.cpp imgui.h ) # 显式声明imgui为静态库,开启PIC支持 add_library(imgui STATIC ${IMGUISOURCE}) set_target_properties(imgui PROPERTIES POSITION_INDEPENDENT_CODE ON) # imgui自身依赖的库设为PRIVATE,不向上传递 target_link_libraries(imgui PRIVATE ${CMAKE_DL_LIBS} OpenGL::GL SDL2::SDL2 ) add_executable(digitus ${SOURCES}) add_subdirectory(Action) add_subdirectory(UserInterface) # 主程序只需要直接链接顶层依赖,传递性依赖会自动处理 target_link_libraries(digitus PRIVATE UserInterface Action glm::glm GLEW::glew SDL2::SDL2 OpenGL::GL )
UserInterface目录下CMakeLists.txt
Set(USERINTERFACESOURCE UserInterface.h UserInterface.cpp CircuitWindow.h CircuitWindow.cpp ) add_library(UserInterface STATIC ${USERINTERFACESOURCE}) # UserInterface直接调用ImGui接口,设为PUBLIC依赖,上层目标自动获取imgui头文件和链接属性 target_link_libraries(UserInterface PUBLIC imgui)
构建验证
修改配置后清空build目录下所有缓存文件,重新执行CMake配置和构建命令即可:
rm -rf build/* cd build cmake .. make -j$(nproc)
修复后三类错误都会被解决:
- 依赖声明补全后不会出现ImGui相关的未定义引用
- imgui开启PIC后,后续将UserInterface改回SHARED动态库也不会触发重定位错误
- 依赖绑定到对应目标后,CMake自动维护链接顺序,不会出现libdl的DSO缺失错误
内容的提问来源于stack exchange,提问作者bonkt
相关产品推荐
相关产品推荐

