制作aarch64 交叉编译器-pc版本

本文介绍如何在Ubuntu 16.04上从源码构建一套完整的Aarch64交叉编译工具链,包括所需库的下载、配置及编译安装过程。该工具链涵盖Binutils、GCC、glibc等核心组件。

0. 系统环境

系统:

  • ubuntu16.04

1. 编译交叉编译工具链

交叉编译工具链需要用到至少七个库:

  1. Binutils
  2. GCC
  3. glibc
  4. Linux Kernel
  5. MPFR
  6. GMP
  7. MPC

同时我们还有两个用于优化的库:

  1. isl
  2. CLooG

这两个库是可选的。搭建完成后我们会获得一系列编译、链接工具,包括我们熟知的 gccld 等。

工具版本

1.binutils-2.37      2.gcc-7.3.0   3.glibc-2.27   4.gmp-6.2.0  5.mpc-1.1.0    6.mpfr-4.0.2

7.linux-4.14.98   8.cloog-0.18.1  9.isl-0.18

进入/home/work/toolchain目录下载相应的包脚本 1-down.sh

#!/bin/sh


export GNU_MIRROR_SITE=https://mirrors.tuna.tsinghua.edu.cn/gnu/
export KERNEL_MIRROR_SITE=https://mirrors.tuna.tsinghua.edu.cn/kernel/

wget $GNU_MIRROR_SITE/binutils/binutils-2.37.tar.xz                 # binutils

wget $GNU_MIRROR_SITE/gcc/gcc-7.3.0/gcc-7.3.0.tar.xz                # gcc

wget $GNU_MIRROR_SITE/glibc/glibc-2.27.tar.xz                       # glibc

wget $KERNEL_MIRROR_SITE/v4.x/linux-4.14.98.tar.xz                 # kernel
wget $GNU_MIRROR_SITE/mpfr/mpfr-4.0.2.tar.xz                        # mpfr
wget $GNU_MIRROR_SITE/gmp/gmp-6.2.0.tar.xz                          # gmp
wget $GNU_MIRROR_SITE/mpc/mpc-1.1.0.tar.gz                          # mpc

# optional
wget ftp://gcc.gnu.org/pub/gcc/infrastructure/isl-0.18.tar.bz2      # isl
wget ftp://gcc.gnu.org/pub/gcc/infrastructure/cloog-0.18.1.tar.gz   # cloog

进入/home/work/toolchain目录解压库文件,脚本2-tar.sh

#!/bin/sh


for f in *.tar.xz;
do
    tar -xJf $f;
done

for f in *.tar.bz2;
do
    tar -xjf $f;
done

for f in *.tar.gz;
do
    tar -xzf $f;
done

建立 GCC 依赖库们的软链接,进入/home/work/toolchain目录执行脚本脚本3-ln.sh

#!/bin/sh


ln -sf ../mpfr-4.0.2 gcc-7.3.0/mpfr      # mfpr
ln -sf ../gmp-6.2.0 gcc-7.3.0/gmp        # gmp
ln -sf ../mpc-1.1.0 gcc-7.3.0/mpc        # mpc

# optional
ln -sf ../isl-0.18 gcc-7.3.0/isl         # isl
ln -sf ../cloog-0.18.1 gcc-7.3.0/cloog   # cloog

设定编译时使用的线程数

export NPROC=`nproc`

1.2. 编译安装 Binutils

这个工具包将会被安装在 /home/work/toolchain/path/bin 内,包括了交叉汇编器、交叉链接器等工具,脚本

#!/bin/sh

export NPROC=`nproc`
export CROSS_COMPILE_INSTALL=/home/work/toolchain/path

mkdir binutils
cd binutils
../binutils-2.37/configure  \
    --prefix=$CROSS_COMPILE_INSTALL         \
    --target=aarch64-cc-linux                  \
    --enable-multilib
make -j$NPROC
make install

1.3. 安装 Linux Kernel 头文件

这一步会将 Linux Kernel 头文件安装咋 $CROSS_COMPILE_INSTALL/aarch64-install/include,这样交叉编译链编译出的软件可以在目标平台中使用 Linux 系统调用。

export NPROC=`nproc` 
export CROSS_COMPILE_INSTALL=/home/work/toolchain/path

cd ./linux-4.14.98
make                                                        \
    ARCH=arm64                                              \
    INSTALL_HDR_PATH=$CROSS_COMPILE_INSTALL/aarch64-cc-linux   \
    headers_install

1.4. 编译安装 GCC 和 glibc

这是很长的一步,我们将要轮流编译属于两个库(GCC 和 glibc)的组件,并最终全部编译完成。编译顺序如下(图源为参考博客)

1.4.1. 编译器

这一步只会安装 C/C++ 交叉编译器本身,它们会被安装在 $CROSS_COMPILE_INSTALL/bin
export NPROC=`nproc` 
export CROSS_COMPILE_INSTALL=/home/work/toolchain/path

mkdir gcc
cd gcc
../gcc-7.3.0/configure  \
    --prefix=$CROSS_COMPILE_INSTALL     \
    --target=aarch64-cc-linux              \
    --enable-language=c,c++             \
    --with-gnu-ld --enable-shared --enable-threads=posix --enable-multilib --enable-c99 --enable-long-long \
    --enable-libstdcxx-pch --enable-lto --enable-libssp --enable-libitm --disable-bootstrap --disable-libmudflap \
    --with-system-zlib --enable-linker-build-id --with-ppl=no --with-cloog=no --enable-checking=release --without-isl --enable-nls \
    --without-local-prefix --with-linker-hash-style=gnu --without-long-double-128 --enable-poison-system-directories --enable-initfini-array \
    --disable-silent-rules --enable-symvers=gnu --enable-cheaders=c_global --enable-__cxa_atexit
make -j$NPROC all-gcc
make install-gcc

这一步要编译个十分钟左右

1.4.2. 标准 C 头文件和启动文件

这一步里我们将所有的标准 C 头文件安装在 $CROSS_COMPILE_INSTALL/aarch64-cc-linux/include 内。同时我们还会编译一些启动文件并安装在 $CROSS_COMPILE_INSTALL/aarch64-cc-linux/lib 内,这些文件将被下一步用到,并在下下步被替换。

注意: 如果前面没有把 $CROSS_COMPILE_INSTALL/bin 加入到 PATH 中的话这一步会报错。

export NPROC=`nproc` 
export CROSS_COMPILE_INSTALL=/home/work/toolchain/path
export PATH=$PATH:$CROSS_COMPILE_INSTALL/bin

mkdir glibc
cd glibc
../glibc-2.27/configure                         \
    --prefix=$CROSS_COMPILE_INSTALL/aarch64-cc-linux               \
    --build=$MACHTYPE                                           \
    --host=aarch64-cc-linux                                        \
    --target=aarch64-cc-linux                                      \
    --with-headers=$CROSS_COMPILE_INSTALL/aarch64-cc-linux/include \
    --enable-multilib                                           \
    libc_cv_forced_unwind=yes
#    --disable-multilib                                          \
make install-bootstrap-headers=yes install-headers
make -j$NPROC csu/subdir_lib #
install csu/crt1.o csu/crti.o csu/crtn.o $CROSS_COMPILE_INSTALL/aarch64-cc-linux/lib
aarch64-cc-linux-gcc -nostdlib -nostartfiles -shared -x c /dev/null -o $CROSS_COMPILE_INSTALL/aarch64-cc-linux/lib/libc.so
touch $CROSS_COMPILE_INSTALL/aarch64-cc-linux/include/gnu/stubs.h

1.4.3. 编译器支持库

这一步我们使用前面编译得到的交叉编译器来编译编译器支持库。

export NPROC=`nproc` 
export CROSS_COMPILE_INSTALL=/home/work/toolchain/path
export PATH=$PATH:$CROSS_COMPILE_INSTALL/bin


cd ./gcc
make -j$NPORC all-target-libgcc #
make install-target-libgcc

1.4.4. 编译标准 C 库

这一步我们可以完成 glibc 的编译安装。标准 C 库将被安装于 $CROSS_COMPILE_INSTALL/aarch64-cc-linux/lib


export NPROC=`nproc` 
export CROSS_COMPILE_INSTALL=/home/work/toolchain/path
export PATH=$PATH:$CROSS_COMPILE_INSTALL/bin

cd ./glibc
make -j$NPROC
make install

这一步也要编译个十分钟左右

1.4.5. 编译标准 C++ 库

这一步我们可以完成 GCC 的编译安装。标准 C++ 库将被安装于 $CROSS_COMPILE_INSTALL/aarch64-cc-linux/lib64

cd ./gcc
make -j$NPROC
make install

这一步也要编译个十分钟左右

1.5. strip


export NPROC=`nproc` 
export CROSS_COMPILE_INSTALL=/home/work/toolchain/path
export PATH=$PATH:$CROSS_COMPILE_INSTALL/bin


cd $CROSS_COMPILE_INSTALL/libexec/gcc/aarch64-mile-linux/7.3.0
strip cc1 cc1obj cc1plus collect2 f951 lto1 lto-wrapper
cd $CROSS_COMPILE_INSTALL/bin
strip *

1.5. 测试交叉编译器


aarch64-cc-linux-gcc helloworld.c -o hello

./hello
 

你正在使用 **libunwind-4.0.10** 源码,在 QNX Neutrino 7.1.0 上为 AArch64 架构进行交叉编译,并遇到了编译错误(如 `#error "Unsupported arch"` 或链接问题等)。你的 `./configure` 命令已经接近正确,但仍有一些关键点需要**修正和优化**。 --- ## ✅ 结论先行:是否需要修改 libunwind-4.0.10? > **是的,libunwind-4.0.10 对 QNX + AArch64 的支持不完整,通常需要手动补丁或配置调整才能成功编译。** 虽然它理论上支持 AArch64,但对 **QNX 平台识别不足**,且 Autotools 配置脚本可能无法自动检测到目标架构,导致: - 编译时报错:`#error "Unsupported arch"` - 找不到 CPU context 定义 - `regname.c`、`Rregs.h` 等文件缺失或未启用 --- ## 🔧 解决方案(适用于 libunwind-4.0.10) ### ✅ 步骤 1:修复 configure 命令(关键改进) 你的当前命令中存在几个问题: #### ❌ 错误点分析 | 项目 | 问题 | |------|------| | `CPPFLAGS="-D__aarch64__ ..."` | `CPPFLAGS` 是预处理器标志,不应包含 `-march=` 这类编译器选项(属于 `CFLAGS`) | | 缺少 `--prefix` | 容易污染系统目录 | | 缺少 `--build` 和 `--target` | 可能导致 autoconf 检测失败 | | 未设置 `LDFLAGS` | QNX 需要 `-lsocket -lexit` 等库 | | 未禁用静态库生成(可选) | 若只需 `.so`,可关闭 | --- ### ✅ 推荐的最终 `configure` 命令 ```bash ./configure \ --host=aarch64-unknown-nto-qnx7.1.0 \ --build=x86_64-pc-linux-gnu \ --target=aarch64-unknown-nto-qnx7.1.0 \ --prefix=/opt/libunwind-aarch64-qnx \ --disable-tests \ --disable-static \ --enable-shared \ CC=aarch64-unknown-nto-qnx7.1.0-gcc \ CXX=aarch64-unknown-nto-qnx7.1.0-g++ \ AR=aarch64-unknown-nto-qnx7.1.0-ar \ RANLIB=aarch64-unknown-nto-qnx7.1.0-ranlib \ LD=aarch64-unknown-nto-qnx7.1.0-ld \ STRIP=aarch64-unknown-nto-qnx7.1.0-strip \ CFLAGS="-D__aarch64__ -D__QNX__ -march=armv8-a -O3 -fPIC" \ CXXFLAGS="-D__aarch64__ -D__QNX__ -march=armv8-a -O3 -fPIC" \ CPPFLAGS="-I$QNX_TARGET/usr/include" \ LDFLAGS="-lsocket -lexit -lc" ``` 📌 **重点说明:** - `--prefix=...`: 指定独立安装路径,避免冲突。 - `--disable-static --enable-shared`: 强制生成 `.so` 动态库(推荐用于嵌入式系统)。 - `-D__aarch64__`: 强制启用 ARM64 支持路径。 - `-D__QNX__`: 让代码识别 QNX 系统(某些头文件依赖此宏)。 - `CPPFLAGS` 只放 `-I` 和纯预处理定义,不要加 `-march`。 - `LDFLAGS` 添加 QNX 必需库:`-lsocket`, `-lexit`, `-lc`。 --- ### ✅ 步骤 2:检查并创建缺失的 AArch64 架构支持文件 libunwind-4.0.10 的源码结构如下: ``` src/ ├── aarch64/ │ ├── init.c │ ├── is_fpreg.c │ ├── regname.c │ ├── Rregs.h │ └── Ginit.c ``` ⚠️ **问题:libunwind-4.0.10 默认可能没有启用 `aarch64/` 目录下的实现!** 你需要确认以下几点: #### ✅ 确认 `config.h` 是否定义了 `_LITTLE_ENDIAN` 和 `_QNX_SOURCE` 在 `include/config.h` 中添加(或确保 configure 设置): ```c #define _LITTLE_ENDIAN 1 #define __QNX__ 1 ``` 否则某些结构体对齐会出错。 #### ✅ 修改 `configure.ac` 或 `Makefile.am`(如果 autogen.sh 存在) 如果你是从 Git 源码构建,建议运行: ```bash autoreconf -i ``` 否则直接编辑 `src/Makefile.in`,确保 `aarch64` 被包含: ```makefile if ARCH_AARCH64 SUBDIRS += aarch64 endif ``` 或者查看 `configure` 输出是否有: ``` checking target architecture... aarch64 ``` 如果没有,说明架构未被识别。 --- ### ✅ 步骤 3:手动打补丁(必要时) #### 补丁 1:在 `include/libunwind-common.h` 中添加 QNX + AArch64 判断 ```diff #elif defined(__aarch64__) # include "aarch64/libunwind_i.h" + #elif defined(__QNX__) && defined(__aarch64__) + # include "aarch64/libunwind_i.h" #else # error "Unsupported arch" #endif ``` #### 补丁 2:在 `src/aarch64/init.c` 中包含 QNX 特有头文件 ```c #ifdef __QNX__ #include <sys/neutrino.h> #include <inttypes.h> // 否则 uint64_t 报错 #endif ``` --- ### ✅ 步骤 4:验证工具链是否定义了 `__aarch64__` 运行: ```bash echo | aarch64-unknown-nto-qnx7.1.0-gcc -dM -E - | grep -i aarch ``` ✅ 正确输出应包含: ``` #define __aarch64__ 1 ``` ❌ 如果没有,请务必在 `CFLAGS` 中加上 `-D__aarch64__`! --- ### ✅ 步骤 5:执行编译 ```bash make clean make -j$(nproc) make install ``` --- ### ✅ 验证输出结果 ```bash file .libs/libunwind.so ``` 输出应类似: ``` .libs/libunwind.so: ELF 64-bit LSB shared object, ARM aarch64, version 1 (SYSV), dynamically linked, stripped ``` 表示已成功生成 AArch64 共享库。 --- ### 🛠 常见错误与解决方法 | 错误信息 | 原因 | 解决方案 | |--------|------|---------| | `#error "Unsupported arch"` | 未识别架构 | 加 `-D__aarch64__` 或补全判断逻辑 | | `undefined reference to 'getcontext'` | QNX 不完全兼容 POSIX context API | 使用 `_setjmp`/`_longjmp` 替代,或打补丁 | | `cannot find -lunwind` | 库未安装或路径不对 | 检查 `--prefix` 并设置 `-L` | | `relocation R_AARCH64_ABS64 against ...` | 缺少 `-fPIC` | 确保 `CFLAGS` 包含 `-fPIC` | --- ### ✅ 替代建议:升级到更新版本 > ⚠️ **强烈建议:不要使用 libunwind-4.0.10**,它是较老版本2017 年左右),对现代平台支持差。 ✅ 推荐使用更活跃维护的分支: ```bash git clone https://github.com/libunwind/libunwind.git cd libunwind autoreconf -i ./configure --host=aarch64-unknown-nto-qnx7.1.0 ... ``` 新版(GitHub 主干)对 AArch64/QNX 有更好的支持,甚至包含 `qnx` 分支或 CI 测试。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值