GmSSL 编译与 Qt 项目集成问题排查记录(-lssl-1_1-x64 -lcrypto-1_1-x64)

目录

  • [GmSSL 编译与 Qt 项目集成问题排查记录](#GmSSL 编译与 Qt 项目集成问题排查记录)
    • 一、背景
    • 二、环境
    • 三、问题排查与解决步骤
      • [1. 解决 OpenSSL 库文件缺失](#1. 解决 OpenSSL 库文件缺失)
      • [2. 发现项目实际依赖 GmSSL](#2. 发现项目实际依赖 GmSSL)
      • [3. 尝试 GmSSL 3.x 版本](#3. 尝试 GmSSL 3.x 版本)
      • [4. 改用 GmSSL-gmbrowser-v0.1(老版本------重中之重!!!)](#4. 改用 GmSSL-gmbrowser-v0.1(老版本——重中之重!!!))
      • [5. 修复 Perl 配置错误](#5. 修复 Perl 配置错误)
      • [6. 修复 socket 函数参数类型不匹配](#6. 修复 socket 函数参数类型不匹配)
      • [7. 修复 Windows 类型重定义](#7. 修复 Windows 类型重定义)
      • [8. 修复原子操作类型不匹配](#8. 修复原子操作类型不匹配)
      • [9. 修复哈希表函数参数错误](#9. 修复哈希表函数参数错误)
      • [10. 修复测试代码类型错误](#10. 修复测试代码类型错误)
      • [11. 最终编译成功](#11. 最终编译成功)
    • [四、Qt 项目集成](#四、Qt 项目集成)
      • [1. 修改 `.pro` 文件](#1. 修改 .pro 文件)
      • [2. 部署运行时 DLL](#2. 部署运行时 DLL)
      • [3. 重新构建](#3. 重新构建)
    • 五、总结

GmSSL 编译与 Qt 项目集成问题排查记录

一、背景

接手一个 Qt 项目(protolib),该项目使用了国密 SM2 算法,头文件中声明了 SM2_compute_id_digestSM2_do_sign 等函数,并在 .pro 文件中链接了 -lssl-1_1-x64-lcrypto-1_1-x64。项目最初因找不到这些库而导致链接失败,后续又因缺少这些函数的实现而报 undefined reference。

主要问题:

二、环境

  • 操作系统:Windows 10/11
  • Qt 版本:5.13.0 MinGW 64-bit(自带 MinGW 7.3.0)
  • 编译工具链:MSYS2 UCRT64(用于编译 GmSSL)
  • Perl:MSYS2 自带 Perl 5.40
  • GmSSL 版本:
    • 尝试过 GmSSL 3.x(CMake 构建)
    • 最终使用 GmSSL-gmbrowser-v0.1(基于 OpenSSL 1.0.2 风格)

三、问题排查与解决步骤

1. 解决 OpenSSL 库文件缺失

现象 :Qt 项目链接时提示 cannot find -lssl-1_1-x64
原因 :项目要求的库名是带版本号的,而实际安装的 OpenSSL 库名为 libssl.dll.a
解决

  • 使用 MSYS2 安装 OpenSSL 1.1.1,生成文件为 libssl.dll.alibcrypto.dll.a
  • .pro 文件中修改为 -lssl-lcrypto,并添加库路径 -LH:/openssl-install/lib
  • 或将导入库复制并重命名为 libssl-1_1-x64.dll.a

2. 发现项目实际依赖 GmSSL

现象 :链接 OpenSSL 后,仍然出现 undefined reference to SM2_compute_id_digest 等。
原因 :项目中的 sm2.h 文件包含 GmSSL 版权声明,依赖 GmSSL 特有的国密接口,原生 OpenSSL 不提供这些函数。
解决:确认需编译并使用 GmSSL。

3. 尝试 GmSSL 3.x 版本

操作

  • 下载 GmSSL 3.x 源码,使用 CMake 配置编译。
  • 生成 libgmssl.dll.a
    检查nm libgmssl.dll.a | grep SM2_compute_id_digest 无输出,表明未导出所需函数。
    结论:GmSSL 3.x 可能未包含这些特定接口,需改用老版本。

4. 改用 GmSSL-gmbrowser-v0.1(老版本------重中之重!!!)

下载源码解压至 H:/GM0.1/GmSSL-gmbrowser-v0.1

在尝试了诸多版本之后在GMSSL网址的犄角旮旯里找到了第一版的gmssl,当时为什么会觉得是它,因为在它的介绍中出现了SM2的字样,让我 眼前一亮,贴一个网址https://github.com/guanzhi/GmSSL/releases,再附一张图片,以彰显我的坚持不懈和敏锐的嗅觉!

5. 修复 Perl 配置错误

错误 :运行 perl Configure mingw64 --prefix=/h/gmssl-old-install 时,报 "glob" is not exported by the File::Glob module
原因 :老版本 Configure 中使用了 qw/glob/ 导入方式,新版 Perl 要求使用 :bsd_glob
解决 :修改 Configure 文件,将所有 'File::Glob' => qw/glob/ 替换为 'File::Glob' => qw/:bsd_glob/。同样修改 test/build.info 中的类似语句。

6. 修复 socket 函数参数类型不匹配

错误crypto/bio/b_sock2.csetsockoptgetsockopt 的参数类型错误(传递 int* 但需要 char*)。
解决:在调用处添加强制类型转换:

  • setsockopt(..., (const char *)&on, ...)
  • getsockopt(..., (char *)&socktype, ...)

7. 修复 Windows 类型重定义

错误sgd.h 中定义的 BOOLCHAR 等与 Windows 系统头文件冲突。
解决

  • sgd.h 开头添加 #include <windows.h>
  • 修改文件末尾的 Windows 分支(#else),将其中 #ifndef _WINDEF_H 内部的类型定义全部移除,因为这些类型已由 windows.h 提供。

8. 修复原子操作类型不匹配

错误crypto/threads_win.cInterlockedExchangeAdd 需要 long volatile*,但传递的是 int*
解决 :在调用处强制转换为 (long volatile *)val

9. 修复哈希表函数参数错误

错误crypto/objects/o_names.c 中将 OBJ_NAME* 强制转换为 const char* 后传递给哈希表检索/删除函数。
解决 :移除错误强制转换,直接传递 &on

10. 修复测试代码类型错误

错误test/threadstest.cCRYPTO_THREAD_run_once 的参数被错误强制转换为 const char*
解决 :移除强制转换,直接传递 &once_run

11. 最终编译成功

执行 makemake install,生成的头文件和库位于 /h/gmssl-old-install

  • 头文件:include/openssl/sm2.h
  • 库文件:lib/libcrypto.alib/libssl.a(静态库)以及导入库和 DLL。
  • 我的pro文件中明确有-lssl-1_1-x64 -lcrypto-1_1-x64,所以需要把bin目录下的这俩文件复制且加个.a的后缀至lib文件夹下。

四、Qt 项目集成

1. 修改 .pro 文件

qmake 复制代码
INCLUDEPATH += "H:/gmssl-old-install/include"
LIBS += -L"H:/gmssl-old-install/lib" -lssl-1_1-x64 -lcrypto-1_1-x64 -lws2_32

2. 部署运行时 DLL

H:/gmssl-old-install/bin 下的 libcrypto-1_1-x64.dlllibssl-1_1-x64.dll 复制到 Qt 项目的输出目录(如 Debug/)。

3. 重新构建

在 Qt Creator 中执行"清理所有"并重新构建,项目成功生成 protolib.dll

五、总结

本次排查的核心是识别出项目对 GmSSL 老版本的依赖,并通过逐一手动修复老代码与现代工具链的兼容性问题,最终成功编译并集成。主要经验:

  • 老旧开源库在新版编译环境中常会遇到类型严格检查、头文件依赖等问题,需耐心分析错误并针对性修改。
  • 修改源码时尽量保持最小改动,避免引入新问题。
  • 使用 nm 工具检查库中符号可快速验证函数是否导出。

整个过程中共修改了 6 个文件,涉及 Perl 脚本、C 源码和头文件,体现了跨平台开发的细致性。希望这份记录能为后续类似问题提供参考。

相关推荐
RAN11426760086 小时前
1.3第一个程序的介绍
开发语言·qt
blue_ice .7 小时前
Verilog DDS 数字信号发生器:DAC 输出模拟波形与 ADC 回采观测
开发语言·单片机·嵌入式硬件·fpga开发
远翔调光芯片^138287988727 小时前
ECP5702能芯科技PD取电芯片在市场上的优势有哪些?
开发语言·人工智能·单片机·嵌入式硬件·智能家居
泡海椒8 小时前
规则引擎对比:JQuick-Java vs Drools 轻量场景选型对比
java·开发语言
泡泡鱼(敲代码中)8 小时前
Python 容器类型学习笔记:列表、元组、字典、集合
开发语言·笔记·python·pycharm
2501_933670798 小时前
平台招商运营校招能力模型:数据分析、SQL与增长场景拆解
开发语言
菜鸟~noob2339 小时前
【Bonjour】华为Peerium架构深度解析:从冯·诺依曼到百万处理器“一台计算机”,附MATLAB性能仿真【含matlab代码,可直接运行】
开发语言·matlab·华为·peerium
白远山9 小时前
24小时自助健身房系统开发实战:从需求分析到完整指南
java·开发语言·数据库·数据挖掘·需求分析
shmily麻瓜小菜鸡11 小时前
TDD(测试驱动开发)详解
开发语言·javascript·typescript·node.js·ecmascript
三克的油12 小时前
java-学习1
java·开发语言·学习