时间轴
时间轴
2025-12-29
init
本文介绍了在x86_64主机上使用ARM交叉工具链编译OpenSSL 1.0.0s的aarch64共享库的完整流程,包括环境准备、Configure配置(需使用linux-aarch64 target并通过环境变量CROSS_COMPILE指定工具链前缀)、修改三个Makefile中的ARFLAGS和AR定义以解决瘦归档和参数顺序问题,以及编译、安装和常见问题排查方法。
目标:在 x86_64 主机上,使用aarch64-none-linux-gnu-交叉工具链, 编译出libssl.so和libcrypto.so(ARM aarch64 共享库)。
1. 环境准备
1.1 源码
1 | cd ~/repository |
1.2 交叉工具链
本文使用 Arm GNU Toolchain 11.2-2022.02(aarch64-none-linux-gnu-三元组)。
ARM目前总共发布了8种架构:ARMv1、ARMv2、ARMv3、ARMv4、ARMv5、ARMv6、ARMv7、ARMv8。
针对于支持ARMv8指令集的处理器可以使用-march=armv8-a参数编译代码,ARM GNU编译器可通过下面的链接下载
推荐使用ARM官网的编译器,它是Portable的,解压后即可使用。
本文使用的是11.2版本的交叉编译器
可以将其添加到环境变量
1 | # ~/.bashrc或~/.bash_profile |
使用11.2.1版本的aarch64-none-linux-gnu-gcc

如果工具链三元组是
aarch64-linux-gnu-(如 Ubuntu 的gcc-aarch64-linux-gnu包),把下面所有aarch64-none-linux-gnu-替换成aarch64-linux-gnu-即可。
2. 配置(Configure)
OpenSSL 1.0.0 没有linux-aarch64这个 target(即使命令行能选上,也会 fall back 到 host 的cc,产物是 x86_64)。
正确做法是使用通用 64-bit targetlinux-generic64,并通过环境变量CROSS_COMPILE指定工具链前缀。
1 | export CROSS_COMPILE=aarch64-none-linux-gnu- |
⚠️ 重要:
CROSS_COMPILE必须用 环境变量 传入。
如果写成./Configure ... CROSS_COMPILE=...命令行参数,
OpenSSL 1.0.0 的 Configure 脚本会报:target already defined - linux-generic64 (offending arg: CROSS_COMPILE=...)
配置完成后,检查Makefile确认交叉编译生效:
1 | grep -E '^(CC|CROSS_COMPILE|AR)=' Makefile |
期望输出:
1 | CROSS_COMPILE= aarch64-none-linux-gnu- |
如果CC= cc(没有前缀),说明交叉编译没生效,需要重新 Configure。
2.1 Configure 参数说明
./Configure的完整参数含义:
| 参数 | 类型 | 说明 |
|---|---|---|
linux-generic64 | target | 通用 64-bit Linux 平台。OpenSSL 1.0.0 没有linux-aarch64目标,必须用这个 |
shared | 选项 | 同时构建共享库(.so)。不加的话只生成静态库(.a) |
--prefix=$PWD/install | 路径 | make install时的安装根目录(头文件、库、证书等) |
--openssldir=$PWD/install/ssl | 路径 | OpenSSL 运行时查找证书/配置文件的默认目录 |
no-idea | 禁用算法 | IDEA 对称加密。专利算法(专利已过期,但旧版 OpenSSL 默认不编译),不写会报idea.h: No such file |
no-md2 | 禁用算法 | MD2 哈希。已被证明极度不安全(1998 年即被碰撞),没必要保留 |
no-mdc2 | 禁用算法 | MDC2 哈希。老旧算法,极少使用 |
no-rc5 | 禁用算法 | RC5 对称加密。专利算法(已过期),默认不编译 |
no-ssl2 | 禁用协议 | SSL 2.0。已废弃且不安全(受 POODLE 等攻击,RFC 6176 废弃) |
no-ssl3 | 禁用协议 | SSL 3.0。已废弃且不安全(受 POODLE 攻击,RFC 7568 废弃) |
-DOPENSSL_NO_HEARTBEATS | 编译宏 | 禁用 TLS Heartbeat 扩展。Heartbleed 漏洞(CVE-2014-0160)的根源 |
关于no-xxx(禁用算法/协议)
OpenSSL 的./Configure接受no-<feature>在编译时剔除不需要的算法,作用:
- 减小体积:禁用的算法不会编译进
.so,库文件更小 - 规避专利:IDEA、RC5 曾是专利算法(已过期,但旧版本仍需显式启用)
- 消除安全风险:MD2/SSL2/SSL3 已被证明不安全,没必要保留
建议:如果不确定需要哪些算法,全加上是最安全的——能显著减小编译产物体积,并消除已知的安全风险算法。
如果你的项目确实需要某个算法(比如必须支持 SSL3 的 legacy 设备),去掉对应的
no-xxx即可。
关于-DOPENSSL_NO_HEARTBEATS(编译宏)
OpenSSL 1.0.0 本身不支持 Heartbeat(Heartbeat 是 1.0.1 引入的),所以这个宏在 1.0.0 上是冗余的。
但写上无害,且如果哪天换到 1.0.1+ 版本就能自动防 Heartbleed。
最简配置(不禁用任何算法)
如果你不想禁用任何算法,可以把这行:
1 | ./Configure linux-generic64 shared \ |
简化为:
1 | ./Configure linux-generic64 shared \ |
Configure 会自动尝试编译所有算法,遇到编译失败的会跳过。只有在你需要减小体积或明确禁用某些算法时才加no-xxx。
3. 修改 Makefile(关键修复)
Configure生成的Makefile里,ARFLAGS默认是空的,且AR的定义顺序有问题:
1 | ARFLAGS= # ← 空 |
两个问题叠加导致构建失败:
- 瘦归档问题:某些版本的交叉工具链(包括本文用的 Arm GNU Toolchain 11.2)的
ar在ARFLAGS为空时,默认创建瘦归档(thin archive)——归档里只存符号表,不内嵌.o文件内容。链接时ld读取成员会失败:
1 | ld: libcrypto.a: member libcrypto.a(cryptlib.o) in archive is not an object |
- AR 参数顺序问题:
ar的语法是ar [-]X[MOPTS] archive [members],操作符(r)必须紧挨着ar或放在MOPTS前面。错误的顺序ar rc r会让ar把最后的r当成归档文件名。
修复:把ARFLAGS改成c(create),并把AR定义里的r和ARFLAGS顺序互换。
⚠️ 重要:OpenSSL 1.0.0 有 3 个 Makefile 需要改(顶层、
crypto/、ssl/), 因为crypto/Makefile和ssl/Makefile各自有独立的AR定义, 且**硬编码了 **ar r(没有$(CROSS_COMPILE)前缀)。 顶层 Makefile 通过make -e传AR环境变量,但子 Makefile 里的AR定义优先级更高。
1 | # 顶层 Makefile |
改完验证:
1 | grep -E '^ARFLAGS|^AR=' Makefile crypto/Makefile ssl/Makefile |
期望输出:
1 | Makefile: ARFLAGS=c |
展开后实际调用:aarch64-none-linux-gnu-ar rc ../../libcrypto.a *.o—— 正确的胖归档格式。
原理
ar命令的 mode 字母含义:r:替换/插入成员(operation)c:创建归档(如果不存在)(modifier)s:写入符号索引(等同于单独跑ranlib)
GNU ar 的语法:
ar [-]X[MOPTS] archive [members]X = operation(r/d/m/p/q/t/x)
MOPTS = modifiers(c/v/w/…)
错误的ar $(ARFLAGS) r(当 ARFLAGS=c 时变成ar c r)会让ar把r当归档名。 正确写法是ar r$(ARFLAGS)→ar rc。
4. 编译(直接 make)
1 | make depend # 必须先跑,因为 ./Configure 改过算法开关 |
编译完成后会得到:
1 | libcrypto.so -> libcrypto.so.1.0.0 (符号链接) |
5. 验证产物
1 | # 文件类型 |
6. 安装
1 | export INSTALLDIR=$HOME/repository/openssl-1.0.0s/_install |
最终目录结构:
1 | _install |
7. 一键脚本
把下面内容保存为build-openssl-aarch64.sh,放在openssl-1.0.0s/同级目录:
1 |
|
1 | chmod +x build-openssl-aarch64.sh |
8. 常见问题排查
| 现象 | 原因 | 修复 |
|---|---|---|
Configure: target already defined | CROSS_COMPILE写成了命令行参数 | 改用export CROSS_COMPILE=...环境变量 |
CC= cc(无前缀) | 用了linux-aarch64等不存在的 target | 改用linux-generic64 |
ld: member ... in archive is not an object | 交叉 ar 生成瘦归档 | 改 3 个 Makefile 的 ARFLAGS/AR(见第 3 节) |
ar: two different operation options specified | ARFLAGS 包含了r(与 AR 定义里的r重复) | ARFLAGS 应该只是c,不能是rc |
ar: creating r或ar: r: No such file | AR 参数顺序错误(ar $(ARFLAGS) r) | sed -i 's/AR=...ar $(ARFLAGS) r$/AR=...ar r$(ARFLAGS)/' Makefile |
| 改了顶层 Makefile 但归档还是瘦归档 | crypto/Makefile和ssl/Makefile有独立的 AR 定义 | 同时改 3 个 Makefile |
.so只有几 KB | 链接时缺--whole-archive(极少见,Makefile 内置了) | 检查 Makefile.shared 的ALLSYMSFLAGS |
编译报openssl/idea.h: No such file | 没加no-idea | Configure 时加no-idea no-mdc2 no-rc5 |
make clean报rm -f install/lib | install/目录已存在且非空 | 手动rm -rf install或忽略该错误 |
9. 总结:四步出 .so
1 | # 1. 配置 |