树莓派交叉编译

目录

一、交叉编译的认知

[1.1 本地编译:](#1.1 本地编译:)

[1.2 交叉编译是什么:](#1.2 交叉编译是什么:)

[1.3 为什么要交叉编译:](#1.3 为什么要交叉编译:)

[1.4 什么是宿主机?什么是目标机?](#1.4 什么是宿主机?什么是目标机?)

[1.5 如何进行交叉编译:](#1.5 如何进行交叉编译:)

二、交叉编译工具链的安装

[2.1 下载交叉编译工具:](#2.1 下载交叉编译工具:)

[2.2 将交叉编译工具链添加到环境变量:](#2.2 将交叉编译工具链添加到环境变量:)

[2.2.1 临时有效的添加环境变量:](#2.2.1 临时有效的添加环境变量:)

[2.2.2 永久有效的添加环境变量:](#2.2.2 永久有效的添加环境变量:)

三、交叉编译实战

[3.1 交叉编译实战(一):](#3.1 交叉编译实战(一):)

[3.2 交叉编译实战(二):](#3.2 交叉编译实战(二):)

四、带WiringPi库的交叉编译实战

[4.1 交叉编译WiringPi库:](#4.1 交叉编译WiringPi库:)

[4.2 把树莓派的WiringPi库拿来](#4.2 把树莓派的WiringPi库拿来)

[4.2.1 将树莓派的libwiringPi.so.2.52上传到虚拟机:](#4.2.1 将树莓派的libwiringPi.so.2.52上传到虚拟机:)

[4.2.2 创建软链接:](#4.2.2 创建软链接:)

[4.2.3 交叉编译:](#4.2.3 交叉编译:)


一、交叉编译的认知

编译 是指将源代码文件(如C/C++文件)经过预处理、编译、汇编和链接等步骤,转换为可执行文件的过程将源代码转换成机器代码的过程称为编译(Compile),编译的工作需要编译器(Complier)来完成。

1.1 本地编译:

  • 本地编译是指在当前的编译平台上,生成能在当前平台上运行的可执行文件。

例如,在x86平台上,使用 x86平台上的工具,开发针对x86平台本身的可执行程序,这个编译过程称为本地编译。 以一个简单的例子来说明本地编译,假设有一个hello.c文件,它包含以下内容:

cpp 复制代码
#include <stdio.h>

int main()
{
	printf("Hello World\n");
	return 0;
}

我们想要在x86平台上进行本地编译,并在x86平台上运行这个程序。可以使用以下命令:

cpp 复制代码
gcc hello.c -o hello

1.2 交叉编译是什么:

  • **交叉编译 是在一个平台上生成另一个平台上的可执行代码。**例如:
  1. 我们再windows上面编写C51代码,并编译成可执行代码,如xx.hex,是在c51上面运行,不是在windows上面运行

  2. 我们在ubuntu上面编写树莓派的代码,并编译成可执行代码,如a.out,是在树莓派上面运行,不是在ubuntu linux上面运行

1.3 为什么要交叉编译:

  1. 平台上不允许或不能够安装我们所需要的编译器 ,比如C51,因为目的平台上的资源贫乏,无法运行我们所需要编译器

  2. 树莓派比C51内存大的多,是不是就不需要交叉编译了?错,也要!树莓派有时又是因为目的平台还没有建立,连操作系统都没有,根本谈不上运行什么编译器。操作系统也是代码,也要编译! 因为平台运行需要两样至少东西:bootloader(启动引导代码) 以及操作系统核心

1.4 什么是宿主机?什么是目标机?

  • 宿主机 (host) :编辑和编译程序的平台,一般是基于X86的PC机,通常也被称为主机。

  • 目标机 (target):**用户开发的系统,通常都是非X86平台。**host编译得到的可执行代码在target上运行。

1.5 如何进行交叉编译:

  • 交叉编译需要用到工具,一般称作为:交叉编译器 或者交叉编译工具链

二、交叉编译工具链的安装

2.1 下载交叉编译工具:

cpp 复制代码
https://github.com/raspberrypi/tools

然后把我们下载下来的压缩文件通过FileZilla上传到我们的虚拟机上面:

然后使用下面指令解压:

cpp 复制代码
unzip tools-master.zip

解压之后我们进入下面这个路径下:

进入到该路径后我们可以看到:arm-linux-gnueabihf-gcc 这个软链接是指向arm-linux-gnueabihf-gcc-4.8.3的,软链接是不占内存的,作用就是指向真正的可执行程序,在使用中就可以使用软链接的名字来调用真正的可执行程序。

所以arm-linux-gnueabihf-gcc就是我们树莓派的交叉编译工具链,使用和gcc是一样的,比如:XXX.c,编译的语句是:

cpp 复制代码
./arm-linux-gnueabihf-gcc XXX.c 	//只不过把"gcc"替换成了"./arm-linux-gnueabihf-gcc"

2.2 将交叉编译工具链添加到环境变量:

现在我们已经拥有了交叉编译工具链,我们知道我们的交叉编译工具链在下面这个路径下:

cpp 复制代码
/home/shiyahao/lessonPi/tools-master/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin

我们在编译的时候还要将这么长的路径加到我们交叉编译之前,就会让我们的编译变得非常的繁琐和麻烦,我希望我们在使用这个交叉编译工具链的时候可以像gcc那样,不管在什么路径下都可以编译,这样就得配置环境变量了

2.2.1 临时有效的添加环境变量:

临时的添加环境变量,其实在前几节学习动态库的制作时就有提到过,那就是使用export ,临时的意思就是"仅在添加完环境变量后的当前窗口有效",也就是说如果再开一个窗口就又识别不到新添加的环境变量了。

  • 使用下面指令查看当前的环境变量:
cpp 复制代码
echo $PATH

这一长串中:前面的**/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games: 是不变的**,然后使用下面指令来添加我们新的环境变量:

cpp 复制代码
export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:想要添加的路径
cpp 复制代码
export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/home/shiyahao/lessonPi/tools-master/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin

运行之后我们退回到根目录下,也就是**/home/shiyahao**下,然后输入下面指令:

cpp 复制代码
arm-linux-gnueabihf-gcc-4.8.3 -v		//-v查看编译信息

我们可以看到在其他路径下我们可以暂时使用交叉编译器了 ,此时我们新开一个终端窗口,再次输入arm-linux-gnueabihf-gcc -v就无法识别了,所以这个环境变量只能临时有效。

2.2.2 永久有效的添加环境变量:

临时有效虽然一句命令就能搞定,但是有风险,因为终端随时可能关闭,然后添加的临时环境变量就失效了,所以还是学习一下如何一劳永逸的修改环境变量:

  • 修改工作目录下的 .bashrc 隐藏文件(该文件用于配置命令终端的
cpp 复制代码
vi /home/shiyahao/.bashrc

然后在文件的末尾添加我们的交叉编译工具链的路径:

其实,bashrc隐藏文件 就是一个脚本,永久有效的核心思路就是通过脚本自动运行export,和动态库写脚本写export的思路是一样的。

  • 然后运行下面指令,用于加载配置文件,生效配置
cpp 复制代码
source /home/shiyahao/.bashrc

此时我们再开一个新的终端,并运行arm-linux-gnueabihf-gcc-4.8.3 -v

可见,这样就永久有效的将交叉编译器的目录添加到了环境变量中去了!

三、交叉编译实战

3.1 交叉编译实战(一):

现在在我们的宿主机的根目录下有一个hello.c文件,我们通过gcc编译器编译出可以在本机X86平台上运行的程序,我们可以通过下面指令查看:

cpp 复制代码
file 程序名

我们可以看到这个程序只能在X86-64平台上运行,是不能在我们的树莓派ARM平台上运行的,我们想要在我们的树莓派ARM平台上运行,我们就得用基于树莓派ARM平台的交叉编译器来编译arm-linux-gnueabihf-gcc-4.8.3

我们看到编译出来的程序是在ARM平台上运行的,我们把它拷贝到树莓派上,指令如下:

cpp 复制代码
scp hello_2 pi@192.168.31.123:/home/pi

可以看到我们交叉编译的程序成功在树莓派上运行

3.2 交叉编译实战(二):

cpp 复制代码
arm-linux-gnueabihf-gcc-4.8.3 clientFTP.c -o RaspberryclientFTP		//交叉编译FTP客户端代码
file RaspberryclientFTP												//产看文件属性
scp RaspberryclientFTP pi@192.168.31.123:/home/pi					//将我们交叉编译出来的程序上传到树莓派

可以看到我们成功的交叉编译了FTP的客户端程序,并成功在树莓派上运行,实现了宿主机和树莓派之间的FTP通信

四、带WiringPi库的交叉编译实战

在之前的交叉编译实战中,成功的将Ubuntu虚拟机上面的代码交叉编译成了能够在树莓派上运行的程序,但是之前的交叉编译代码不需要链接库,如果代码包含了WiringPi库或者线程库,那么在gcc编译时就需要链接库,对于这种需要链库的C代码进行交叉编译不能直接无脑的在"arm-linux-gnueabihf-gcc XXX.c"后加上"-lwiringPi",其原因是库文件也是当前平台下的文件,并不能被树莓派平台所识别!

  • 首先先将我们的WiringPi库上传或者下载到我们的根目录(home/CLC)下:
  • 然后进入这个文件夹后,运行build安装:
  • 在**/usr/local/lib/**路径下就可以看到这个wiringPi的动态库:
  • 通过file指令查看文件属性:

可以看到这个动态库只能在当前平台(X86-64)上运行,是不能在我们的ARM树莓派平台上运行的,所以我们这里有两种方法:

4.1 交叉编译WiringPi库:

既然这个库文件无法被树莓派平台识别,那就先交叉编译库文件,再链库并交叉编译代码,但是对于动态库的交叉编译和之前的方法可能不同,所以这种方法暂时不展开。

4.2 把树莓派的WiringPi库拿来

4.2.1 将树莓派的libwiringPi.so.2.52上传到虚拟机:

直接把树莓派上面使用的WiringPi拿过来也可以解决我们的问题:

cpp 复制代码
cd /usr/lib		//进入树莓派/usr/lib目录下
ls				//查看当前目录下的文件

然后通过file指令查看该文件的属性:

然后通过下面指令发送到我们的虚拟机上面:

cpp 复制代码
scp /usr/lib/libwiringPi.so.2.52 CLC@192.168.31.90:/home/CLC/lessonPi
4.2.2 创建软链接:

参考文章:Linux创建连接命令 ln -s创建软连接 - 张娜nana - 博客园 (cnblogs.com)

  • 软链接的概念:
  1. 软链接文件有类似于Windows的快捷方式。

  2. 在符号连接中,文件实际上是一个文本文件,其中包含的有另一文件的位置信息。

  3. 你选定的位置上生成一个文件的镜像,不会占用磁盘空间

  • 硬链接的概念:
  1. 它会在你选定的位置上生成一个和源文件大小相同的文件
  • 硬链接如何生成:
cpp 复制代码
ln libwiringPi.so.2.52 libwiringPi.so
  • 软链接如何生成:
cpp 复制代码
ln -s libwiringPi.so.2.52 libwiringPi.so 
指令 参数   要被链接的文件    软链接文件名字

然后再通过file命令查看一下虚拟机的libwiringPi.so.2.52的文件属性:

确实是树莓派ARM平台上的WiringPi动态库

4.2.3 交叉编译:

现在有了树莓派ARM平台上的WiringPi库,可以尝试交叉编译带有WiringPi库的C代码了,比如下面这个代码:

cpp 复制代码
#include <stdio.h>
#include <wiringPi.h>
 
#define BEEP 7
 
int main (void)
{
 
	wiringPiSetup () ; //初始化wiringPi库
 
	pinMode (BEEP, OUTPUT); //配置输入输出模式
 
	while(1){
		digitalWrite (BEEP, LOW) ;	//蜂鸣器响
		delay (1000) ;		// mS
 
		digitalWrite (BEEP, HIGH) ;	//蜂鸣器不响
		delay (1000) ;
	}
 
	return 0;
}

然后使用下面指令进行交叉编译:

cpp 复制代码
arm-linux-gnueabihf-gcc beep.c -L ./ -lwiringPi -I /home/CLC/WiringPi/wiringPi -o BEEP
  • 使用"-L ":指定动态库的优先查找目录为当前目录

  • 使用"-I"(大写i):指定头文件的优先查找目录为/home/mjm/WiringPi/wiringPi

我们在编译的时候出错了,然后重新向虚拟机导入版本2.50的wiringPi动态库,然后重新生成软链接,然后在编译就OK了

使用下面指令将交叉编译出来的BEEP程序上传到树莓派:

cpp 复制代码
scp BEEP pi@192.168.31.123:/home/pi/waishe

然后在树莓派上成功运行,蜂鸣器开始了滴滴声

相关推荐
我们的五年1 分钟前
【Linux课程学习】:进程描述---PCB(Process Control Block)
linux·运维·c++
我言秋日胜春朝★1 小时前
【Linux】进程地址空间
linux·运维·服务器
C-cat.1 小时前
Linux|环境变量
linux·运维·服务器
yunfanleo1 小时前
docker run m3e 配置网络,自动重启,GPU等 配置渠道要点
linux·运维·docker
糖豆豆今天也要努力鸭2 小时前
torch.__version__的torch版本和conda list的torch版本不一致
linux·pytorch·python·深度学习·conda·torch
烦躁的大鼻嘎2 小时前
【Linux】深入理解GCC/G++编译流程及库文件管理
linux·运维·服务器
ac.char2 小时前
在 Ubuntu 上安装 Yarn 环境
linux·运维·服务器·ubuntu
敲上瘾2 小时前
操作系统的理解
linux·运维·服务器·c++·大模型·操作系统·aigc
长弓聊编程2 小时前
Linux系统使用valgrind分析C++程序内存资源使用情况
linux·c++
cherub.3 小时前
深入解析信号量:定义与环形队列生产消费模型剖析
linux·c++