网站建设开题报告ppt模板,商城网站建站系统,泉州网站建设网站制作,免费的企业网站制作Debian或Ubuntu静态交叉编译arm和aarch64 介绍术语ARM架构前置条件从源代码编译一个简单的C程序configure和make交叉编译关于静态链接和依赖关系使用 musl libc 实现与 configure 和 make 进行交叉编译 ARM 正在获得越来越多的关注#xff0c;并且越来越受欢迎。直接在这些基于… Debian或Ubuntu静态交叉编译arm和aarch64 介绍术语ARM架构前置条件从源代码编译一个简单的C程序configure和make交叉编译关于静态链接和依赖关系使用 musl libc 实现与 configure 和 make 进行交叉编译 ARM 正在获得越来越多的关注并且越来越受欢迎。直接在这些基于 ARM 的设备上构建并不总是可能的特别是当它们的资源有限时。大多数构建和开发计算机仍然在 x86 上通过使用交叉编译可以构建可在其他体系结构上使用的二进制文件或可执行文件。例如使用您的标准 PC很可能是 x86来构建可在其他架构例如 ARM上的另一台机器或设备上使用的东西。在这篇文章中我将解释如何使用 Debian 10 或 Ubuntu 20.04 LTS 对 32 位 ARM (arm) 或 64 位 ARM (aarch64) 进行交叉编译。静态编译的好处是减少依赖方便移植。 介绍
对我来说交叉编译功能最常用于构建在基于 Linux 的设备上未安装或不可用的故障排除工具。例如具有自定义 Linux 版本的 Raspberry Pi、NAS、路由器或接入点等设备没有安装附加软件包的选项或安装附加软件包的选项有限。挑选一些设备随机运行一些Linux常用命令输出如下
/ # telnet
/bin/sh: telnet: not found
/ # tcpdump
/bin/sh: telnet: not found
/ # strace
/bin/sh: strace: not found
/ # curl
/bin/sh: curl: not found对于下面的步骤我将使用 Debian 10 (Buster)并且还将在 Ubuntu 20.04.1 (LTS) 上测试相同的步骤。所有步骤都经过验证可以在两者之间互换。两者的起点都是最小安装标准系统实用程序 SSH 服务器。这可以确保如果有人想要重复这些步骤所有内容都是可重现的并且不会跳过或遗漏任何已预安装的内容。
术语
在交叉编译中需要使用以下令人困惑的术语
构建平台构建机器的架构主机平台您正在构建的架构目标平台将处理编译的二进制文件的体系结构
构建和主机或多或少是清晰的但目标可能会令人困惑。简而言之目标仅在使用开发工具如编译器本身时才相关。 当您为与正在使用的相同架构进行构建时构建、主机和目标是相同的。这称为“本机”编译。如果构建和目标平台相同但主机不同那么我们正在讨论交叉编译这是本文所讨论的。这三个平台都不同用于为另一种体系结构构建交叉编译器。
需要明确的是在本文中构建平台和目标平台是 x86_64标准 PC主机是 ARM 平台。我将介绍 32 位 ARMarmv6、armv7 或简称为 arm和 64 位 ARM (aarch64)。
ARM架构
要找出需要编译哪一个32 位或 64 位 ARM最简单的方法是查看 uname -m 的输出。对于X86_64标准PC
jensddeb10:~$ uname -m
x86_6432位ARM
[ap1:~]# uname -m
armv7l64位ARM
rootarmv8:/ # uname -m
aarch64前置条件
在开始编译之前我们需要安装ARM交叉编译所需的软件包和工具。其中包括编译本机所需的标准工具。对于32位ARM(arm)
jensddeb10:~$ sudo apt install gcc make gcc-arm-linux-gnueabi binutils-arm-linux-gnueabi
Reading package lists... Done
Building dependency tree
...
Processing triggers for man-db (2.8.5-2) ...
Processing triggers for libc-bin (2.28-10) ...对于64位ARM(aarch64)
jensddeb10:~$ sudo apt install gcc make gcc-aarch64-linux-gnu binutils-aarch64-linux-gnu
Reading package lists... Done
...
Processing triggers for man-db (2.8.5-2) ...
Processing triggers for libc-bin (2.28-10) ...当然如果您计划针对这两种架构进行编译则可以安装 32 位和 64 位所需的编译器。
从源代码编译一个简单的C程序
一旦我们安装了先决条件我们就可以尝试编译一个简单的 C 程序。首先我们对要进行编译的 PC 进行所谓的本机编译以确保我们的程序能够执行我们想要的操作。将源代码保存为 helloworld.c
#includestdio.h
int main()
{printf(Hello World!\n);return 0;
}本机x86-64编译源代码
jensddeb10:~$ vi helloworld.c
jensddeb10:~$ gcc helloworld.c -o helloworld-x86_64要查看编译结果的类型和平台我们可以使用file工具检查输出
jensddeb10:~$ file helloworld.x86_64
helloworld.x86_64: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]f55972265cd343c3110a5d339d71caeed755c23e, not stripped我们可以执行二进制文件来检查结果
jensddeb10:~$ ./helloworld-x86_64
Hello World!
jensddeb10:~$下一步是为 ARM 编译相同的源代码。我们只需使用不同的编译器对于 32 位 ARM使用 arm-linux-gnueabi-gcc 代替 gcc对于 64 位 ARM 或 aarch64使用 gcc-aarch64-linux-gnu来完成此操作。32位ARM编译
jensddeb10:~$ arm-linux-gnueabi-gcc helloworld.c -o helloworld-arm -static
jensddeb10:~$ file helloworld-arm
helloworld-arm: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), statically linked, for GNU/Linux 3.2.0, BuildID[sha1]971f8b03dcb473de2caa1abbb63990977c6478b3, not stripped64位ARM编译
jensddeb10:~$ aarch64-linux-gnu-gcc helloworld.c -o helloworld-aarch64 -static
jensddeb10:~$ file helloworld-aarch64
helloworld-aarch64: ELF 64-bit LSB executable, ARM aarch64, version 1 (GNU/Linux), statically linked, for GNU/Linux 3.7.0, BuildID[sha1]428239fafd78d5fd28dc400e913618817224ea50, not strippedfile命令行输出给了我们一个不同的结果这是我们所期望的。正如预期的那样尝试在构建机器 (x86_64) 上执行这些二进制文件将导致错误
jensddeb10:~$ ./helloworld-aarch64
-bash: ./helloworld-aarch64: cannot execute binary file: Exec format error
jensddeb10:~$ ./helloworld-arm
-bash: ./helloworld-arm: cannot execute binary file: Exec format error为了测试这是否有效我们需要一台运行我们构建的架构的机器或设备
rootarmv8:/$ uname -a
Linux armv8 4.4.214-armada-17.10.1 #1 SMP Fri Jul 31 23:23:54 UTC 2020 aarch64 aarch64 aarch64 GNU/Linux
rootarmv8:/$ uname -m
aarch64
rootarmv8:/$ wget http://192.168.1.1/helloworld-aarch64
...
helloworld-aarch64 100% |******************************| 557k 0:00:00 ETA
...
rootarmv8:/ # chmod x helloworld-aarch64
rootarmv8:/ # ./helloworld-aarch64
Hello World!上面的输出显示我们的小程序在交叉编译后在 ARM 上运行得很好
configure和make交叉编译
上面的例子非常简单但是当从较大的项目编译源代码时通常是通过使用configure生成一个makefile然后使用make运行编译和其他必要的步骤来完成的。要将 gcc 替换为另一个特定于目标平台的编译器将需要大量工作。幸运的是大多数时候您可以在运行配置时指定要编译的平台。
作为示例我将为 strace 的 ARM aarch64 创建一个二进制文件。为了避免出现与嵌入式 ARM 设备的依赖关系问题我将提供静态选项有关更多说明请参阅下文。
第一步是从 https://github.com/strace/strace/releases/tag/v5.10 获取 strace 的源代码并提取它
jensddeb10:~$ wget https://github.com/strace/strace/releases/download/v5.10/strace-5.10.tar.xz
...
strace-5.10.tar.xz 100%[] 1.77M 2.49MB/s in 0.7s
2021-01-26 16:57:20 (2.49 MB/s) - ‘strace-5.10.tar.xz’ saved [1859688/1859688]
jensddeb10:~$ tar -xf strace-5.10.tar.xz
jensddeb10:~$ cd strace-5.10/
jensddeb10:~/strace-5.10$下一步是运行配置。但这里我们需要指定构建和主机平台以便我们最终得到 ARM 的二进制文件静态链接
jensddeb10:~/strace-5.10$ ./configure --build x86_64-pc-linux-gnu --host aarch64-linux-gnu LDFLAGS-static -pthread --enable-mperscheck
checking for a BSD-compatible install... /usr/bin/install -c
checking whether build environment is sane… yes
checking for aarch64-linux-gnu-strip... aarch64-linux-gnu-strip
...
config.status: creating strace.spec
config.status: creating debian/changelog
config.status: creating config.h
config.status: executing depfiles commands
jensddeb10:~/strace-5.10$此时我们已准备好通过运行 make 来进行实际的交叉编译
jensddeb10:~/strace-5.10$ make
aarch64-linux-gnu-gcc -E -P -DHAVE_CONFIG_H \
...
jensddeb10:~/strace-5.10$ file strace
strace: ELF 64-bit LSB executable, ARM aarch64, version 1 (GNU/Linux), statically linked, for GNU/Linux 3.7.0, BuildID[sha1]db1ce4305df1dac73b81efe99847725d65ac9ab4, with debug_info, not stripped正如您所看到的我构建了这个用于 aarch64 的版本。如果您想对armv6或armv7执行相同的操作只需在运行configure时将–host aarch64-linux-gnu替换为–host arm-linux-gnueabi即可。
为了使其正常工作我传递给 ./configure 的标志和参数有一些额外的解释
checking for library containing timer_create… no
configure: error: failed to find timer_create
was fixed by adding LDFLAGS”-pthread”
checking for m32 personality compile support… no
checking whether to enable m32 personality support… no
configure: error: Cannot enable m32 personality support
was fixed by adding –enable-mperscheck与小型 C 程序一样是时候在 ARM 上测试编译后的二进制文件了
rootarmv8:/data $ uname -a
Linux armv8 4.4.214-armada-17.10.1 #1 SMP Fri Jul 31 23:23:54 UTC 2020 aarch64 aarch64 aarch64 GNU/Linux
rootarmv8:/data $ uname -m
aarch64
rootarmv8:/data $ wget http://192.168.1.1/strace
...
strace 100% |************************| 5989k 0:00:00 ETA
...
rootarmv8:/data $ chmod x strace
rootarmv8:/data $ ./strace -V
strace -- version 5.10
Copyright (c) 1991-2020 The strace developers https://strace.io.
This is free software; see the source for copying conditions. There is NOwarranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.Optional features enabled: no-m32-mpers这使我们能够在随机的 aarch64 机器上简单地复制和使用 strace。
关于静态链接和依赖关系
正如我在一开始提到的我主要使用交叉编译来构建故障排除工具。通常您构建的平台是有限的。这可能是由于缺乏资源例如嵌入式设备造成的。但也因为预构建的软件包要么不可用要么无法安装。在很多情况下这也意味着为您正在构建的任何内容安装依赖项可能会出现问题。显然这些依赖关系也必须针对同一架构构建。
如果您有这种限制或者您只是希望二进制文件在该架构上运行。无需担心依赖项或可能已安装的这些依赖项的冲突旧版本您可以使用静态链接。这意味着在构建时所有必需的依赖项都将包含在二进制文件本身中。
静态链接有一些缺点因为它可能不安全所包含的依赖项不会随系统更新当执行较低级别系统调用的库和生成的二进制文件较大时可能会导致不兼容。在构建故障排除工具时我可以忍受这些事情因为它们不适合长期使用。 虽然静态链接可能是您正在寻找的但它并不总是那么容易实现。尤其是与交叉编译相结合它会让你头疼。大多数工具都依赖于 libc 或 glibc出于我在上一段中提到的充分理由这不鼓励静态链接。幸运的是有一个从头开始开发的 libc 实现它允许对 libc 依赖项进行正确的静态链接musl发音为 musscle。
使用 musl libc 实现与 configure 和 make 进行交叉编译
为了使用 musl我们需要下载正确的版本进行交叉编译。您可以在这里找到完整列表https://musl.cc/#binaries。
下载后我们可以提取存档并测试这是否适用于我们的构建机器
jensddeb10:~$ wget https://musl.cc/aarch64-linux-musl-cross.tgz
...
aarch64-linux-musl-cross.tgz 100%[] 103.69M 6.81MB/s in 16s
2021-01-27 15:19:55 (6.42 MB/s) - ‘aarch64-linux-musl-cross.tgz’ saved [108731156/108731156]
jensddeb10:~$ tar -xvzf aarch64-linux-musl-cross.tgz
aarch64-linux-musl-cross/
aarch64-linux-musl-cross/usr
...
jensddeb10:~$ ./aarch64-linux-musl-cross/bin/aarch64-linux-musl-gcc --version
aarch64-linux-musl-gcc (GCC) 10.2.1 20210116
Copyright (C) 2020 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.接下来我将为 aarch64 构建 TCPdump 的静态链接版本。当您需要记录、调查或排除网络连接故障时它始终是一个方便使用的好工具。不幸的是tcpdump 并不总是可用或者在最好的情况下作为有限的 Busybox 版本。首先我们需要安装一些必需的工具这些工具由 tcpdump 用于构建过程
jensddeb10:~$ sudo apt install flex bison
Reading package lists... Done
Building dependency tree
...
Processing triggers for man-db (2.8.5-2) ...
Processing triggers for libc-bin (2.28-10) ...接下来我们需要下载 tcpdump 和 libpcap 的源代码并解压。您可以在这里找到最新版本https://www.tcpdump.org/index.html#latest-releases
jensddeb10:~$ wget https://www.tcpdump.org/release/libpcap-1.10.0.tar.gz
...
libpcap-1.10.0.tar.gz 100%[] 912.66K 1.51MB/s in 0.6s
2021-01-27 15:20:22 (1.51 MB/s) - ‘libpcap-1.10.0.tar.gz’ saved [934559/934559]
jensddeb10:~$ tar -xvzf libpcap-1.10.0.tar.gz
jensddeb10:~$ wget https://www.tcpdump.org/release/tcpdump-4.99.0.tar.gz
...
tcpdump-4.99.0.tar.gz 100%[] 1.92M 2.57MB/s in 0.7s
2021-01-27 15:21:36 (2.57 MB/s) - ‘tcpdump-4.99.0.tar.gz’ saved [2008080/2008080]
jensddeb10:~$ tar -xvzf tcpdump-4.99.0.tar.gz下载并解压源代码后我们需要首先运行 libpcap 的配置脚本。只是这一次我们需要将编译器设置为 musl-compiler 以进行交叉编译方法是将 CC 设置为aarch64-linux-musl-gcc
jensddeb10:~$ cd libpcap-1.10.0/
jensddeb10:~/libpcap-1.10.0$ CC/home/jensd/aarch64-linux-musl-cross/bin/aarch64-linux-musl-gcc ./configure --build x86_64-pc-linux-gnu --host aarch64-linux-gnu LDFLAGS-static
checking build system type... x86_64-pc-linux-gnu
checking host system type... aarch64-unknown-linux-gnu
...
config.status: creating config.h
config.status: executing default-1 commands如果一切顺利我们可以通过发出 make 来实际编译 libpcap
jensddeb10:~/libpcap-1.10.0$ make
...
config.status: creating pcap-config.tmp
mv pcap-config.tmp pcap-config
chmod ax pcap-config现在我们可以对 tcpdump 本身重复相同的操作./configure 和 make。通过进行静态链接将包含 libpcap结果是单个二进制 tcpdump
jensddeb10:~/libpcap-1.10.0$ cd ../tcpdump-4.99.0/
jensddeb10:~/tcpdump-4.99.0$ CC/home/jensd/aarch64-linux-musl-cross/bin/aarch64-linux-musl-gcc ./configure --build x86_64-pc-linux-gnu --host aarch64-linux-gnu LDFLAGS-static
checking build system type... x86_64-pc-linux-gnu
checking host system type... aarch64-unknown-linux-gnu
checking for aarch64-linux-gnu-gcc... /home/jensd/aarch64-linux-musl-cross/bin/aarch64-linux-musl-gcc
checking whether the C compiler works... yes
...
config.status: creating Makefile
config.status: creating tcpdump.1
config.status: creating config.h
config.status: executing default-1 commands
jensddeb10:~/tcpdump-4.99.0$ make
...
aarch64-linux-gnu-ranlib libnetdissect.a/home/jensd/aarch64-linux-musl-cross/bin/aarch64-linux-musl-gcc -DHAVE_CONFIG_H -I. -I../libpcap-1.10.0 -I/usr/inet6/include -g -O2 -static -o tcpdump fptype.o tcpdump.o libnetdissect.a ../libpcap-1.10.0/libpcap.a
jensddeb10:~/tcpdump-4.99.0$ file tcpdump
tcpdump: ELF 64-bit LSB executable, ARM aarch64, version 1 (SYSV), statically linked, with debug_info, not stripped正如您在最后一个命令中看到的我们有静态链接的 tcpdump 二进制文件。如果一切顺利我们应该能够在基于 aarch64 的机器上执行此操作而无需任何进一步的依赖。
rootarmv8:/$ uname -m
aarch64
rootarmv8:/$ wget http://192.168.1.1/tcpdump
...
tcpdump 100%[] 6.73M --.-KB/s in 0.1s
2021-01-27 13:55:49 (52.5 MB/s) - tcpdump saved [7061368/7061368]
rootarmv8:/$ chmod x tcpdump
rootarmv8:/$ ./tcpdump -i eth0
tcpdump: verbose output suppressed, use -v[v]… for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), snapshot length 262144 bytes
13:57:20.452643 IP 192.168.0.90.34020 192.168.1.10.9000: Flags [S], seq 3386726277, win 64240, options [mss 1460,sackOK,TS val 3092573417 ecr 0,nop,wscale 7], length 0
13:57:20.452715 IP 192.168.1.10.9000 192.168.0.90.34020: Flags [S.], seq 3761157769, ack 3386726278, win 28960, options [mss 1460,sackOK,TS val 4397992 ecr 3092573417,nop,wscale 7], length 0
13:57:20.453325 IP 192.168.0.90.34020 192.168.1.10.9000: Flags [.], ack 1, win 502, options [nop,nop,TS val 3092573418 ecr 4397992], length 0
13:57:20.508762 IP 192.168.1.10.46819 8.8.8.8.53: 15310 PTR? 90.0.168.192.in-addr.arpa. (43)^C
4 packets captured
23 packets received by filter
5 packets dropped by kernel
rootarmv8:/$正如您所看到的tcpdump 工作正常并且不需要任何依赖项。如果您需要在工具集非常有限并且无法轻松安装它们的平台上工作或排除故障这确实很有帮助。您只需复制该文件即可运行。 作者岬淢箫声日期2023年10月31日版本1.0链接http://caowei.blog.csdn.net