ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

VS2017 编译 64 位 libssh2 链接错误解决指南

VS2017 编译 64 位 libssh2 链接错误解决指南 简介本资源面向需要在Windows 64位环境下使用SSH2协议进行安全远程连接开发的C/C工程师提供已用VS2017编译完成的libssh2库文件省去自行搭建编译环境的繁琐过程。压缩包共115个文件以109个h头文件为主另含3个lib静态库、2个dll动态库及1个cpp示例文件整体约2.14MB头文件覆盖libssh2与OpenSSL相关接口声明库文件可直接用于链接。资源标签涉及libssh2与windows平台适合从事远程文件传输、shell访问等开发场景的中高级开发者。已有1513人学习下载读者可快速将libssh2.lib与头文件目录接入VS2017项目完成链接器与包含路径配置避免依赖OpenSSL编译与CMake生成环节的常见坑同时借助示例文件理解调用方式提升集成效率。1. 为什么 VS2017 编译 64 位 libssh2 总在链接阶段翻车在 Windows 上做 C/C 开发一旦涉及 SSH 会话、SFTP 上传下载或者端口转发libssh2 几乎是绕不开的底层库。但很多人在 VS2017 里编译 64 位 libssh2 时都会遇到同一个现象编译能过链接报错满屏的unresolved external symbol或者运行期直接崩溃在libssh2_session_handshake。这不是玄学而是 64 位目标下库依赖链、运行库选项和 OpenSSL 版本三者没有对齐导致的。这篇文章面向的是需要在 VS2017 工程里集成 64 位 libssh2 的 Windows 开发者尤其是做工业采集、设备管理、自动化运维工具的同学。我会把从源码准备、依赖编译、VS2017 工程配置到最终链接验证的完整路径拆开每一步都给出可复现的命令和参数说明。你不需要提前装好 CMake 或 Perl但需要有一台能正常跑 VS2017 的 64 位 Windows 机器以及足够的耐心处理 OpenSSL 这个最大的变量。2. 编译前的依赖链梳理与源码准备2.1 libssh2 在 64 位 Windows 下的依赖关系libssh2 本身是纯 C 库但它默认依赖加密后端。在 Windows 上最稳的组合是 OpenSSL而不是 WinCNG 或 mbedTLS。原因很直接VS2017 时代大量现成的 64 位第三方库都是基于 OpenSSL 1.0.2 或 1.1.0 编译的WinCNG 虽然系统自带但 API 行为在不同 Windows 版本上有差异调试成本高。依赖链是这样的libssh2 调用 OpenSSL 的 libcrypto 和 libsslOpenSSL 又依赖 Windows 的 Crypt32 和 WS2_32。如果你在 VS2017 里只加了 libssh2 的 lib 文件链接器会依次报缺SSL_CTX_new、EVP_DigestInit_ex这类符号。所以第一步不是急着编译 libssh2而是先把 64 位 OpenSSL 准备好。常见做法是直接用 OpenSSL 官方源码自己编或者用已经编好的 64 位静态库。我一般会自己编因为这样能控制运行库选项/MT 还是 /MD避免和主工程冲突。2.2 获取 libssh2 源码与目录规划libssh2 的源码可以从官方仓库或发布页获取这里不写具体外链。下载后解压目录结构里关键的是src、include、win32三个文件夹。win32目录下虽然有 VS 工程文件但那些工程默认是 32 位的直接改成 64 位会踩坑所以更推荐用 CMake 生成 VS2017 解决方案。我习惯把目录规划成下面这样避免路径里出现空格和中文D:\dev\ ├── openssl-1.1.1\ │ ├── include\ │ └── lib\ ├── libssh2-1.10.0\ │ ├── src\ │ ├── include\ │ └── win32\ └── build\ ├── openssl\ └── libssh2\路径里不要有空格否则 CMake 生成 VS2017 工程时某些自定义命令会解析失败。另外源码版本建议选 1.9.0 或 1.10.0这两个版本对 VS2017 的兼容性最好再新的版本可能要求 C11 特性VS2017 的 MSVC 对 C11 支持不完整。2.3 用 CMake 生成 VS2017 64 位解决方案先确认 CMake 版本不低于 3.10然后在 build 目录下执行cd D:\dev\build\libssh2 cmake -G Visual Studio 15 2017 Win64 ^ -DCMAKE_BUILD_TYPERelease ^ -DOPENSSL_ROOT_DIRD:/dev/openssl-1.1.1 ^ -DOPENSSL_INCLUDE_DIRD:/dev/openssl-1.1.1/include ^ -DOPENSSL_CRYPTO_LIBRARYD:/dev/openssl-1.1.1/lib/libcrypto.lib ^ -DOPENSSL_SSL_LIBRARYD:/dev/openssl-1.1.1/lib/libssl.lib ^ -DCRYPTO_BACKENDOpenSSL ^ -DBUILD_SHARED_LIBSOFF ^ -DCMAKE_INSTALL_PREFIXD:/dev/libssh2-install ^ D:/dev/libssh2-1.10.0这里几个参数需要重点说明。-G Visual Studio 15 2017 Win64直接锁定 64 位生成器不要用默认的 Win32。-DCRYPTO_BACKENDOpenSSL强制走 OpenSSL 后端避免 CMake 自动探测到 WinCNG。-DBUILD_SHARED_LIBSOFF生成静态库方便直接嵌到主工程里省去 DLL 部署的麻烦。-DCMAKE_INSTALL_PREFIX指定安装目录编译完执行cmake --build . --config Release --target INSTALL就能把头文件和 lib 归集到一处。如果 CMake 报找不到 OpenSSL优先检查OPENSSL_ROOT_DIR是否指向了包含 include 和 lib 的父目录而不是 lib 目录本身。这个路径层级问题在 VS2017 下特别常见。3. 在 VS2017 里编译 64 位 libssh2 的完整操作3.1 用 CMake 生成工程后的编译命令CMake 生成成功后build 目录下会出现libssh2.sln。你可以直接用 VS2017 打开也可以走命令行编译。命令行更可控适合反复构建cd D:\dev\build\libssh2 cmake --build . --config Release --target libssh2 cmake --build . --config Release --target INSTALL第一条命令只编译 libssh2 库本身第二条把产物安装到CMAKE_INSTALL_PREFIX指定的目录。编译完成后在安装目录下应该能看到include\libssh2.h、include\libssh2_sftp.h和lib\libssh2.lib。如果lib目录下出现的是libssh2_static.lib或带d后缀的调试库说明配置和预期有偏差需要回看 CMake 参数。这里有个细节VS2017 的 MSVC 在编译 libssh2 的session.c时可能报C4996警告提示strncpy不安全。这不是错误但如果你开了/WX警告视为错误编译会中断。解决办法是在 CMake 参数里加-DCMAKE_C_FLAGS/wd4996或者在 VS2017 工程属性里把SDL 检查关掉。3.2 主工程中配置头文件路径与库目录假设你有一个自己的 VS2017 工程需要链接 libssh2。右键工程 → 属性确保平台是x64然后依次配置C/C → 常规 → 附加包含目录加入D:\dev\libssh2-install\include和D:\dev\openssl-1.1.1\include链接器 → 常规 → 附加库目录加入D:\dev\libssh2-install\lib和D:\dev\openssl-1.1.1\lib链接器 → 输入 → 附加依赖项加入libssh2.lib、libssl.lib、libcrypto.lib、ws2_32.lib、crypt32.lib注意顺序libssh2.lib放在最前面libssl.lib和libcrypto.lib紧随其后。链接器是从左到右解析符号的如果 libssh2 在前面而 OpenSSL 在后面符号能正常解析反过来则可能报缺 libssh2 内部的符号。还有一个容易忽略的点运行库选项。libssh2 和 OpenSSL 编译时用的运行库必须和主工程一致。如果你编 OpenSSL 时用了/MT主工程也必须用/MT否则会出现LNK2038运行库不匹配的错误。在 VS2017 里这个选项在C/C → 代码生成 → 运行库Release 下通常选/MT或/MD取决于你的部署方式。3.3 验证链接是否成功的三个检查点配置完成后不要急着跑完整业务代码先写一个最小验证程序#include libssh2.h #include stdio.h int main() { int rc libssh2_init(0); if (rc ! 0) { printf(libssh2_init failed: %d\n, rc); return 1; } printf(libssh2 version: %s\n, libssh2_version(0)); libssh2_exit(); return 0; }编译这个程序时如果链接通过并且运行输出类似libssh2 version: 1.10.0说明 64 位库已经正确集成。如果运行时报缺 DLL检查是否误用了动态库版本如果输出为空或崩溃检查 OpenSSL 的 libcrypto 是否被正确链接。第二个检查点是看生成的 exe 是不是 64 位。用dumpbin /headers your.exe | findstr machine输出应该是x64。第三个检查点是用dumpbin /dependents your.exe看依赖的 DLL 列表确认没有混入 32 位的 OpenSSL DLL。4. 避坑64 位 libssh2 编译中最容易踩的五个问题4.1 链接报错 unresolved external symbol SSL_CTX_new现象编译通过链接时满屏unresolved external symbol符号名以SSL_或EVP_开头。原因OpenSSL 的 libcrypto.lib 和 libssl.lib 没有加入附加依赖项或者加入的是 32 位版本。VS2017 在 x64 平台下不会自动区分 32 位和 64 位 lib只要路径对就尝试链接但符号修饰不同最终解析失败。解决用dumpbin /headers libcrypto.lib | findstr machine确认库是 x64。然后在链接器输入里显式加入libssl.lib和libcrypto.lib并确保库目录指向 64 位版本。4.2 CMake 生成的是 Win32 工程而不是 x64现象用 CMake 生成 sln 后VS2017 打开发现解决方案平台只有 Win32没有 x64。原因-G参数写成了Visual Studio 15 2017而没有加Win64后缀。CMake 默认生成 32 位工程。解决删掉 build 目录下的 CMakeCache.txt重新执行带Win64的生成命令。如果已经生成了 Win32 工程也可以在 VS2017 的配置管理器里新建 x64 平台但这样容易遗漏某些项目的平台设置不如重新生成干净。4.3 运行期崩溃在 libssh2_session_handshake现象编译链接都正常调用libssh2_session_handshake时程序直接崩溃没有明确错误码。原因OpenSSL 初始化没有做或者 libssh2 和 OpenSSL 的运行库选项不一致导致堆内存管理冲突。在 64 位下指针宽度变化会让这类问题更容易暴露。解决在调用 libssh2 之前确保 OpenSSL 1.1.0 及以上版本已经自动初始化1.1.0 之后不需要手动调SSL_library_init。如果是 1.0.2 版本需要手动调用SSL_library_init()和OpenSSL_add_all_algorithms()。另外用dumpbin /directives检查两个 lib 的/MT或/MD标记是否一致。4.4 编译 libssh2 时提示找不到 libssh2_config.h现象在 VS2017 里直接打开win32目录下的工程文件编译报找不到libssh2_config.h。原因win32目录下的工程是给旧版 VS 用的没有包含 CMake 生成的配置头文件。这个头文件是在 CMake 配置阶段根据你的系统环境生成的不在源码根目录里。解决不要用win32目录下的现成工程改用 CMake 生成。如果必须用需要手动把 build 目录下生成的libssh2_config.h复制到src目录并确保包含路径正确。4.5 静态库链接后主工程体积暴涨或符号冲突现象链接 libssh2 静态库后exe 体积增加了几 MB或者报LNK2005符号重复定义。原因libssh2 静态库把 OpenSSL 的部分符号也打包进来了而主工程可能通过其他库间接链接了 OpenSSL导致同一符号出现两次。解决优先使用动态库版本的 libssh2 和 OpenSSL把 DLL 随 exe 一起部署。如果必须静态链接用/FORCE:MULTIPLE强制忽略重复符号但这只是掩盖问题。更彻底的办法是统一整个工程的 OpenSSL 版本只保留一份 libcrypto 和 libssl。5. 进阶用 dumpbin 和依赖查看器做最终验证编译完成只是第一步真正要确认 64 位 libssh2 能在目标机器上稳定跑还得做依赖验证。我一般会用两个工具dumpbin和 Dependencies或者 Dependency Walker 的替代品。dumpbin是 VS2017 自带的命令行就能用dumpbin /headers D:\dev\libssh2-install\lib\libssh2.lib | findstr machine dumpbin /dependents YourApp.exe第一条确认 lib 本身是 x64第二条看 exe 依赖的 DLL 列表。如果列表里出现libcrypto-1_1-x64.dll和libssl-1_1-x64.dll说明动态链接配置正确。如果出现的是不带x64的版本说明链接到了 32 位库需要回退检查库目录。还有一个容易被忽略的验证点在 Windows 7 64 位系统上跑。VS2017 默认生成的 exe 可能依赖api-ms-win-crt-runtime-l1-1-0.dll这个在未打补丁的 Win7 上不存在。解决办法是在工程属性里把C/C → 代码生成 → 运行库改成/MT静态链接 CRT或者把 VC 运行库随安装包一起部署。我自己的习惯是每次编完 libssh2先跑一遍最小验证程序再用dumpbin确认平台和依赖最后在一台干净的 Win7 64 位虚拟机上做冒烟测试。这套流程走下来基本能拦住 90% 的集成问题。希望帮到你。本文还有配套的精品资源点击获取
返回列表