目录
一. 交叉编译的概念
1.1 宿主机和目标机
宿主机(Host) 是我们编辑和编译程序的平台,一般是基于X86的PC机,也被称为主机。
目标机(Target)是我们的目标运行环境,通常是非X86平台的设备,如树莓派。
1.2 什么是交叉编译
交叉编译是指在一台计算机上进行编译,生成在另一种不同体系结构或操作系统上运行的可执行程序或库文件。它通常用于开发跨平台的软件,或者在资源有限的嵌入式系统上进行开发。
在传统的编译过程中,源代码会被编译成针对本地操作系统和硬件体系结构的机器码。而交叉编译则允许我们在一台计算机上使用特定的工具链,将源代码编译成针对目标平台的机器码。
举个例子:
交叉编译就好像是一种特殊的翻译工作。假设有两个国家,一个是中国,另一个是美国。在中国,人们使用汉语来交流,而在美国,人们使用美语来交流。
现在,我们想要在中国制作一本书,然后在美国出版。但是,问题是美国的人无法理解汉语,所以我们需要将这本书翻译成美语,以便美国的人能够读懂。
1.3 为什么要交叉编译
交叉编译是一种编译方式,它主要用于在一个平台(宿主机)上生成在另一个平台(目标机)上运行的代码。这种方式在嵌入式系统开发中尤为常见,因为这些系统的硬件资源通常有限,无法直接在其上运行复杂的编译器。
1. 平台上不允许或者不能安装我们所需要的编译器:有些平台,例如嵌入式设备,可能由于硬件资源限制(如CPU、内存)或者操作系统的限制,无法直接安装和运行编译器。在这种情况下,我们需要在一台性能更强的主机(如个人电脑)上进行编译,生成目标机可执行的代码。这就是交叉编译。
2. 因为目的平台上的资源匮乏,无法运行我们所需要的编译器:编译器通常需要大量的计算资源和内存空间来运行。对于资源有限的设备(如嵌入式设备、IoT设备),直接在设备上运行编译器可能会导致设备过载甚至崩溃。因此,我们需要在一台资源丰富的主机上进行编译,然后将编译后的代码移植到目标设备上运行。这也是交叉编译的一种应用。
1.4 交叉编译的优点
资源优化:交叉编译允许开发者在具有丰富资源(如高性能处理器、大量内存等)的宿主机上进行编译,这可以极大地提高编译速度并节省目标机的资源。
开发效率:开发者可以在舒适的开发环境中进行开发和编译,而不需要直接在目标机上进行操作。这可以极大地提高开发效率。
兼容性:交叉编译可以产生针对特定硬件和操作系统的特定代码,从而确保软件在目标平台上的最佳性能。
测试和调试:开发者可以在主机上使用强大的测试和调试工具,而不需要在目标机上进行这些操作。
1.5 树莓派是否需要交叉编译
答案是肯定的,有时候确实需要。对于树莓派,尽管它自身可以运行编译器,但在某些情况下,例如在操作系统还未建立,或者需要编译的代码对计算资源要求过高时,我们需要在一台性能更强的主机上进行编译,然后将编译后的代码移植到树莓派上运行。这就是交叉编译的过程。
为了让一个平台运行起来,至少需要两样东西:bootloader(启动引导代码)以及操作系统核心。这两者都是代码,都需要编译。
二. 使用交叉编译
2.1 版本的要求
在Linux上安装交叉编译工具时,版本的选择是非常重要的,因为不同版本的工具链可能支持的语言特性、库和目标平台都有所不同。以下是一些关于版本选择的考虑因素:
目标平台的架构:你需要选择一个支持你的目标平台架构(如ARM、MIPS、PowerPC等)的交叉编译工具链。
操作系统版本:你的目标平台上的操作系统版本也会影响你的选择。例如,如果你的目标平台运行的是一个较旧的Linux内核,你可能需要选择一个兼容这个内核版本的交叉编译工具链。
库的版本:如果你的代码依赖于特定版本的库,你需要确保你的交叉编译工具链支持这些库。否则,你可能需要手动编译和安装这些库。
编程语言的版本:你的代码使用的编程语言和版本也会影响你的选择。例如,如果你的代码是用C++11编写的,你需要选择一个支持C++11的编译器。
主机平台的兼容性:你需要选择一个与你的主机平台兼容的交叉编译工具链。例如,如果你的主机是一个64位的Linux系统,你需要选择一个支持64位的工具链。
2.2 如何安装交叉编译工具链
下面均已ubantu系统和树莓派4B来进行操作
树莓派的硬件架构主要是ARM架构,包括ARMv6、ARMv7和ARMv8(也称为AArch64)。
通常,你可以在树莓派的官方文档或者相关的开发者社区中找到交叉编译工具链的具体版本信息。树莓派的官方GitHub仓库中有一个工具链项目,名为
tools
,该项目包含了用于编译树莓派内核和模块的预编译交叉编译工具链。在大多数情况下,你可以使用最新版本的交叉编译工具链。这是因为新版本的工具链通常包含了对旧硬件架构的支持。
如果你在树莓派上运行
在Ubuntu上,你可以使用以下命令来安装8.3版本的交叉编译工具链:gcc -v
显示的版本是8.3.0,那么你在主机上通常应该安装与之匹配的版本的交叉编译工具链。这是因为,如果你在树莓派上直接编译代码,它会使用这个版本的GCC。因此,为了确保你在主机上交叉编译的结果与在树莓派上直接编译的结果一致,你应该使用同样版本的交叉编译工具链。![]()
sudo apt install gcc-8-arm-linux-gnueabihf /*进行软链接*/ sudo ln -s /usr/bin/arm-linux-gnueabihf-gcc-8 /usr/bin/arm-linux-gnueabihf-gcc
2.3 使用的效果
使用arm-linux-gnueabihf-gcc编译编写好的.c文件
使用scp将编译好的可执行文件拷贝给树莓派4B
在树莓派4B上运行该可执行文件
三. 带wiringPi库的交叉编译
当树莓派的应用场景需要用到wiringPi库中的功能时,我们在ubuntu上编写代码就要加上这个wiringPi库。所以我们要在ubuntu上下载wiringPi库:
下载链接 提取码:8888
并将该库拷贝到相应的路径中
将树莓派中的WiringPi的动态库拷贝到主机当中
在主机中将两个动态库进行软链接
sudo ln -s libwiringPi.so.2.70 libwiringPi.so sudo ln -s libwiringPiDev.so.2.70 libwiringPiDev.so
使用的效果
1. 在主机上编写需要依赖wiringpi库的代码
2. 编译该代码
arm-linux-gnueabihf-gcc test.c -I ./CROSS/WiringPi/wiringPi -L ./CROSS -lwiringPi
出现的错误:
解决错误:
1. 将树莓派中的libcrypt-2.28.so拷贝到主机中
2. 并将该动态库进行软链接
sudo ln -s libcrypt.so libcrypt.so.1
3. 编译该代码
arm-linux-gnueabihf-gcc test.c -I /home/blue/CROSS/WiringPi/wiringPi -L /home/blue/CROSS/ -lwiringPi -Wl,-rpath /home/blue/CROSS/
-Wl,-rpath /home/blue/CROSS/:指定运行时库搜索路径。
4. 将可执行文件拷贝到树莓派4B中并使用
四. 软链接与硬链接
4.1 软链接
软链接,也被称为符号链接(Symbolic Link),是一种特殊的文件类型,主要在Unix和类Unix的操作系统(如Linux)中使用。软链接其实就是一个普通文件,但该文件中包含了另一个文件的路径信息。它的作用可以理解为“快捷方式”,通过软链接,可以快速访问或操作链接所指向的原始文件。
创建软链接的命令通常是
ln -s
,后面跟着两个参数,第一个是原始文件的路径,第二个是软链接文件的路径。例如:ln -s /path/to/original /path/to/link 这将在/path/to/link位置创建一个软链接,指向/path/to/original。
注意:
软链接只是包含了原始文件的路径,而不包含原始文件的内容,因此软链接本身占用的存储空间很小。 如果删除了原始文件,软链接将会变成一个“死链接”,无法再用来访问文件。 如果删除了软链接,对原始文件没有任何影响。
4.2 硬链接
硬链接是 Unix 和 Unix-like 操作系统(比如 Linux)文件系统中的一个概念。硬链接其实就是指向文件系统中的一个 inode 的指针。每一个文件都有一个 inode,它包含了文件的元数据(比如文件大小、创建时间等),同时也指向了存储文件内容的磁盘块。
创建硬链接的命令通常是
ln
,后面跟着两个参数,第一个是原始文件的路径,第二个是硬链接文件的路径。例如:ln /path/to/original /path/to/link 这将在 /path/to/link 位置创建一个硬链接,指向 /path/to/original。
注意:
当你创建一个硬链接时,你实际上是创建了一个新的指针,指向同一个 inode。因此,原始文件和硬链接在文件系统中是等价的,它们都可以用来访问文件的内容。这就意味着,删除原始文件并不会影响到硬链接,因为硬链接仍然指向文件的 inode,所以文件的内容仍然可以通过硬链接来访问。
硬链接有一些限制。首先,硬链接不能跨越不同的文件系统。 其次,硬链接不能链接到目录,只能链接到文件。 最后,如果删除了所有指向一个 inode 的硬链接,那么该 inode 及其关联的磁盘块将被回收,文件的内容将无法访问。
4.3 软链接与硬链接的区别
实现方式:硬链接是对一个文件的 inode 的直接引用,它和原始文件共享同一个 inode,因此具有相同的文件内容和属性。软链接则是一个独立的文件,它的内容是指向另一个文件的路径。
跨文件系统:硬链接不能跨越不同的文件系统,因为不同的文件系统有各自独立的 inode 空间。而软链接则可以跨越不同的文件系统,因为它只是包含了另一个文件的路径。
链接目录:硬链接不能链接到目录,只能链接到文件。而软链接可以链接到目录。
删除原始文件:如果删除了原始文件,硬链接仍然可以访问文件的内容,因为它和原始文件共享同一个 inode。而如果删除了原始文件,软链接就会变成一个“死链接”,无法再用来访问文件。
存储空间:硬链接和原始文件共享同一个 inode,因此不会占用额外的存储空间。而软链接是一个独立的文件,它会占用一些存储空间,但这个空间通常很小,因为它只需要存储另一个文件的路径。
查看链接:硬链接看起来就像一个普通的文件,没有特别的标识来表明它是一个链接。而软链接在列表显示(如 ls -l)时会显示为一个特别的文件类型(l),并显示出它指向的文件路径。