Win10下使用CMake编译libcurl报LNK2019未解析符号错误如何解决
我尝试在Win10系统下基于CMake编译项目中的libcurl,目前libcurl部分的配置如下:
link_directories("C:/Program Files/OpenSSL-Win64-1_1_1/lib") link_directories("C:/Program Files/OpenSSL-Win64-1_1_1") list(APPEND CMAKE_PREFIX_PATH ${CMAKE_CURRENT_SOURCE_DIR}/out/build/x64-Debug/libssh2-1.10.0/src) add_subdirectory(curl-7.80.0)
执行编译时触发如下错误:
Creating library C:/PATH/build/curl-7.80.0/lib/Debug/libcurl-d_imp.lib and object C:/PATH/build/curl-7.80.0/lib/Debug/libcurl-d_imp.exp
libssh2.obj : error LNK2019: unresolved external symbol libssh2_init referenced in function Curl_ssh_init [C:\PATH\curl-7.80.0\build\lib\libcurl.vcxproj]
libssh2.obj : error LNK2019: unresolved external symbol libssh2_exit referenced in function Curl_ssh_cleanup
[C:\PATH\curl-7.80.0\build\lib\libcurl.vcxproj]
libssh2.obj : error LNK2019: unresolved external symbol libssh2_session_init_ex referenced in function ssh_force_knownhost_key_type
[C:\PATH\curl-7.80.0\build\lib\libcurl.vcxproj]
libssh2.obj : error LNK2019: unresolved external symbol libssh2_session_abstract referenced in function sftp_perform
[C:\PATH\curl-7.80.0\build\lib\libcurl.vcxproj]
我使用的OpenSSL通过slproweb提供的Win32OpenSSL安装包安装,我对CMake的了解仅够编译普通自有项目,这个问题超出了我的知识范围,恳请大家提供帮助。
补充1:CMake生成的实际链接命令
Link:
C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Tools\MSVC\14.29.30133\bin\HostX64\x64\link.exe /ERRORREPORT:QUEUE /OUT:"C:\PATH\bin\64bit_\Debug\libcurl-d.dll" /INCREMENTAL /ILK:"libcurl.dir\Debug\libcurl-d.ilk" /NOLOGO /LIBPATH:"C:/Program Files/OpenSSL-Win64-1_1_1/lib" /LIBPATH:"C:/Program Files/OpenSSL-Win64-1_1_1/lib/Debug" /LIBPATH:"C:/Program Files/OpenSSL-Win64-1_1_1" /LIBPATH:"C:/Program Files/OpenSSL-Win64-1_1_1/Debug" /LIBPATH:"C:/PATH/out/build/x64-Debug/libssh2-1.10.0/src" /LIBPATH:"C:/PATH/out/build/x64-Debug/libssh2-1.10.0/src/Debug" /LIBPATH:"C:/PATH/out/build/x64-Debug/libssh2-1.10.0" /LIBPATH:"C:/PATH/out/build/x64-Debug/libssh2-1.10.0/Debug" wldap32.lib winmm.lib ws2_32.lib "......\out\build\x64-Debug\libssh2-1.10.0\src\libssh2.lib" advapi32.lib crypt32.lib kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib /MANIFEST /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /manifest:embed /DEBUG /PDB:"C:/PATH/bin/64bit_/Debug/libcurl-d.pdb" /SUBSYSTEM:CONSOLE /TLBID:1 /DYNAMICBASE /NXCOMPAT /IMPLIB:"C:/PATH/build/curl-7.80.0/lib/Debug/libcurl-d_imp.lib" /MACHINE:X64 /machine:x64 /DLL libcurl.dir\Debug\libcurl.res
补充2:针对libssh2_exit执行dumpbin的结果
00C 00000050 SECT4 notype () External | libssh2_exit
01B 00000008 SECT5 notype Static | $unwind$libssh2_exit
01C 0000000C SECT6 notype Static | $pdata$libssh2_exit
这个报错的核心原因是libcurl编译时对libssh2的符号识别和实际libssh2库的编译配置不匹配,按以下步骤排查修复即可:
- 添加静态编译标记
你使用的是静态编译的libssh2库,但libcurl默认会按照动态库的规则去查找带dll导入前缀的libssh2符号,导致符号不匹配。在add_subdirectory(curl-7.80.0)之前添加如下配置,强制指定静态链接libssh2:
# 启用libcurl的ssh支持 set(CURL_USE_LIBSSH2 ON CACHE BOOL "enable libssh2" FORCE) # 告诉curl当前用的是静态版libssh2 add_compile_definitions(LIBSSH2_STATIC) # 补充libssh2的头文件目录,替换为你实际的libssh2源码include路径和编译输出的头文件路径 include_directories(${CMAKE_CURRENT_SOURCE_DIR}/libssh2-1.10.0/include ${CMAKE_CURRENT_SOURCE_DIR}/out/build/x64-Debug/libssh2-1.10.0/include)
- 统一运行库配置
检查libssh2和libcurl的编译选项,确保二者使用完全相同的CRT运行库:Debug模式下统一为/MDd(动态运行库)或/MTd(静态运行库),Release模式下对应为/MD或/MT,避免运行库不匹配导致的符号冲突。 - 清理缓存重新编译
删除CMake生成的build目录所有内容,重新执行CMake生成命令、编译命令,避免旧缓存配置干扰。
如果上述操作后仍有问题,可以用find_package显式导入libssh2目标,让CMake自动处理依赖配置,替换你原来的CMAKE_PREFIX_PATH配置即可:
find_package(Libssh2 REQUIRED PATHS ${CMAKE_CURRENT_SOURCE_DIR}/out/build/x64-Debug/libssh2-1.10.0)
内容的提问来源于stack exchange,提问作者Narase

