这篇文章上次修改于 945 天前,可能其部分内容已经发生变化,如有疑问可询问作者。

本文以在ubuntu 20.04(amd64)系统上交叉编译在ubuntu 20.04(ppc64el)系统上运行的wget程序为例,说明交叉编译的方法。

1 准备

交叉编译时可能会依赖第三方的软件包或库文件,编译时要求依赖库的架构需要与目标架构相同。通常编译主机默认并不包含这些库,这时可以有两个解决办法:一是先交叉编译出所依赖的库,二是直接下载现成的已有安装包。使用符合目标主机架构的安装包明显可以降低适配工作量。

wget构建时依赖openssl和zlib库,所以需要先配置好这两个库的头文件、库文件信息。

在ubuntu系统上,在配置好ppc64el架构的apt软件源后,即可以使用apt直接下载所需deb软件包并将deb包安装后使用。为防止其他架构deb包安装时可能与当前主机架构相冲突,所以不适用apt install命令直接进行安装,而采用先下载后安装到指定目录方式。

1.1 apt获取ppc64el架构软件包

apt只下载不安装软件包

apt download zlib1g-dev:ppc64el   #下载软件包到当前目录下

1.2 dpkg

解压deb包到指定路径

dpkg -X <软件包名>.deb <路径>   #显示解压出的文件列表
dpkg -x <软件包名>.deb <路径>   #不显示文件列表

1.3 配置交叉工具

ppc64el交叉编译工具链可以在ibm提供的软件源中获得,在apt源中增加:

ppc64el@Compile-Ubuntu-2004:/etc/apt/sources.list.d$ touch ibm_linux_toolchain.list
ppc64el@Compile-Ubuntu-2004:/etc/apt/sources.list.d$ cat ibm_linux_toolchain.list
deb [arch=amd64,ppc64el] https://public.dhe.ibm.com/software/server/POWER/Linux/toolchain/at/ubuntu focal at15.0

添加该软件源公钥信息

ppc64el@Compile-Ubuntu-2004:~$ wget https://public.dhe.ibm.com/software/server/POWER/Linux/toolchain/at/ubuntu/dists/focal/6976a827.gpg.key
sudo apt-key add 6976a827.gpg.key

安装交叉编译工具

ppc64el@Compile-Ubuntu-2004:~$ sudo apt update
ppc64el@Compile-Ubuntu-2004:~$ sudo apt install advance-toolchain-at15.0-cross-ppc64le

成功后,工具保存在/opt/at15.0目录下。

1.4 配置ubuntu额外软件源

ubuntu软件源均使用阿里云国内镜像

注意 [arch=amd64,i386] 信息,仅使用指定架构,否则可能由于部分架构文件确实apt工具报错。

ppc64el@Compile-Ubuntu-2004:/etc/apt$ cat sources.list
# deb cdrom:[Ubuntu 20.04.4 LTS _Focal Fossa_ - Release amd64 (20220223)]/ focal main restricted

# See http://help.ubuntu.com/community/UpgradeNotes for how to upgrade to
# newer versions of the distribution.
deb [arch=amd64,i386] http://mirrors.aliyun.com/ubuntu/ focal main restricted multiverse
# deb-src http://cn.archive.ubuntu.com/ubuntu/ focal main restricted

## Major bug fix updates produced after the final release of the
## distribution.
deb [arch=amd64,i386] http://mirrors.aliyun.com/ubuntu/ focal-updates main restricted multiverse
# deb-src http://cn.archive.ubuntu.com/ubuntu/ focal-updates main restricted

## N.B. software from this repository is ENTIRELY UNSUPPORTED by the Ubuntu
## team. Also, please note that software in universe WILL NOT receive any
## review or updates from the Ubuntu security team.
deb [arch=amd64,i386] http://mirrors.aliyun.com/ubuntu/ focal universe
# deb-src http://cn.archive.ubuntu.com/ubuntu/ focal universe
deb [arch=amd64,i386] http://mirrors.aliyun.com/ubuntu/ focal-updates universe
# deb-src http://cn.archive.ubuntu.com/ubuntu/ focal-updates universe

## N.B. software from this repository is ENTIRELY UNSUPPORTED by the Ubuntu
## team, and may not be under a free licence. Please satisfy yourself as to
## your rights to use the software. Also, please note that software in
## multiverse WILL NOT receive any review or updates from the Ubuntu
## security team.
# deb-src http://cn.archive.ubuntu.com/ubuntu/ focal multiverse
# deb-src http://cn.archive.ubuntu.com/ubuntu/ focal-updates multiverse

## N.B. software from this repository may not have been tested as
## extensively as that contained in the main release, although it includes
## newer versions of some applications which may provide useful features.
## Also, please note that software in backports WILL NOT receive any review
## or updates from the Ubuntu security team.
deb [arch=amd64,i386] http://mirrors.aliyun.com/ubuntu/ focal-backports main restricted universe multiverse
# deb-src http://cn.archive.ubuntu.com/ubuntu/ focal-backports main restricted universe multiverse

## Uncomment the following two lines to add software from Canonical's
## 'partner' repository.
## This software is not part of Ubuntu, but is offered by Canonical and the
## respective vendors as a service to Ubuntu users.
# deb http://archive.canonical.com/ubuntu focal partner
# deb-src http://archive.canonical.com/ubuntu focal partner

deb [arch=amd64,i386] http://mirrors.aliyun.com/ubuntu/ focal-security main restricted multiverse
# deb-src http://security.ubuntu.com/ubuntu focal-security main restricted
deb [arch=amd64,i386] http://mirrors.aliyun.com/ubuntu/ focal-security universe
# deb-src http://security.ubuntu.com/ubuntu focal-security universe
# deb-src http://security.ubuntu.com/ubuntu focal-security multiverse

# This system was installed using small removable media
# (e.g. netinst, live or single CD). The matching "deb cdrom"
# entries were disabled at the end of the installation process.
# For information about how to configure apt package sources,
# see the sources.list(5) manual.

注意 [arch=arm64,armhf,ppc64el,riscv64]信息,仅使用指定架构,否则可能由于部分架构文件确实apt工具报错。

ppc64el@Compile-Ubuntu-2004:/etc/apt/sources.list.d$ touch ubuntu-ppc64el.list
ppc64el@Compile-Ubuntu-2004:/etc/apt/sources.list.d$ cat ubuntu-ppc64el.list
# 默认注释了源码仓库,如有需要可自行取消注释
deb [arch=arm64,armhf,ppc64el,riscv64] https://mirrors.aliyun.com/ubuntu-ports/ focal main restricted universe multiverse
# deb-src https://mirrors.aliyun.com/ubuntu-ports/ focal main main restricted universe multiverse
deb [arch=arm64,armhf,ppc64el,riscv64] https://mirrors.aliyun.com/ubuntu-ports/ focal-updates main restricted universe multiverse
# deb-src https://mirrors.aliyun.com/ubuntu-ports/ focal-updates main restricted universe multiverse
deb [arch=arm64,armhf,ppc64el,riscv64] https://mirrors.aliyun.com/ubuntu-ports/ focal-backports main restricted universe multiverse
# deb-src https://mirrors.aliyun.com/ubuntu-ports/ focal-backports main restricted universe multiverse
deb [arch=arm64,armhf,ppc64el,riscv64] https://mirrors.aliyun.com/ubuntu-ports/ focal-security main restricted universe multiverse
# deb-src https://mirrors.aliyun.com/ubuntu-ports/ focal-security main restricted universe multiverse

# 预发布软件源,不建议启用
# deb [arch=arm64,armhf,ppc64el,riscv64] https://mirrors.aliyun.com/ubuntu-ports/ focal-proposed main restricted universe multiverse
# deb-src https://mirrors.aliyun.com/ubuntu-ports/ focal-proposed main restricted universe multiverse

dpkg工具增加ppc64el架构

ppc64el@Compile-Ubuntu-2004:~$ sudo dpkg --add-architecture ppc64el

2 下载依赖包

ppc64el@Compile-Ubuntu-2004:~$ sudo mkidr /opt/ppc64el/package  #用于存放deb包
ppc64el@Compile-Ubuntu-2004:~$ cd /opt/ppc64el/package
ppc64el@Compile-Ubuntu-2004:/opt/ppc64el/package$ apt download zlib1g:ppc64el
...
ppc64el@Compile-Ubuntu-2004:/opt/ppc64el/package$ ls -l
total 4592
-rw-r--r-- 1 root    root     960792 8月   3  2021 libgnutls28-dev_3.6.13-2ubuntu1.6_ppc64el.deb
-rw-r--r-- 1 root    root      30208 8月   3  2021 libgnutls-openssl27_3.6.13-2ubuntu1.6_ppc64el.deb
-rw-r--r-- 1 ppc64el ppc64el 1589020 3月  29 09:08 libssl1.1_1.1.1l-1ubuntu1.2_ppc64el.deb
-rw-r--r-- 1 ppc64el ppc64el 1880712 3月  29 09:08 libssl-dev_1.1.1l-1ubuntu1_ppc64el.deb
-rw-r--r-- 1 ppc64el ppc64el   61832 10月 21  2020 zlib1g_1%3a1.2.11.dfsg-2ubuntu1.2_ppc64el.deb
-rw-r--r-- 1 ppc64el ppc64el  164960 10月 21  2020 zlib1g-dev_1%3a1.2.11.dfsg-2ubuntu1.2_ppc64el.deb

3 安装ppc64el包到指定目录(/opt/ppc64el)

ppc64el@Compile-Ubuntu-2004:/opt/ppc64el/package$ sudo dpkg -X zlib1g_1%3a1.2.11.dfsg-2ubuntu1.2_ppc64el.deb  ..
...
...

4 设置环境变量

设置CC、CFLAGS、LDFLAGS环境变量,用于构建时搜索的包含路径和库路径。

ppc64el@Compile-Ubuntu-2004:~$ tail -10 7 .bashrc
tail: option used in invalid context -- 1
ppc64el@Compile-Ubuntu-2004:~$ tail -10 .bashrc
    . /etc/bash_completion
  fi
fi

## customsize environment variable
export ADV_TOOL_DIR=/opt/at15.0
export CC=${ADV_TOOL_DIR}/bin/powerpc64le-linux-gnu-gcc
export CFLAGS="-I/opt/ppc64el/usr/include -I/opt/ppc64el/usr/include/powerpc64le-linux-gnu"
export LDFLAGS="-L/opt/ppc64el/usr/lib/powerpc64le-linux-gnu"

5 构建wget

5.1 编译

ppc64el@Compile-Ubuntu-2004:~$ tar zxvf wget-1.21.tar.gz
ppc64el@Compile-Ubuntu-2004:~$ cd wget-1.21/
ppc64el@Compile-Ubuntu-2004:~/wget-1.21$ mkdir build
ppc64el@Compile-Ubuntu-2004:~/wget-1.21$ cd build
# 设置目标主机powerpc64le-linux,使用openssl,并设置安装目录为当前目录下的wget目录
ppc64el@Compile-Ubuntu-2004:~/wget-1.21/build$ ../configure --prefix=$PWD/wget --host=powerpc64le-linux --with-ssl=openssl
ppc64el@Compile-Ubuntu-2004:~/wget-1.21/build$ make
ppc64el@Compile-Ubuntu-2004:~/wget-1.21/build$ make install
ppc64el@Compile-Ubuntu-2004:~/wget-1.21/build$ cd wget/

5.2 查看安装结果

ppc64el@Compile-Ubuntu-2004:~/wget-1.21/build/wget$ du -h --max-depth=2
872K    ./bin
120K    ./share/man
2.9M    ./share/locale
240K    ./share/info
3.3M    ./share
12K     ./etc
4.2M    .

ppc64el@Compile-Ubuntu-2004:~/wget-1.21/build/wget$ ls -l bin
total 868
-rwxr-xr-x 1 ppc64el ppc64el 898808 3月  29 11:21 wget

5.3 查看可执行文件架构

ppc64el@Compile-Ubuntu-2004:~/wget-1.21/build/wget$ file bin/wget
bin/wget: ELF 64-bit LSB executable, 64-bit PowerPC or cisco 7500, version 1 (SYSV), dynamically linked, interpreter /opt/at15.0/lib64/ld64.so.2, BuildID[sha1]=04d9f1376f35b3ae850186be065ec2495e13eae7, for GNU/Linux 4.12.14, with debug_info, not stripped

由于编译出的wget是ppc64el架构,显然在当前主机是不能运行的。

ppc64el@Compile-Ubuntu-2004:~/wget-1.21/build/wget/bin$ ./wget
-bash: ./wget: cannot execute binary file: Exec format error

将安装目录打包,并安装至ppc64el架构系统上,便可以正常运行了(注意,可能遇到库依赖问题可通过设置环境变量或修改ld.so.conf配置解决,这里不再赘述)。