Linux下MinGW交叉编译WinXP 32位OpenSSL应用报错排查
问题根因
之前的操作存在几处核心错误,直接导致编译失败:
- 首次编译OpenSSL调用原生
./config脚本,该脚本默认检测当前Linux主机环境,编译生成的是Linux平台ELF格式的.so动态库,完全无法用于Windows程序交叉编译。同时命令里重复传入了两次配置参数,--prefix路径错误指向了编译器二进制文件位置,编译应用时也没有添加OpenSSL头文件搜索路径,因此触发找不到openssl/ssl.h的报错。 - 第二次编译OpenSSL虽然指定了MinGW目标平台,但编译完成后没有执行
make install步骤,源码目录内的include文件夹是未完成安装处理的原始头文件集合,applink.c这类平台适配文件只有执行安装步骤后才会被拷贝到对应include目录。同时编译应用时没有链接OpenSSL的库文件,即使头文件找到也会出现链接错误。 - 版本选择存在潜在兼容问题:OpenSSL 1.1.1分支从1.1.1d之后默认开启了高版本Windows系统API依赖,如果不加对应编译参数指定目标系统版本,编译出的程序在WinXP下会报系统入口点不存在的错误。OpenSSL 3.0及以上版本已经完全放弃WinXP支持,无法使用。
正确操作步骤
第一步:校验交叉编译工具链
先确认已安装的i686 MinGW工具链符合要求,执行以下命令:
i686-w64-mingw32-gcc -v
检查输出内容中Thread model字段为posix,如果是win32线程模型需要重新安装posix版本的MinGW,否则OpenSSL多线程相关功能会编译失败。
第二步:交叉编译适配WinXP 32位的OpenSSL库
不要在OpenSSL源码目录内直接存放编译产物,单独创建目录存放最终安装的头文件和库,依次执行以下命令:
# 进入解压后的OpenSSL 1.1.1w源码目录,该版本是1.1.1分支最终维护版,对WinXP兼容性最好 cd openssl-1.1.1w # 清理之前的编译残留 make clean # 创建独立的安装目录 mkdir -p ../openssl-win32-xp # 配置编译参数,指定目标平台、启用的TLS版本、关闭不需要的组件、指定WinXP兼容 ./Configure mingw \ enable-tls1_2 enable-tls1_3 \ no-asm no-async no-dso no-engine no-shared \ -D_WIN32_WINNT=0x0501 \ --cross-compile-prefix=i686-w64-mingw32- \ --prefix=$(pwd)/../openssl-win32-xp # 编译,并行数不要过高,避免OpenSSL依赖顺序错误导致编译失败 make -j4 # 安装编译产物到指定目录,这一步会生成完整可用的头文件、静态库 make install cd ..
安装完成后,openssl-win32-xp目录下会生成include(存放所有OpenSSL头文件,包含需要的applink.c)、lib(存放静态库libssl.a、libcrypto.a)两个子目录,这才是可以用于交叉编译的开发文件。
第三步:修正测试代码问题
原有测试代码存在几处需要修改的点:
- 删除
#include <openssl/applink.c>行,该文件仅在使用MSVC编译器编译时需要包含,MinGW环境下包含会触发重复定义错误。 - 修正端口号:代码中写的连接端口为449,标准HTTPS服务端口为443,测试时需要和目标服务端口保持一致,否则无法建立连接。
- 补充错误判断:socket连接失败返回INVALID_SOCKET时直接终止流程,不要把无效socket传给OpenSSL层导致程序崩溃。
第四步:编译最终应用
执行以下命令编译应用,指定头文件、库文件搜索路径,链接所有依赖库:
i686-w64-mingw32-gcc main.c -o main.exe \ -I./openssl-win32-xp/include \ -L./openssl-win32-xp/lib \ -lssl -lcrypto -lws2_32 -lgdi32 -lcrypt32 \ -static -mthreads \ -D_WIN32_WINNT=0x0501
命令中-D_WIN32_WINNT=0x0501宏指定目标系统为Windows XP,-static参数开启静态链接,编译出的exe不需要依赖额外的DLL文件,直接拷贝到WinXP 32位系统即可运行。
补充说明
- 如果需要编译动态库版本,删除Configure参数中的
no-shared选项即可,编译安装后会在bin目录下生成libssl-1_1.dll、libcrypto-1_1.dll,编译应用时去掉-static参数,运行时将两个DLL和exe放在同一目录即可。 - TLS 1.3在OpenSSL 1.1.1版本中为原生支持特性,不需要额外打补丁,编译时加上
enable-tls1_3参数即可启用。 - 如果编译时出现高版本系统API找不到的报错,优先检查是否所有编译步骤都加了
-D_WIN32_WINNT=0x0501宏定义,该宏会告知Windows头文件仅导出WinXP支持的API接口。
内容的提问来源于stack exchange,提问作者Dimitrios Desyllas
相关产品推荐
相关产品推荐

