OpenSSL 1.0.0s aarch64交叉编译

字数 3.1k
阅读
访客

时间轴

时间轴

2026-07-16

init

本文介绍了在x86_64主机上使用Arm GNU Toolchain 11.2交叉编译OpenSSL 1.0.0s,生成aarch64共享库(.so)的完整流程。文章首先说明了环境准备,包括源码选择与交叉工具链配置,并指出OpenSSL 1.0.0没有专门的aarch64 target,必须使用通用64位target并通过环境变量指定工具链前缀。随后详细解析了Configure参数,包括禁用IDEA、MD2、MDC2、RC5算法及SSL 2.0/3.0协议,并解释了相关安全考量。文章重点解决了构建中的关键问题:由于交叉工具链的ar在ARFLAGS为空时默认创建瘦归档,且AR参数顺序错误,导致链接失败,需同时修改顶层、Makefile和Makefile.shared三个Makefile中的ARFLAGS与AR定义。最后总结了编译、验证、安装步骤,并提供了常见问题排查表。本文为在ARM64平台

目标:在 x86_64 主机上,使用aarch64-none-linux-gnu-交叉工具链,编译出libssl.solibcrypto.so(ARM aarch64 共享库)。

1. 环境准备

1.1 源码

123456
cd ~/repositorywget https://github.com/openssl/openssl/releases/download/OpenSSL_1_0_0s/openssl-1.0.0s.tar.gztar xvf openssl-1.0.0s.tar.gz        # 如果尚未解压cd openssl-1.0.0s

如果不是必须要用 OpenSSL 1.0.0,OpenSSL 1.1.1 这个版本更推荐使用,不仅代码更健壮,编译也更简单。

123
./Configure linux-aarch64 --cross-compile-prefix=aarch64-none-linux- --prefix=$PWD/_install sharedmake -j$(nproc)

1.2 交叉工具链

本文使用 Arm GNU Toolchain 11.2-2022.02aarch64-none-linux-gnu-三元组)。

ARM目前总共发布了8种架构:ARMv1、ARMv2、ARMv3、ARMv4、ARMv5、ARMv6、ARMv7、ARMv8。

针对支持ARMv8指令集的处理器可以使用-march=armv8-a参数编译代码,ARM GNU编译器可通过下面的链接下载

推荐使用ARM官网的编译器,它是Portable的,解压后即可使用。

本文使用的是11.2版本的交叉编译器

可以将其添加到环境变量

123
# ~/.bashrc或~/.bash_profileemacs ~/.bashrcexport PATH="$HOME/tools/gcc-arm-11.2-2022.02-x86_64-aarch64-none-linux-gnu/bin:$PATH"

使用11.2.1版本的aarch64-none-linux-gnu-gcc

aarch64-none-linux-gnu-gcc
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指定工具链前缀。

1234567
export CROSS_COMPILE=aarch64-none-linux-gnu-./Configure linux-generic64 shared \  --prefix=$PWD/_install \  --openssldir=$PWD/_install/ssl \  no-idea no-md2 no-mdc2 no-rc5 no-ssl2 no-ssl3 \  -DOPENSSL_NO_HEARTBEATS

⚠️ 重要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

期望输出:

123
CROSS_COMPILE= aarch64-none-linux-gnu-CC= $(CROSS_COMPILE)gccAR= $(CROSS_COMPILE)ar $(ARFLAGS) r

如果CC= cc(没有前缀),说明交叉编译没生效,需要重新 Configure。

2.1 Configure 参数说明

./Configure的完整参数含义:

参数类型说明
linux-generic64target通用 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。

最简配置(不禁用任何算法)

如果你不想禁用任何算法,可以把这行:

12345
./Configure linux-generic64 shared \  --prefix=$PWD/_install \  --openssldir=$PWD/_install/ssl \  no-idea no-md2 no-mdc2 no-rc5 no-ssl2 no-ssl3 \  -DOPENSSL_NO_HEARTBEATS

简化为:

123
./Configure linux-generic64 shared \  --prefix=$PWD/_install \  --openssldir=$PWD/_install/ssl

Configure 会自动尝试编译所有算法,遇到编译失败的会跳过。只有在你需要减小体积明确禁用某些算法时才加no-xxx


3. 修改 Makefile(关键修复)

Configure生成的Makefile里,ARFLAGS默认是空的,且AR的定义顺序有问题:

12
ARFLAGS=                  # ← 空AR= $(CROSS_COMPILE)ar $(ARFLAGS) r

两个问题叠加导致构建失败

  1. 瘦归档问题:某些版本的交叉工具链(包括本文用的 Arm GNU Toolchain 11.2)的arARFLAGS为空时,默认创建瘦归档(thin archive)——归档里只存符号表,不内嵌.o文件内容。链接时ld读取成员会失败:
1
ld: libcrypto.a: member libcrypto.a(cryptlib.o) in archive is not an object
  1. AR 参数顺序问题ar的语法是ar [-]X[MOPTS] archive [members],操作符(r)必须紧挨着ar或放在MOPTS前面。错误的顺序ar c rARFLAGS=c但顺序未修正时)会让arr当成归档文件名。

修复:把ARFLAGS改成c(create),并把AR定义里的rARFLAGS顺序互换。

⚠️ 重要:OpenSSL 1.0.0 有 3 个 Makefile 需要改(顶层、crypto/ssl/),因为crypto/Makefilessl/Makefile各自有独立的AR定义,且硬编码了ar r(没有$(CROSS_COMPILE)前缀)。顶层 Makefile 通过make -eAR环境变量,但子 Makefile 里的AR定义优先级更高。

123456789
# 顶层 Makefilesed -i 's/^ARFLAGS= $/ARFLAGS=c/' Makefilesed -i 's/^AR= $(CROSS_COMPILE)ar $(ARFLAGS) r$/AR= $(CROSS_COMPILE)ar r$(ARFLAGS)/' Makefile# crypto/Makefile(注意行首是 tab)sed -i 's|^AR=		ar r|AR=		$(CROSS_COMPILE)ar r$(ARFLAGS)|' crypto/Makefile# ssl/Makefile(注意行首是 tab)sed -i 's|^AR=		ar r|AR=		$(CROSS_COMPILE)ar r$(ARFLAGS)|' ssl/Makefile

改完验证:

1
grep -E '^ARFLAGS|^AR=' Makefile crypto/Makefile ssl/Makefile

期望输出:

1234
Makefile:      ARFLAGS=cMakefile:      AR= $(CROSS_COMPILE)ar r$(ARFLAGS)crypto/Makefile: AR=		$(CROSS_COMPILE)ar r$(ARFLAGS)ssl/Makefile:    AR=		$(CROSS_COMPILE)ar r$(ARFLAGS)

展开后实际调用: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)会让arr当归档名。 正确写法是ar r$(ARFLAGS)ar rc


4. 编译(直接 make)

12
make depend   # 必须先跑,因为 ./Configure 改过算法开关make # 不可以 make -j$(nproc)

编译完成后会得到:

1234
libcrypto.so -> libcrypto.so.1.0.0   (符号链接)libcrypto.so.1.0.0                  (2.1 MB, ELF aarch64)libssl.so -> libssl.so.1.0.0        (符号链接)libssl.so.1.0.0                     (387 KB, ELF aarch64)

5. 验证产物

123456789101112131415161718
# 文件类型file libcrypto.so libssl.so# 期望:ELF 64-bit LSB shared object, ARM aarch64, ...# 大小(libcrypto ≈ 2.1 MB,libssl ≈ 387 KB)ls -lh libcrypto.so libssl.so# 导出符号aarch64-none-linux-gnu-nm -D libcrypto.so | grep -E 'SSLeay|RAND_bytes|AES_set_encrypt_key'aarch64-none-linux-gnu-nm -D libssl.so    | grep -E 'SSL_library_init|TLSv1_method|DTLSv1_method'# ELF 头aarch64-none-linux-gnu-readelf -h libcrypto.so | grep -E 'Class|Machine|Type'# 期望:Class: ELF64 / Machine: AArch64 / Type: DYN (Shared object file)# libssl.so 应依赖 libcrypto.soaarch64-none-linux-gnu-readelf -d libssl.so | grep NEEDED# 期望:NEEDED  Shared library: [libcrypto.so.1.0.0]

6. 安装

12
export INSTALLDIR=$HOME/repository/openssl-1.0.0s/_installmake install

最终目录结构:

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
_install├── bin│   ├── c_rehash│   └── openssl├── include│   └── openssl│       ├── aes.h│       ├── asn1.h│       ├── asn1_mac.h│       ├── asn1t.h│       ├── bio.h│       ├── blowfish.h│       ├── bn.h│       ├── buffer.h│       ├── camellia.h│       ├── cast.h│       ├── cms.h│       ├── comp.h│       ├── conf.h│       ├── conf_api.h│       ├── crypto.h│       ├── des.h│       ├── des_old.h│       ├── dh.h│       ├── dsa.h│       ├── dso.h│       ├── dtls1.h│       ├── e_os2.h│       ├── ebcdic.h│       ├── ec.h│       ├── ecdh.h│       ├── ecdsa.h│       ├── engine.h│       ├── err.h│       ├── evp.h│       ├── hmac.h│       ├── krb5_asn.h│       ├── kssl.h│       ├── lhash.h│       ├── md4.h│       ├── md5.h│       ├── modes.h│       ├── obj_mac.h│       ├── objects.h│       ├── ocsp.h│       ├── opensslconf.h│       ├── opensslv.h│       ├── ossl_typ.h│       ├── pem.h│       ├── pem2.h│       ├── pkcs12.h│       ├── pkcs7.h│       ├── pqueue.h│       ├── rand.h│       ├── rc2.h│       ├── rc4.h│       ├── ripemd.h│       ├── rsa.h│       ├── safestack.h│       ├── seed.h│       ├── sha.h│       ├── ssl.h│       ├── ssl2.h│       ├── ssl23.h│       ├── ssl3.h│       ├── stack.h│       ├── symhacks.h│       ├── tls1.h│       ├── ts.h│       ├── txt_db.h│       ├── ui.h│       ├── ui_compat.h│       ├── whrlpool.h│       ├── x509.h│       ├── x509_vfy.h│       └── x509v3.h├── lib│   ├── engines│   │   ├── lib4758cca.so│   │   ├── libaep.so│   │   ├── libatalla.so│   │   ├── libcapi.so│   │   ├── libchil.so│   │   ├── libcswift.so│   │   ├── libgmp.so│   │   ├── libgost.so│   │   ├── libnuron.so│   │   ├── libpadlock.so│   │   ├── libsureware.so│   │   └── libubsec.so│   ├── libcrypto.a│   ├── libcrypto.so -> libcrypto.so.1.0.0│   ├── libcrypto.so.1.0.0│   ├── libssl.a│   ├── libssl.so -> libssl.so.1.0.0│   ├── libssl.so.1.0.0│   └── pkgconfig│       ├── libcrypto.pc│       ├── libssl.pc│       └── openssl.pc│...............................

7. 一键脚本

把下面内容保存为build-openssl-aarch64.sh,放在openssl-1.0.0s/同级目录:

123456789101112131415161718192021222324252627282930313233343536373839
#!/usr/bin/env bashset -euo pipefail# ============ 配置 ============# 工具链路径(按你的环境修改)CROSS=${CROSS:-/home/zhaohang/tools/gcc-arm-11.2-2022.02-x86_64-aarch64-none-linux-gnu/bin}CROSS_COMPILE=${CROSS_COMPILE:-aarch64-none-linux-gnu-}# ==============================SRCDIR=$(cd "$(dirname "$0")/openssl-1.0.0s" && pwd)INSTALLDIR="$SRCDIR/_install"export PATH="$CROSS:$PATH"export CROSS_COMPILEcd "$SRCDIR"# 配置./Configure linux-generic64 shared \  --prefix="$INSTALLDIR" \  --openssldir="$INSTALLDIR/ssl" \  no-idea no-md2 no-mdc2 no-rc5 no-ssl2 no-ssl3 \  -DOPENSSL_NO_HEARTBEATS# ★ 关键修复:强制 ar 生成胖归档(修复瘦归档 + AR 参数顺序两个问题)#    需要改 3 个 Makefile:顶层、crypto/、ssl/sed -i 's/^ARFLAGS= $/ARFLAGS=c/' Makefilesed -i 's/^AR= $(CROSS_COMPILE)ar $(ARFLAGS) r$/AR= $(CROSS_COMPILE)ar r$(ARFLAGS)/' Makefilesed -i 's|^AR=		ar r|AR=		$(CROSS_COMPILE)ar r$(ARFLAGS)|' crypto/Makefilesed -i 's|^AR=		ar r|AR=		$(CROSS_COMPILE)ar r$(ARFLAGS)|' ssl/Makefile# 编译make dependmake -j1 # 只能 make -j1 编译# 安装make installecho "=== 构建完成 ==="
12
chmod +x build-openssl-aarch64.sh./build-openssl-aarch64.sh

8. 常见问题排查

现象原因修复
Configure: target already definedCROSS_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 specifiedARFLAGS 包含了r(与 AR 定义里的r重复)ARFLAGS 应该只是c,不能是rc
ar: creating rar: r: No such fileAR 参数顺序错误(ar $(ARFLAGS) rsed -i 's/AR=...ar $(ARFLAGS) r$/AR=...ar r$(ARFLAGS)/' Makefile
改了顶层 Makefile 但归档还是瘦归档crypto/Makefilessl/Makefile有独立的 AR 定义同时改 3 个 Makefile
.so只有几 KB链接时缺--whole-archive(极少见,Makefile 内置了)检查 Makefile.shared 的ALLSYMSFLAGS
编译报openssl/idea.h: No such file没加no-ideaConfigure 时加no-idea no-mdc2 no-rc5
make cleanrm -f install/libinstall/目录已存在且非空手动rm -rf install或忽略该错误

9. 总结:四步出 .so

12345678910111213141516171819202122
# 1. 配置export PATH=/home/zhaohang/tools/gcc-arm-11.2-2022.02-x86_64-aarch64-none-linux-gnu/bin:$PATHexport CROSS_COMPILE=aarch64-none-linux-gnu-# 2. Configure./Configure linux-generic64 shared --prefix=$PWD/_install \  no-idea no-md2 no-mdc2 no-rc5 no-ssl2 no-ssl3 -DOPENSSL_NO_HEARTBEATS# 3. 改 3 个 Makefile 的 AR 定义(修复瘦归档 + AR 参数顺序)sed -i 's/^ARFLAGS= $/ARFLAGS=c/' Makefilesed -i 's/^AR= $(CROSS_COMPILE)ar $(ARFLAGS) r$/AR= $(CROSS_COMPILE)ar r$(ARFLAGS)/' Makefilesed -i 's|^AR=		ar r|AR=		$(CROSS_COMPILE)ar r$(ARFLAGS)|' crypto/Makefilesed -i 's|^AR=		ar r|AR=		$(CROSS_COMPILE)ar r$(ARFLAGS)|' ssl/Makefile# 4. 编译make depend && make -j1# 5. 安装make install# 6. 验证file libcrypto.so libssl.so
评论加载中…