GmSSL 3.1.1 跨平台静态库编译

GmSSL 3.1.1 跨平台静态库编译:Linux、macOS、Windows(MinGW)一键构建

一、前言

在项目开发过程中,需要使用 GmSSL 提供的国密算法能力,并将其集成到不同操作系统下的应用程序中。为了方便后续进行静态链接,避免依赖 GmSSL 动态库,编写了一个简单的 Shell 脚本,用于在 Linux、macOS 和 Windows(MinGW 环境)下编译生成 GmSSL 静态库。

本文使用的 GmSSL 版本为 v3.1.1,通过 CMake 配置编译选项,根据操作系统自动选择对应的构建工具,并支持多核并行编译。

脚本主要实现以下功能:

  • 支持 Linux、macOS、Windows(MinGW/MSYS)平台。
  • 使用 CMake 配置生成静态库 libgmssl.a。
  • Windows 使用 MinGW Makefiles 生成器和 mingw32-make 编译。
  • 自动检测 CPU 核心数量,进行并行编译。
  • 每次编译前自动清理旧的构建目录,避免不同平台的编译缓存相互影响。

需要注意的是,这里的跨平台指的是同一份脚本可以分别在三个平台的本地环境中运行,并不是在任意一台机器上直接交叉编译出所有平台的静态库。

二、GmSSL 简介

GmSSL 是北京大学开发的国产商用密码开源库,支持多种国密算法、密码标准和安全通信协议。

GitHub 项目地址:

GitHub - guanzhi/GmSSL: 支持国密SM2/SM3/SM4/SM9/SSL的密码工具箱 · GitHub

本文使用版本:

GitHub - guanzhi/GmSSL at v3.1.1 · GitHub

GmSSL 支持的密码算法包括 SM2、SM3、SM4、SM9 等,同时提供 C 语言接口,方便其他语言通过 FFI、CGO、JNI 等方式调用。

GmSSL 3.x 使用 CMake 作为构建系统,可以根据不同操作系统和编译工具生成对应的构建文件。

本文主要编译静态库:

复制代码
libgmssl.a

静态库可以在应用程序链接阶段参与链接,适用于需要减少运行时第三方动态库依赖的场景。

三、编译环境准备

编译前,需要确保各平台已安装 CMake、C 编译器及相应的构建工具。

3.1 Linux

以 Ubuntu/Debian 为例,可以执行:

复制代码
sudo apt update

sudo apt install -y \
    build-essential \
    cmake \
    git

检查安装情况:

复制代码
gcc --version
cmake --version
make --version

其中:

  • gcc:C 语言编译器。
  • cmake:负责生成构建文件。
  • make:负责执行编译任务。

其他 Linux 发行版可通过对应的包管理器安装这些工具。

3.2 macOS

macOS 可以通过 Xcode Command Line Tools 和 Homebrew 安装编译环境。

首先安装命令行开发工具:

复制代码
xcode-select --install

然后安装 CMake:

复制代码
brew install cmake

检查环境:

复制代码
clang --version
cmake --version
make --version

macOS 通常默认使用 Clang 编译器。本文脚本要求 CMake 默认生成器能够使用 make,如环境使用了其他默认生成器,需要对应调整。

3.3 Windows(MinGW)

Windows 平台这里使用 MinGW-w64 编译工具链,而不是 Visual Studio/MSVC 编译器。

可以使用 MSYS2 提供的 MinGW-w64 环境。

MSYS2 官网:

Getting Started - MSYS2

安装 MSYS2 后,建议使用 MSYS2 MinGW x64 终端进行编译。

在对应终端安装所需工具:

复制代码
pacman -S --needed \
    mingw-w64-x86_64-gcc \
    mingw-w64-x86_64-cmake \
    mingw-w64-x86_64-make \
    git

安装完成后检查:

复制代码
gcc --version
cmake --version
mingw32-make --version

需要注意,Windows 环境中可能同时存在 MSYS、MinGW、UCRT 等多种工具链,建议保持 CMake、GCC 和 Make 的运行环境一致,避免编译器或生成器不匹配。

本文使用的 MinGW Makefiles 生成器,需要配套使用 mingw32-make。

四、获取 GmSSL v3.1.1 源码

通过 Git 下载 GmSSL 源码:

复制代码
git clone https://github.com/guanzhi/GmSSL.git
cd GmSSL

切换到 v3.1.1:

复制代码
git checkout v3.1.1

确认当前版本:

复制代码
git describe --tags --exact-match

预期输出:

复制代码
v3.1.1

后续所有编译操作均基于该版本进行。

五、跨平台静态库编译脚本

5.1 完整脚本

在 GmSSL 源码根目录下创建 build-static.sh 文件,内容如下:

复制代码
#!/bin/bash

set -euo pipefail

# 简单的 GmSSL 构建脚本:生成静态库 libgmssl.a

ROOT_DIR="$(cd "$(dirname "$0")" && pwd)"
BUILD_DIR="$ROOT_DIR/build"
UNAME_S="$(uname -s || echo Unknown)"

echo "清理旧的构建目录..."
rm -rf "$BUILD_DIR"

echo "创建构建目录: $BUILD_DIR"
mkdir -p "$BUILD_DIR"
cd "$BUILD_DIR"

echo "检测平台: $UNAME_S"

if [[ "$UNAME_S" == MINGW* || "$UNAME_S" == MSYS* ]]; then
    echo "使用 MinGW Makefiles 构建静态库"

    cmake .. \
        -G "MinGW Makefiles" \
        -DBUILD_SHARED_LIBS=OFF \
        -DCMAKE_BUILD_TYPE=Release
else
    echo "使用默认生成器构建静态库"

    cmake .. \
        -DBUILD_SHARED_LIBS=OFF \
        -DCMAKE_BUILD_TYPE=Release
fi

echo "开始编译..."

if command -v nproc >/dev/null 2>&1; then
    JOBS=$(nproc)
elif [[ "$(uname -s)" == "Darwin" ]]; then
    JOBS=$(sysctl -n hw.ncpu)
else
    JOBS=1
fi

if [[ "$UNAME_S" == MINGW* || "$UNAME_S" == MSYS* ]]; then
    mingw32-make -j"${JOBS}"
else
    make -j"${JOBS}"
fi

echo "构建完成: 静态库应位于 $BUILD_DIR/bin/libgmssl.a"

这里的核心目标是统一编译流程,而不是为每个平台分别维护一套复杂的构建脚本。

5.2 执行脚本

Linux、macOS:

复制代码
chmod +x build-static.sh
./build-static.sh

Windows(MinGW/MSYS Bash 环境):

复制代码
bash build-static.sh

脚本会自动识别当前操作系统,选择对应的构建命令。

注意: 脚本会直接删除源码根目录下已有的 build 文件夹,请确认该目录没有需要保留的文件。

六、脚本实现原理

6.1 严格错误处理

复制代码
set -euo pipefail

这行命令启用了 Bash 的三个常用选项。

选项 作用
-e 命令失败时退出脚本
-u 使用未定义变量时报告错误
-o pipefail 管道中任一命令失败时,使管道返回失败状态

这样可以减少编译失败后脚本继续执行的情况。

需要注意,set -e 在条件判断等语法结构中存在例外,并不意味着任何非零退出状态都会使脚本立即退出。

6.2 获取源码目录

复制代码
ROOT_DIR="$(cd "$(dirname "$0")" && pwd)"
BUILD_DIR="$ROOT_DIR/build"

其中:

  • $0 表示当前脚本的调用路径。
  • dirname "$0" 获取脚本所在目录。
  • pwd 获取绝对路径。
  • BUILD_DIR 指定构建产物存放目录。

通过这种方式,避免使用固定的绝对路径,让脚本能够在不同机器上复用。

6.3 自动识别操作系统

复制代码
UNAME_S="$(uname -s || echo Unknown)"

uname -s 用于获取操作系统名称。

不同平台常见返回值如下:

操作系统 返回值示例
Linux Linux
macOS Darwin
Windows(MinGW) MINGW64_NT-10.0
Windows(MSYS) MSYS_NT-10.0

Windows 环境下,脚本通过以下判断选择构建工具:

复制代码
if [[ "$UNAME_S" == MINGW* || "$UNAME_S" == MSYS* ]]; then

其中的 * 表示通配符,因此可以匹配不同版本的 Windows 系统标识。

需要说明的是,识别出 MSYS 并不代表当前环境必然已经配置好 MinGW 编译器。如果 gcc 或 mingw32-make 不存在,仍需要先配置正确的 MinGW 工具链。

6.4 CMake 配置静态库

脚本中最重要的两个编译选项:

复制代码
-DBUILD_SHARED_LIBS=OFF
-DCMAKE_BUILD_TYPE=Release

BUILD_SHARED_LIBS=OFF 用于控制未显式指定类型的 add_library() 默认创建静态库。

GmSSL v3.1.1 的 CMake 配置中定义了:

复制代码
option(BUILD_SHARED_LIBS "Build using shared libraries" ON)

add_library(gmssl ${src})

因此,关闭 BUILD_SHARED_LIBS 后,gmssl 目标会被构建为静态库。

而 CMAKE_BUILD_TYPE=Release 表示使用 Release 构建配置,通常会启用相应的编译优化。

需要注意,BUILD_SHARED_LIBS=OFF 并不会禁止项目中所有动态库的生成。GmSSL v3.1.1 中还存在显式使用 SHARED 定义的目标,因此该脚本主要保证 gmssl 目标生成静态库,并不是只构建静态库这一个目标。

6.5 Windows 使用 MinGW Makefiles

Windows 分支中使用:

复制代码
cmake .. -G "MinGW Makefiles" \
    -DBUILD_SHARED_LIBS=OFF \
    -DCMAKE_BUILD_TYPE=Release

这里的 -G 用于指定 CMake 生成器。

MinGW Makefiles 会生成适用于 MinGW Make 工具的构建文件,因此后续使用:

复制代码
mingw32-make

而 Linux 和 macOS 分支没有显式指定生成器,使用 CMake 默认生成器,并在后续执行:

复制代码
make

需要特别注意:

在 Windows 上,CMake 生成器必须与当前 Make 工具及编译器环境匹配。

如果使用了 Ninja 或 Visual Studio 等生成器,就不能直接套用本文的 mingw32-make 编译命令。

6.6 自动获取 CPU 核心数

复制代码
if command -v nproc >/dev/null 2>&1; then
    JOBS=$(nproc)
elif [[ "$(uname -s)" == "Darwin" ]]; then
    JOBS=$(sysctl -n hw.ncpu)
else
    JOBS=1
fi

不同系统获取 CPU 核心数量的方法不同。

Linux 通常使用:

复制代码
nproc

macOS 使用:

复制代码
sysctl -n hw.ncpu

如果都不可用,则默认使用一个编译任务。

最后通过:

复制代码
make -j"${JOBS}"

或者:

复制代码
mingw32-make -j"${JOBS}"

实现并行编译,减少构建耗时。

其中 -j 指定同时执行的任务数量。

6.7 静态库输出目录

GmSSL v3.1.1 的 CMakeLists.txt 中定义了:

复制代码
set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)

因此,正常构建后,GmSSL 静态库会生成在:

复制代码
GmSSL/
├── build-static.sh
├── CMakeLists.txt
├── include/
├── src/
└── build/
    └── bin/
        └── libgmssl.a

该路径适用于本文选择的 Makefiles 构建方式。实际目录中还可能存在命令行工具、测试程序及其他构建产物。

七、验证编译结果

编译成功后,可以检查静态库是否存在。

Linux、macOS:

复制代码
ls -lh build/bin/libgmssl.a

Windows(MinGW Bash):

复制代码
ls -lh build/bin/libgmssl.a

也可以使用 ar 查看静态库中的目标文件:

复制代码
ar -t build/bin/libgmssl.a

正常情况下,会列出静态库包含的多个 .o 目标文件。

如果还需要验证 GmSSL 功能,可以执行项目测试:

复制代码
cd build
ctest --output-on-failure

需要注意,静态库文件存在仅表示构建生成了产物,并不能完全证明所有密码算法功能或外部项目链接过程都正常,建议根据实际使用场景进行进一步测试。

八、常见问题

8.1 Windows 提示找不到 mingw32-make

如果出现:

复制代码
mingw32-make: command not found

一般是 MinGW Make 工具未安装,或者工具所在目录没有加入 PATH。

可在 MSYS2 MinGW x64 环境安装:

复制代码
pacman -S mingw-w64-x86_64-make

然后通过以下命令检查:

复制代码
which mingw32-make

确认可以找到对应的可执行文件。

8.2 CMake 提示生成器不匹配

例如:

复制代码
Error: generator ... does not match the generator used previously

通常是同一个构建目录之前使用了其他生成器。

本文脚本在执行 CMake 之前会删除旧的 build 目录,因此可以避免大部分此类问题。

8.3 设置 BUILD_SHARED_LIBS=OFF 后仍有动态库

这是因为该选项只影响没有显式指定库类型的 add_library()。

如果项目使用:

复制代码
add_library(example SHARED ...)

该目标仍然按照动态库进行构建。

对于 GmSSL v3.1.1,gmssl 目标使用:

复制代码
add_library(gmssl ${src})

因此可以通过 BUILD_SHARED_LIBS=OFF 将其构建为静态库。

8.4 Windows 静态库能否直接在 Linux 或 macOS 使用?

不能直接通用。

虽然三个平台可能都生成名为 libgmssl.a 的文件,但不同平台的目标文件格式、ABI、工具链以及系统依赖存在差异。

例如:

  • Linux 通常使用 ELF 对象文件。
  • macOS 使用 Mach-O 对象文件。
  • Windows MinGW 使用 COFF/PE 体系下的对象文件。

因此,需要在目标平台上分别编译生成对应的静态库。

另外,Windows 下使用 MinGW 编译生成的 .a 静态库,也不能保证直接兼容 MSVC 工具链。

8.5 静态链接后是否就不需要其他依赖?

不一定。

静态链接 GmSSL 可以减少对 GmSSL 共享库的运行时依赖,但仍可能需要链接操作系统提供的其他库。

例如,Windows 下使用 GmSSL 的网络相关功能时,可能需要链接:

复制代码
ws2_32

macOS 下则可能涉及 Security 等系统框架。

最终需要根据目标程序调用的接口和链接工具链确定依赖。

九、总结

本文通过一个简单的 Shell 脚本,实现了 GmSSL v3.1.1 在 Linux、macOS 和 Windows(MinGW)环境下的静态库构建。

整体思路是:

  1. 使用 CMake 统一项目配置。
  2. 设置 BUILD_SHARED_LIBS=OFF,构建 libgmssl.a。
  3. 根据平台选择 Make 工具。
  4. 自动检测 CPU 核心数,实现并行编译。
  5. 清理旧目录,避免构建缓存冲突。

这种方式比较适合需要在多个操作系统下维护 GmSSL 依赖的项目,也方便后续将静态库集成到 C/C++、Go CGO 或其他需要原生密码库的应用中。

参考资料:

相关推荐
安当加密-焱垚2 天前
静态脱敏系统解决方案
国密·数据脱敏·静态脱敏系统解决方案·静态脱敏系统访问控制·静态脱敏系统防勒索方案
安当加密-焱垚6 天前
轻量级证书签发系统如何集成
国密·轻量级证书签发系统如何集成·轻量级证书签发系统成本分析·轻量级证书签发系统技术趋势分析
安当加密-焱垚8 天前
统一身份认证系统常见问题解答
国密·统一身份认证系统常见问题解答·统一身份认证系统性能对比·统一身份认证系统技术趋势分析
安当加密-焱垚13 天前
静态脱敏系统身份认证方案
国密·静态脱敏系统身份认证方案·合规审计中如何应用静态脱敏系统·登录认证中如何应用静态脱敏系统·身份认证中如何应用静态脱敏系统
安当加密03012 个月前
IEC62351与GB/Z 25320合规解读:电力通信安全与能源局工控安全如何满足
国密·工控安全·iec62351·gb/z 25320·电力通信安全
安当加密03012 个月前
政务OA国密改造:电子公文SM2签名与UKEY认证合规路径
国密·sm2签名·ukey·政务oa·电子公文
安当加密03012 个月前
电力纵向加密认证与调度数据网隔离实战:从接入防护到隔离装置选型
国密·电力监控系统·纵向加密认证·隔离装置·调度数据网
安当加密03012 个月前
政务云密码应用与密评合规:四层面产品全景图与落地路径
国密·政务云·密评·密码应用·四层面
qinwsq2 个月前
Gmssl windows下编译
windows·gmssl