Skip to main content

C++交叉编译问题排查

1. 编译器版本的问题

1.1. 问题现象

在X86_64 Ubuntu24.04系统上用aarch64-linux-gnu-g++进行交叉编译C++代码, C++源码文件如下:

// Test.cpp

#include <iostream>

int main()
{
std::cout << "Hello world!" << std::endl;
return 0;
}

编译命令如下:

aarch64-linux-gnu-g++ ./Test.cpp -o Test

编译成功后,将目标文件Test通过scp工具推送到ARM64 Ubuntu22.04系统上,然后执行./Test, 但出现如下报错:

./Test 
./Test: /lib/aarch64-linux-gnu/libstdc++.so.6: version `GLIBCXX_3.4.32' not found (required by ./Test)

1.2. 原因分析

错误来自 libstdc++ 版本不匹配:你在 x86_64 上用 aarch64 的交叉编译器(通常基于较新的 GCC)生成的二进制,链接到了 GLIBCXX_3.4.32。目标机(ARM64 Ubuntu 22.04)上的 /usr/lib/aarch64-linux-gnu/libstdc++.so.6 没有这个版本符号,运行时找不到所以报错。

1.3. 解决方法

1.3.1. 方法1:静态链接 C++ 标准库

静态链接libstdc++

最简单的解决方案是静态链接 libstdc++:

aarch64-linux-gnu-g++ ./Test.cpp -o Test -static-libstdc++ -static-libgcc

该方法在我的环境上验证失败,报错信息如下:

# ARM64 Ubuntu22.04 上运行
./Test
./Test: /lib/aarch64-linux-gnu/libc.so.6: version `GLIBC_2.38' not found (required by ./Test)
./Test: /lib/aarch64-linux-gnu/libc.so.6: version `GLIBC_2.36' not found (required by ./Test)
1.3.2. 完全静态链接

如果还有问题,可以采用完全静态链接:

aarch64-linux-gnu-g++ ./Test.cpp -o Test -static

该方法在我的环境上验证成功:

# ARM64 Ubuntu22.04 上运行
./Test
Hello world!

优点:生成的可执行文件在目标系统上不依赖动态库版本 缺点:文件体积会变大

以Test为例,体积比较如下:

# 不使用静态链接
-rwxr-xr-x 1 root root 70K Jan 30 06:57 Test
# 静态链接libstdc++
-rwxr-xr-x 1 root root 2.6M Jan 30 07:21 Test
# 完全静态链接
-rwxr-xr-x 1 root root 3.2M Jan 30 07:13 Test

1.3.2. 方法2:使用目标系统兼容的工具链

安装与 Ubuntu 22.04 兼容的交叉编译工具链:

# 移除可能存在的现有工具链
sudo apt remove gcc-aarch64-linux-gnu g++-aarch64-linux-gnu

# 安装 Ubuntu 22.04 兼容的工具链
sudo apt update
sudo apt install gcc-11-aarch64-linux-gnu g++-11-aarch64-linux-gnu

然后使用特定的版本编译:

aarch64-linux-gnu-g++-11 ./Test.cpp -o Test

验证成功:

# ARM64 Ubuntu22.04 上运行
./Test
Hello world!

1.3.3. 方法3 使用ubuntu:22.04的Docker镜像

使用 Docker 创建一个与目标系统兼容的编译环境:

# 创建 Dockerfile
cat > Dockerfile << 'EOF'
FROM ubuntu:22.04

RUN apt-get update && \
apt-get install -y \
gcc-aarch64-linux-gnu \
g++-aarch64-linux-gnu \
build-essential && \
apt-get clean

WORKDIR /workspace
EOF

# 构建镜像并编译
docker build -t cross-compile-env .
docker run -v $(pwd):/workspace cross-compile-env \
aarch64-linux-gnu-g++ /workspace/Test.cpp -o /workspace/Test

2. TODO 其他问题