随着开源软件的出现及其在创建复杂系统中的应用,这种解决方案的接受度不断提高,开发能够在多个硬件平台上无缝运行的应用程序的能力变得至关重要。始终需要在一种架构上开发软件,但又要能够在其他目标架构上执行这些软件。实现这一目标的一个常用技术是针对目标架构的交叉编译。
交叉编译在嵌入式系统中非常重要,因为这些系统的目标是运行在像ARM和PowerPC这样的专业硬件上。这些系统资源受限,因此直接编译并不是一个选项。因此,开发人员将利用常见的x86架构作为主机,并使用特定于目标硬件的工具链,生成与目标硬件兼容的二进制文件。
本文涵盖了一个案例研究,其中为PowerPC进行了开源软件包的交叉编译。文章将详细介绍使用的工具和工具链,以及如何针对该架构实现交叉编译的逐步教程。
The 问题陈述
给定一个具有PowerPC架构的目标板,目的是为这个板添加L3路由能力。为此考虑了一种流行的开源路由协议套件FRRouting(FRR)。
FRR 是一个协议套件,使任何 Linux 机器能够像一个 全面 路由器一样工作。它为 amd64、arm64、armhf、 和 i386 打包,但 不 支持 PowerPC。 这 促使了 FRR 的交叉编译。
Build host | target host | |
---|---|---|
CPU 架构 |
x86_64 |
Powerpc(32位) |
操作系统 |
Ubuntu 18.4 |
QorIQ SDK |
处理器 |
12 |
2 (e5500) |
内存 |
12GB |
1GB |
T表 1. 构建和目标平台的差异
T交叉编译之旅
交叉编译有两个主要阶段:
配置构建环境和预编译工具链
1. 在环境中安装所需的构建工具。常见的构建工具包括autoconf、make、cmake、build-essentials、pkg-config、libtool等。
2. 针对目标主机环境设置特定的预编译工具链。CPU/板卡供应商提供其自己的架构特定工具链。目标板卡特定的工具链可从供应商的产品网站获取。
3. 工具链附带一个环境文件,用于设置像CC、GCC、PKG_CONFIG_PATH等这些交叉编译所需的环境变量。编辑环境文件 /opt/fsl-qoriq/2.0/environment-setup-ppce5500-fsl-linux
并根据工具链目录的路径更新变量的路径。
export SDKTARGETSYSROOT=/opt/fsl-qoriq/2.0/sysroots/ppce5500-fsl-linux
export PATH=/opt/fsl-qoriq/2.0/sysroots/x86_64-fslsdk-linux/usr/bin:/opt/fsl-qoriq/2.0/sysroots/x86_64-fslsdk-linux/usr/bin/../x86_64-fslsdk-linux/bin:/opt/fsl-qoriq/2.0/sysroots/x86_64-fslsdk-linux/usr/bin/powerpc-fsl-linux:/opt/fsl-qoriq/2.0/sysroots/x86_64-fslsdk-linux/usr/bin/powerpc-fsl-linux-uclibc:/opt/fsl-qoriq/2.0/sysroots/x86_64-fslsdk-linux/usr/bin/powerpc-fsl-linux-musl:$PATH
export CCACHE_PATH=/opt/fsl-qoriq/2.0/sysroots/x86_64-fslsdk-linux/usr/bin:/opt/fsl-qoriq/2.0/sysroots/x86_64-fslsdk-linux/usr/bin/../x86_64-fslsdk-linux/bin:/opt/fsl-qoriq/2.0/sysroots/x86_64-fslsdk-linux/usr/bin/powerpc-fsl-linux:/opt/fsl-qoriq/2.0/sysroots/x86_64-fslsdk-linux/usr/bin/powerpc-fsl-linux-uclibc:/opt/fsl-qoriq/2.0/sysroots/x86_64-fslsdk-linux/usr/bin/powerpc-fsl-linux-musl:$CCACHE_PATH
export PKG_CONFIG_SYSROOT_DIR=$SDKTARGETSYSROOT
export PKG_CONFIG_PATH=$SDKTARGETSYSROOT/usr/lib/pkgconfig
export CONFIG_SITE=/opt/fsl-qoriq/2.0/site-config-ppce5500-fsl-linux
export PYTHONHOME=/opt/fsl-qoriq/2.0/sysroots/x86_64-fslsdk-linux/usr unset command_not_found_handle
export CC="powerpc-fsl-linux-gcc -m32 -mhard-float -mcpu=e5500 --sysroot=$SDKTARGETSYSROOT"
export CXX="powerpc-fsl-linux-g++ -m32 -mhard-float -mcpu=e5500 --sysroot=$SDKTARGETSYSROOT"
export CPP="powerpc-fsl-linux-gcc -E -m32 -mhard-float -mcpu=e5500 --sysroot=$SDKTARGETSYSROOT"
export AS="powerpc-fsl-linux-as "
export LD="powerpc-fsl-linux-ld --sysroot=$SDKTARGETSYSROOT"
export GDB=powerpc-fsl-linux-gdb
export STRIP=powerpc-fsl-linux-strip
export RANLIB=powerpc-fsl-linux-ranlib
export OBJCOPY=powerpc-fsl-linux-objcopy
export OBJDUMP=powerpc-fsl-linux-objdump
export AR=powerpc-fsl-linux-ar
export NM=powerpc-fsl-linux-nm
export M4=m4
export TARGET_PREFIX=powerpc-fsl-linux-
export CONFIGURE_FLAGS="--target=powerpc-fsl-linux --host=powerpc-fsl-linux --build=x86_64-linux --with-libtool-sysroot=$SDKTARGETSYSROOT"
export CFLAGS=" -O2 -pipe -g -feliminate-unused-debug-types"
export CXXFLAGS=" -O2 -pipe -g -feliminate-unused-debug-types"
export LDFLAGS="-Wl,-O1 -Wl,--hash-style=gnu -Wl,--as-needed"
export CPPFLAGS=""
export KCFLAGS="--sysroot=$SDKTARGETSYSROOT"
export OECORE_DISTRO_VERSION="2.0"
export OECORE_SDK_VERSION="2.0"
export ARCH=powerpc
export CROSS_COMPILE=powerpc-fsl-linux-
在预编译工具链中解决依赖关系
每个软件都有自己的一组依赖项(工具/库),在交叉编译之前需要解决这些依赖关系。
根据这些工具/库在目标架构中的包可用性,有两种选项可以解决它们。要么直接从可用的包中安装它们,要么也可以从源代码交叉编译它们。
特别针对FRR编译,libpcre2、libyang、clippy、libelf 和 json-c 库需要从源代码构建。除此之外,protobuf 和 libcap 库包可用于 PPC(PowerPC)架构,可以直接安装到工具链中。
1. 从包中安装库
可用于目标架构的库包可以通过两种方式安装到工具链系统根目录中:
- 第一种方法使用基于Ubuntu/Debian的
dpkg-deb
工具直接安装Debian包,如下所示:Shell$ dpkg-deb -x <pkg_name>.deb <toolchain_directory_path>
# libcap示例:
$ wget http://launchpadlibrarian.net/222364908/libcap-dev_2.24-12_powerpc.deb
$ dpkg-deb -x libcap-dev_2.24-12_powerpc.deb /opt/fsl-qoriq/2.0/sysroots/ppce5500-fsl-linux/
注意:
- 下载所有依赖包并按顺序安装。
- 库包可能会安装到不同的目录结构中。根据工具链将这些库文件复制到正确的目录。
- 在第二种方法中,debian/rpm 包被提取并手动放置到工具链目录路径,如下所述:
- 要提取 debian 包,请使用
ar
和tar
工具,如下所述:纯文本$ ar -x <package>.deb
$ tar -xJf data.tar.xz
注意: 此方法适用于不支持
dpkg-deb
的系统。 - 要提取 rpm 包,请使用
rpm2cpio
工具,如下命令:纯文本$ rpm2cpio <package>.rpm | cpio -idmv
-
包提取和文件放置的 libcap 示例:
Shell# 提取 .deb 包
$ ar -x libcap-dev_2.24-12_powerpc.deb
# 将提取三个文件 (control.tar.gz, data.tar.xz, debian-binary)
$ ls
control.tar.gz data.tar.xz debian-binary libcap-dev_2.24-12_powerpc.deb
# data.tar.xz 包含程序文件
# control.tar.gz 包含包的元数据
# debian-binary 包含 deb 文件格式的版本
# 解压 data.tar.xz 提取程序文件。
$ tar -xJf data.tar.xz
# 注意: rpm2cpio <package>.rpm 将直接提取程序文件。
# 对所有依赖的 debian 或 rpm 包在同一路径上执行相同操作,这将提取所有程序文件和所需的符号链接,并保持相同的目录结构。
# 提取的文件应复制到工具链目录路径下的 /usr 目录,与已有的文件并列。
$ cp usr/include/sys/capability.h /opt/fsl-qoriq/2.0/sysroots/ppce5500-fsl-linux/usr/include/sys/
-
要验证包/库是否成功安装,请运行以下命令:
Shell# 确保从工具链的环境文件中导出 PKG_CONFIG_PATH 变量
$ pkg-config --list-all | grep <package_library_name>
注意: 如果尚未安装,请安装
pkg-config
。
- 要提取 debian 包,请使用
2. 交叉编译库
目标架构的库包不可用,需从源代码编译。在开始编译之前,加载与工具链打包的环境文件,以设置所有必要的参数,用于交叉编译所需。
$ source <env_file_path>
按照库的README文件中提供的编译步骤进行。此外,在构建过程步骤中设置以下参数:
- 运行
./configure
脚本时设置--host 参数
Shell$ ./configure --host=<target_host_parameter>
# 示例:
$ ./configure --host=powerpc-fsl-linux
注意:
- <target_host_parameter> 是为其构建库/工具的系统。可以在工具链的环境文件中找到。它是 $CC、$LD 等中的公共前缀。
- 将有两种类型的依赖库。一种仅在编译过程中需要,另一种是在目标主机上运行时的依赖需求。请相应设置
--host 参数
。
- 在构建依赖库时,使用“make install”时,将DESTDIR设置为工具链的sysroot目录。
Shell
$ make DESTDIR=<toolchain_directory_path> install
示例:
$ make DESTDIR=/opt/fsl-qoriq/2.0/sysroots/ppce5500-fsl-linux/ install
结论
系统架构、库、依赖项和工具链的差异使跨编译成为一种复杂的技术执行方式。为了简化复杂性,本文揭示了跨编译的各个阶段。FRR 和 PowerPC 被作为所需软件和目标硬件的示例。然而,本文中涵盖的步骤为在特定硬件上跨编译任何软件提供了一种合理的策略。环境设置、工具链和依赖项将根据需求有所不同。
Source:
https://dzone.com/articles/heterogeneity-computing-environments-cross-compilation