在CMake中链接预构建静态库Noesis时出现未定义引用问题
Noesis GUI库集成中的链接错误问题及解决
问题初始表现
在游戏项目中集成Noesis GUI库时,链接阶段所有调用Noesis函数的地方均出现undefined reference错误,示例报错:
[0/1] Re-running CMake... -- -- Configuring done (0.3s) -- Generating done (0.1s) -- Build files have been written to: C:/projects/Curse of Elliah/cmake-build-debug [1/2] Linking CXX executable Curse_of_Elliah.exe FAILED: Curse_of_Elliah.exe C:\WINDOWS\system32\cmd.exe /C "cd . && C:\Users\wilto\AppData\Local\Programs\CLion\bin\mingw\bin\g++.exe -g @CMakeFiles\Curse_of_Elliah.rsp -o Curse_of_Elliah.exe -Wl,--out-implib,libCurse_of_Elliah.dll.a -Wl,--major-image-version,0,--minor-image-version,0 && cd ." C:\Users\wilto\AppData\Local\Programs\CLion\bin\mingw\bin/ld.exe: CMakeFiles/Curse_of_Elliah.dir/libs/Noesis/NoesisGL/GLRenderDevice.cpp.obj: in function `NoesisApp::GLRenderDevice::GLRenderDevice(bool)': C:/projects/Curse of Elliah/libs/Noesis/NoesisGL/GLRenderDevice.cpp:154: undefined reference to `Noesis::RenderDevice::RenderDevice()'
Noesis为预构建库,包含头文件、.lib导入库和.dll动态库,但始终无法链接到.dll中的函数定义。
根据官方集成教程:
/Bin: 存放各架构动态库的目录,可执行文件需能访问此路径,最简单的方式是通过构建后步骤复制到对应位置。
/Include: 公共头文件目录,需添加到项目的附加包含目录中。
/Lib: 存放需链接的目标库的目录,按架构分类,需添加到附加库目录并链接对应库。
已完成的配置:
- 头文件放入项目lib目录,通过CMake引入后可正常使用;
.lib文件置于libs/Noesis/Lib/windows_x86_64/Noesis.lib,通过message(STATUS)验证CMake可找到该文件;.dll文件尝试放置在lib子目录(已添加到Windows环境变量)、构建目录cmake-build-debug及其子目录(含与.exe同级路径),均无效。
尝试过的方案:
- 常规
include_directories+target_link_libraries引入方式; - 通过
add_library导入共享库:
add_library(noesis SHARED IMPORTED) set_target_properties(noesis PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${PROJECT_SOURCE_DIR}/libs/Noesis" IMPORTED_LOCATION "${PROJECT_SOURCE_DIR}/libs/Noesis/Bin/windows_x86_64/Noesis.dll" IMPORTED_IMPLIB "${PROJECT_SOURCE_DIR}/libs/Noesis/Lib/windows_x86_64/Noesis.lib" #INTERFACE_LINK_LIBRARIES "\$<LINK_ONLY:gdi32>" )
- 修改
IMPORTED_LOCATION指向.lib文件并省略IMPORTED_IMPLIB;
所有尝试均未解决问题,且Noesis官方不支持CMake,无法获取官方帮助。
最小复现项目测试
创建仅包含Noesis的最小项目,使用MSVC和Visual Studio 2022生成器,CMake代码如下:
cmake_minimum_required(VERSION 3.29) project(untitled) set(CMAKE_CXX_STANDARD 23) include_directories("${CMAKE_CURRENT_SOURCE_DIR}/libs/Noesis") link_directories("${CMAKE_CURRENT_SOURCE_DIR}/libs/Noesis/Bin/windows_x86_64") add_library(noesis SHARED IMPORTED) set_target_properties(noesis PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_SOURCE_DIR}/libs/Noesis" IMPORTED_LOCATION "${CMAKE_CURRENT_SOURCE_DIR}/libs/Noesis/Bin/windows_x86_64/Noesis.dll" IMPORTED_IMPLIB "${CMAKE_CURRENT_SOURCE_DIR}/libs/Noesis/Lib/windows_x86_64/Noesis.lib" #INTERFACE_LINK_LIBRARIES "\$<LINK_ONLY:gdi32>" ) add_executable(untitled main.cpp) target_link_libraries (untitled ${noesis})
项目结构:
untitled - cmake-build-debug - libs - Noesis - Bin - windows_x86_64 - Noesis.dll - Lib - windows_x86_64 - Noesis.lib - Noesis头文件 - CMakeList.txt - main.cpp
仍出现相同链接错误:
main.obj : error LNK2019: unresolved external symbol "__declspec(dllimport) void __cdecl Noesis::Init(void)" (__imp_?Init@Noesis@@YAXXZ) referenced in function main [C:\projects\untitled\cmake-build-debug\untitled.vcxproj] C:\projects\untitled\cmake-build-debug\Debug\untitled.exe : fatal error LNK1120: 1 unresolved externals [C:\projects\untitled\cmake-build-debug\untitled.vcxproj]
问题排查与解决
- 将
target_link_libraries中的${noesis}改为noesis后,链接错误消失,但运行时出现错误码-1073741515 (0xC0000135),推测是.exe无法找到.dll文件; - 最终发现问题根源:MSVC将
.exe生成在了cmake-build-debug/Debug子目录中,之前仅将.dll放在cmake-build-debug目录下,未放入实际生成.exe的子目录,将.dll复制到该子目录后问题完全解决。
内容的提问来源于stack exchange,提问作者William Toft
相关产品推荐
相关产品推荐

