《树莓派实战秘籍》——第 2 章 为树莓派做Linux黑客 2.1 技巧21建立交叉编译器工具链

简介:

本节书摘来自异步社区《树莓派实战秘籍》一书中的第2章,第2.1节,作者: 【美】Ruth Suehle , Tom Callaway 更多章节内容可以访问云栖社区“异步社区”公众号查看。

第 2 章 为树莓派做Linux黑客

虽然树莓派有很多可用的操作系统,但支持得最好的一个肯定是Linux,树莓派基金会通过维护一个Linux内核源代码树的方式保持了对树莓派的硬件支持。

Linux以其灵活性和对大量设备的支持而著名。无论你是刚刚开始有兴趣学习Linux,或者准备对Linux动手改造以成为一个令人敬服的黑客,本章都将帮助你完成这一过程。

本文仅用于学习和交流目的,不代表异步社区观点。非商业转载请注明作译者、出处,并保留本文的原始链接。

2.1 技巧21建立交叉编译器工具链

树莓派适合用来做很多事情,不过编译速度可不是它的强项。如果希望在一个合理的时间内从源代码生成什么的话,这时候你就需要在一台更高速的计算机上运行交叉编译器了。

交叉编译器是一种建立并运行在某一架构上,但是生成另一种架构上适用的二进制文件的编译器(及其依赖库),而这两种架构通常是不相容的。在本例中,你需要建立一个交叉编译器,以为树莓派的Linux环境生成优化过的二进制文件。

类似于Linux上的大多数任务,你可以有几种方法构建交叉编译器,只要能保证最终使用的工具链可以在树莓派上达到最佳性能优化即可。我们建议不要安装Linux发行版上预打包的交叉编译器,相反,下面的章节将引导你如何使用crosstool-ng工具从无到有的打造交叉编译器。

2.1.1 安装crosstool-ng工具

crosstool-ng是为了帮助你完成生成编译器工具链这样复杂任务而设计的,它提供了一个功能强大的前端与构建脚本,可以让你选择需要让工具链完成的功能,然后自动生成,而这个过程中你并不需要去确切的了解这些无数工具链是如何组织在一起的。

相比于手动构建交叉编译器,这就是个救命神器。

crosstool-ng使用与Linux内核源码相同的配置前端技术构建,因此它使用的菜单结构与你熟悉的Linux内核类似,其中许多选项可能对你并无意义,有些可能看上去很相似,容易混淆。不必害怕,勇敢的黑客!你只需要在默认配置上改变很少一些选项就可以了。

现在你可以把树莓派放在一边,目前并不需要它。相反,你需要从一个x86系统运行你喜欢的Linux发行版,任何你使用方便并包含一个可工作的编译器的发行版本都可以。至于系统配置,当然是越大越好,更多的CPU核心和更大的内存将会使构建更快,而x86_64总会是首选。此外,你还应该有一个无故障的可用磁盘空间(10GB应该绰绰有余了)。

要构建交叉编译工具链,首先需要保证有一些开发组件。具体来说,你需要有一个本地编译器(在本例中是支持C和C++的GCC)、libstdc(标准C++库,包括共享和静态库)、libtool和make(用于基础构建)、GNU MP(用于高效精确数学计算)、gperf(一个完美的哈希函数发生器)、bison(C语法解析器)、flex(词法模式识别引擎)、ncurses(终端图形库)、sed(流编辑器)、subversion(访问SVN代码库的客户端工具)、texinfo(一个文档生成和解析工具)等。

不用对这些工具太过担心,因为你并不需要知道它们是如何工作的(甚至不必了解为什么需要它们),只要知道这么做就可以了。实际上,所有你需要做的就是安装这些工具。你可以通过下列命令完成安装:

对于Fedora系统,输入:


screenshot

对于Ubuntu系统,输入:


screenshot

libtool sed subversion libgmp-dev libstdc++-dev'1

接下来,下载一份crosstool-ng2源代码的副本。当撰写本书之时,其最新的版本为1.18.03。

将crosstool-ng的源打包压缩文件解压到你的home目录:


screenshot

修正PPL问题

crosstool-ng使用的帕尔马多面体库(PPL,Parma Polyhedra Library)版本里面有一个错误,具体来说,它和较新版本的GNU多精度运算库(GMP,GNU Mutiple Precision Arithmetic Library)不兼容。我们提供了修补此问题的补丁文件,以允许PPL在较新版本的GMP下正确编译。在我们的GitHub仓库中有一个名为101-gmp-build-fix.patch的文件,首先,从这个GitHub版本树(https://github.com/spotrh/rpihacks)中克隆一份本地拷贝到你的home目录,然后将补丁文件复制到crosstool-ng的源代码目录:

65b

将此补丁文件放置在crosstool-ng-1.18.0/patches/ppl/0.11.2/目录下,这样crosstool-ng在编译之前可以使用补丁修正到PPL 0.11.2中。

如果系统使用的是旧的GMP版本,则此补丁可能并不需要,不过打上也不会造成任何问题。我们强烈建议你在进行下一步之前将此补丁文件拷贝到crosstool-ng补丁目录中。

2.1.2 配置crosstool-ng

进入crosstool-ng-1.18.0目录中并运行configure。你需要传递的唯一选项是一个prefix值:其指定了安装crosstool-ng的位置。我们强烈建议你使用/opt/crosstool-ng-1.18.0作为安装目录,以保证安装位置足以远离Linux系统的其他部分:


screenshot

几乎和以往创建的其他配置脚本一样,这个配置脚本也会检查你的Linux系统,以确保所有crosstool-ng的依赖已经安装并且可以引用。如果检查失败的话,简单地使用你的Linux发行版本的相应工具(根据相应的发行版使用yum或apt-get)安装缺少的包即可4。安装完成之后将创建一个Makefile文件,要生成crosstool-ng代码,运行:


screenshot

生成会很顺利,因为crosstool-ng并不难构建。完成之后,你需要运行make install将之安装到新的位置(/opt/crosstoolng-1.18.0)即可。下面的命令不要忘记以root用户运行:


screenshot

2.1.3 将crosstool-ng加入到你的路径

现在,你已经安装并配置好crosstool-ng软件,将它加入到你的路径中去,可以让你在运行crosstool-ng命令时不必输入一个很长的命令字符串。

根据Linux发行版和shell选项的不同,最简单的加入方式也会有所不同。如果是Fedora系统,使用的是缺省的bash shell,需要修改~/.bash_profile。如果是Ubuntu系统,则需要编辑~/.profile文件。需要修改的文件是一个配置文件(或以点开头的文件5),位于home目录下且设置了PATH变量。一般来说,这个文件包含了明确输出PATH变量的一行,如下所示:


screenshot

在这一行的上面,添加如下一行:


screenshot

这将追加/opt/crosstool-ng-1.18.0/bin到已有变量PATH($PATH)的后面。保存文件,然后你可以打开一个新的shell实例,或者source修改后的文件。由于我们是勇敢的黑客,所以我们只采取source新文件的方式,方式如下:


screenshot

如果你使用的shell不是bash,以上指令会有所不同。不过如果你做出这样的选择,证明上述章节的大部分内容对你只不过是常识而已,你应该能够搞定在你选择的shell中添加一个目录到PATH变量中去这个任务。

2.1.4 配置交叉编译器

现在是时候真正构建树莓派的交叉编译器了。在构建过程中,crosstool-ng会从Internet上下载相当多的源文件,为了保持整洁,你应该建立一个临时的存放目录(sandbox目录),并于此目录下展开工作:


screenshot

现在你可以通过运行下面的命令放心地启动crosstool-ng的配置实用程序了:


screenshot

crosstool-ng支持种类众多、各不相同的工具链及这些工具链的子变体。为了获得最佳的优化,我们推荐使用GCC编译器的Linaro变体。Linaro是一个非营利组织,专门优化和改进ARM平台的开源技术,他们往往能做出最好的ARM Linux编译器。

对应上述推荐,接下来你要建立一个Linaro的GCC交叉编译器,并专门针对树莓派的内部硬件做了优化。

在GCC语言中,这是一个arm-bcm2708hardfp-linux-gnueabi工具链。bcm2708描述了特定的CPU类型(Broadcom 2708),hardfp表示它使用了一个硬件浮点单元(具体来说,意思是传递给函数的值位于浮点寄存器中),linux是操作系统类型,gnueabi表示其支持GNU嵌入式应用程序二进制接口(EABI,Embedded Application Binary Interface),EABI允许不同的编译器生成兼容代码。

虽然crosstool-ng的大多数设置使用其缺省值就可以了,但你仍需要仔细检查其中的一些值。当你启动ct-ng的menuconfig时,它会在终端窗口打开一个文本用户界面(简称TUI,Text User Interface),并呈现一系列菜单,你可以使用箭头键、回车键(选择一个项目或菜单)、空格键(启用或禁用指定项目)来浏览菜单项。对于已经启用的项目旁边会有一个星号或设定值。

顶层菜单如图2-1所示。


screenshot

以下各节描述了你需要做出的更改,按照菜单结构从上往下分别阐述。

路径和其他选项(Paths and Misc Options)

在本节中的crosstool-ng菜单(如图2-2所示),进行了如下更改。


screenshot

  • 启用“Try features marked as EXPERIMENTAL”。
  • 将“Prefix directory”设置成你希望交叉编译工具链的安装位置。我们建议将其放在/opt目录或者你的home目录下单独的子目录中,以确保你的交叉编译工具链不和系统原生的工具链混淆。我们保留了其默认值${HOME}/x-tools/${CT_ TARGET},其实际为~/x-tools/arm-rpilinux-gnueabi/目录。
  • 设置“Number of parallel jobs”。这个值被传递给make命令,用来加速交叉编译工具链的构建时间。将此值设置得过低将使得构建时间比其需要的更长,但设置得过高将导致CPU的资源被过度分散(也将使编译时间比它需要的更长)。这个有魔力的值似乎应该是你的系统的CPU核数再乘以1.5,我们的八核笔记本上这个值是12。如果你不知道你的系统有多少CPU核,可以运行:


screenshot

计算输出行的数目,因为Linux将每一个CPU核都看做唯一的处理器。

目标选项(Target Options)

在这个菜单(如图2-3所示)里,确认以下设置被配置。

  • 设置“Target architecture”为arm。
  • 设置“Endianness”为Little endian。
  • 设置“Bitness”为32-bit。


screenshot

上述所有设置一般都是默认值,不过随后的设置就不一定如此了。进行如下更改可以调整交叉编译工具链为树莓派生成最佳的二进制文件。

  • 设置“Architecture level”为armv6zk。这是树莓派ARM CPU的特定ARM架构版本。
  • 设置“Emit assembly for CPU”为arm1176jzf-s。
  • 设置“Tune for CPU”为arm1176jzf-s。
  • 设置“Use specific FPU”为vfp。
  • 设置“Floating point”为hardware(FPU)。
  • 设置“Default instruction set mode”为arm。
  • 启用“Use EABI”选项。

工具链选项(Toolchain Options)

在工具链选项(图2-4)中做如下修改。

  • 设置“Tuple's vendor string”为rpi。实际上,这里可以填上任何我们想填的字段。我们强烈建议你这么写的目的是为了让你清楚你正在使用的是树莓派的交叉编译工具链。


screenshot

操作系统选项(Operating System Options)

在操作系统选项(如图2-5所示)中做如下修改。

  • 设置“Target OS”为linux。
  • 设置“Linux kernel version”为3.6.11(你的树莓派也许运行的还不是3.6.11内核,但这是一个安全的设置值)。


screenshot

二进制实用工具选项(Binary Utilities Options)

在二进制实用工具选项(图2-6)中做如下修改。

  • 设置“Binary format”为ELF。
  • 设置“binutils version”为2.22。


screenshot

C编译器选项(C Compiler Options)

在C编译器选项(如图2-7所示)中做如下修改。


screenshot

  • 启用“Show linaro versions”。
  • 设置“gcc version”为linaro-4.7-2013.01(如果你在阅读本书时有新的版本,大可随意尝试它)。
  • 启用“C++”。
  • 设置“gcc extra config”为 --with-float=hard。
  • 启用“Link libstdc++ statically into gcc binary”。

C库选项(C-library Options)

在C库选项(如图2-8所示)中做如下修改。


screenshot

  • 设置“C library”为“eglibc”。
  • 设置“eglibc version”为“2_13”。

这样就完成了配置部分。然后进入主界面,退出,并在提示时(选择YES)保存配置文件。

禁用CT_WANTS_STATIC_LINK

在某些系统上,crosstool-ng会默认设置CT_WANTS_STATIC_LINK值为Y(即使你没有这样选择),这将导致它在构建过程的早期失败。不过你可以使用sed命令来确保其被禁用,运行此命令:


screenshot

这个命令可能看上去很复杂,但它所做的事情是搜索和CT_WANTS_STATIC_LINK相匹配的字符串且被启用的选项,如果找到,则使用禁用字符串将其替代,从而通过这种方法来禁用crosstool-ng配置文件中的CT_WANTS_STATIC_LINK特性。

2.1.5 开始构建

现在,你只需要启动构建过程即可:


screenshot

接下来,它会下载所有它需要的东西并建立你的树莓派优化交叉编译工具链。这个过程是最长的部分,时间根据你的系统配置和网络速度而有所不同,但在一个性能强劲的笔记本上,如果花费了45分钟至1个小时或更长时间是不太可能的。

当上述过程成功之后,你拥有了一个位于~/x-tools/arm-rpi-linux-gnueabi/bin目录的交叉编译器。你需要将这个目录添加到PATH中,可以使用你在前面添加crosstool-ng目录相同的方式。在你要添加的行中将这句:


screenshot

更改为:


screenshot

保存文件,然后再次source文件以更新PATH值。现在你可以通过运行如下命令来测试你的工具链了:


screenshot

这将返回大量信息,如gcc是如何配置与优化,以及打印出的编译器版本等。如果看到这些,你的树莓派交叉编译器已经随时可用了。

相关文章
|
2天前
|
Linux 编译器 Android开发
FFmpeg开发笔记(九)Linux交叉编译Android的x265库
在Linux环境下,本文指导如何交叉编译x265的so库以适应Android。首先,需安装cmake和下载android-ndk-r21e。接着,下载x265源码,修改crosscompile.cmake的编译器设置。配置x265源码,使用指定的NDK路径,并在配置界面修改相关选项。随后,修改编译规则,编译并安装x265,调整pc描述文件并更新PKG_CONFIG_PATH。最后,修改FFmpeg配置脚本启用x265支持,编译安装FFmpeg,将生成的so文件导入Android工程,调整gradle配置以确保顺利运行。
22 1
FFmpeg开发笔记(九)Linux交叉编译Android的x265库
|
1月前
|
数据建模 Linux C++
linux交叉编译live555
linux交叉编译live555
32 1
|
1月前
|
Linux
linux 交叉编译libpng,libjpeg库
linux 交叉编译libpng,libjpeg库
22 1
|
12天前
|
存储 算法 Linux
【实战项目】网络编程:在Linux环境下基于opencv和socket的人脸识别系统--C++实现
【实战项目】网络编程:在Linux环境下基于opencv和socket的人脸识别系统--C++实现
32 6
|
1月前
|
存储 Linux 编译器
Linux 交叉编译第三方库需要设置的环境变量
Linux 交叉编译第三方库需要设置的环境变量
23 0
|
16天前
|
Linux 计算机视觉
Linux交叉编译opencv并移植ARM端
通过以上步骤,你可以在Linux上交叉编译OpenCV,并将生成的库文件和头文件移植到ARM平台上,从而在ARM上使用OpenCV。 买CN2云服务器,免备案服务器,高防服务器,就选蓝易云。百度搜索:蓝易云
33 0
|
1月前
|
算法 Linux 调度
根基已筑!Anolis OS 23.1 预览版本搭载 Linux 6.6 内核和工具链升级完成
Anolis OS 23.1 对软件包的选择和组合进行了重新规划与决策,满足更为广泛的应用场景需求。
|
1月前
|
存储 缓存 Linux
Linux 系统调用深思:从原理到实战
Linux 系统调用深思:从原理到实战
39 1
|
1月前
|
Linux 编译器
Linux交叉编译libunwind
Linux交叉编译libunwind
28 0
|
1月前
|
Linux
Linux 交叉编译qt源码安装 注意项/建议
Linux 交叉编译qt源码安装 注意项/建议
10 0