【交叉编译】ubuntu安装树莓派工具链与环境变量配置
文章目录
一、什么是交叉编译?
交叉编译:是在一个平台上生成另一个平台上的可执行代码。
- 我们在windows上编写C51或stm32的代码,并通过keil5(集成环境软件)编译成可执行代码,如xx.hex文件,最后是烧录放到C51或者stm32上运行,而不是在windows上运行
- 再比如,我们在linux系统的ubuntu上面编写树莓派的代码,并编译成可执行代码,如a.out,但是要放在树莓派上面运行,不是在ubuntu上运行
编译:是在一个平台上生成在该平台上的可执行代码。
二、为什么要交叉编译?
1.目的平台资源贫乏
平台上不允许或不能够安装并运行我们所需要的gcc等编译器,比如C51,stm32等
2.目的平台尚未建立
平台运行需要两样至少东西:bootloader(启动引导代码)以及操作系统核心
如:树莓派有时又是因为目的平台还没有建立,连操作系统都没有,根本谈不上运行什么编译器。操作系统也是代码,也要编译!
宿主机(host) :编辑和编译程序的平台,一般是基于X86的PC机,如电脑主机,通常也被称为主机。
目标机(target):用户开发的系统,通常都是非X86平台,如ARM树莓派。host编译得到的可执行代码在target上运行。
交叉编译需要用到什么工具?
交叉编译器、交叉编译工具链
三、如何进行交叉编译?
下面,以ubuntu系统上进行树莓派的交叉编译为例,我这里使用的版本是ubuntu-12.04.5-64bit
1.交叉编译工具链的安装
跳转到网址后,再Repositories
下找到tools
点击tool
进到下载页面进行下载即可
下载完毕后,将其上传到ubuntu虚拟机并进行解压,我这里使用的版本是ubuntu-12.04.5-64bit
这边我采用共享文件夹的方式进行上传
上传完成后,一般在能看到我们的共享文件夹,把里面的压缩包拷贝到新建的lessonPi文件夹下
cd /mnt/hgfs //进入共享文件夹的位置
ls //查看共享文件夹
选一个地方新建文件夹,进入新文件夹后,进行拷贝到当前位置,windosShare是我共享文件夹的名字,具体看自己的
cp /mnt/hgfs/windowShare/tools-master.zip .
进行解压
unzip tools-master.zip
解压完成
找到需要用到的软链接,arm-linux-gnueabihf-gcc
cd tools-master/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin
ls
为什么说是是软链接
ls -l
输入指令查看发现,arm-linux-gnueabihf-gcc指向arm-linux-gnueabihf-gcc-4.8.3
为了方便使用,重命名一个arm-linux-gnueabihf-gcc,类似windos的快捷方式
2.配置树莓派gcc的PATH环境变量
①临时有效配置
把arm-linux-gnueabihf-gcc添加到环境路径
先cd到存放arm-linux-gnueabihf-gccd的bin文件夹
echo $PATH //获取环境变量路径
pwd //获取当前路径
然后把红框的部分进行拼接,再进行export命令,将其添加到环境变量
export PATH=/usr/lib/lightdm/lightdm:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/home/CLC/lessonPi/tools-master/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin
此时,cd到外面目录,输入下面蓝框的指令,如果有类似返回值,说明添加成功
cd
arm-linux-gnueabihf-gcc -v
临时有效:在新建终端就不认识了
②永久有效配置
修改工作目录或根目录下的.bashrc 隐藏文件
cd
pwd
vi /pwd获取的工作目录/.bashrc
把刚才的export命令放到最后即可
export PATH=/usr/lib/lightdm/lightdm:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/home/CLC/lessonPi/tools-master/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin
加载配置文件,马上生效配置
source /pwd获取到的工作目录/.bashrc
此时,新建一个终端进行测试,发现都能识别
交叉编译:
检查下交叉编译工具对不对:
输入 arm-linux-gnueabihf-gcc -v
得到 gcc version 4.8.3
3.交叉编译测试
①普通gcc编译
编写一个测试代码test.c
#include <stdio.h>
int main(){
printf("hello\n");
return 0;
}
默认gcc进行编译,并命名为test1
gcc test.c -o test1
查看文件属性,看到test1
只能在x86-64
位运行
file test1 //查看test1文件属性
②树莓派gcc编译
使用树莓派gcc进行编译,并命名为test2
arm-linux-gnueabihf-gcc test.c -o test2
查看文件属性,看到test2
只能在ARM
下运行
file test2 //查看test2文件属性
③验证
把test2
放到树莓派中运行,查看结果如何
如果你的虚拟机和树莓派在同一局域网下,可用下面命令进行远程拷贝
(我这边采用共享文件夹 + FinalShell远程访问工具,反正就是要弄过去)
scp test2 pi@树莓派ip地址:/home/pi
弄过来后,在树莓派上可能会发现运行不了,大概率是权限问题
给它用chmod
指令打开权限后,由原来的白色变成绿色,此时再运行,发现测试成功
sudo chmod 777 test2 //打开全部权限
把test1
也给它拿过来,发现运行不了,验证成功
4.带wiringPi库进行交叉编译
wiringPi库下载并解压好后,通过共享文件夹的方式,拷贝文件夹,上传到虚拟机
windowShare是我共享文件夹的名字,具体看自己/mnt/hgfs目录下的文件名
# -rf 拷贝文件夹
cp /mnt/hgfs/windowShare/wiringPi/ /home/CLC/lessonPi/ -rf
安装
./build
安装完毕
小知识
grep gcc * -nir grep gcc 匹配寻找gcc * 在所有文件下 n 匹配出来的显示行号 i 不区分大小写 r 递归查找,每个目录都找进去
①编译测试
把原来能在树莓派上编译的测试demo1.c
放到ubuntu虚拟机上进行编译
/*demo1.c*/
#include <wiringPi.h>
#include <stdio.h>
int main()
{
int cmd;
if (wiringPiSetup() == -1)
{
printf("硬件接口初始化失败!\n");
return -1;
}
pinMode(7, OUTPUT);
digitalWrite(7, LOW);
while (1)
{
printf("请输入:0或者1,(0-断开开关,1-导通开关)\n");
scanf("%d", &cmd);
getchar();
if (cmd == 1)
{
digitalWrite(7, HIGH);
}
else if (cmd == 0)
{
digitalWrite(7, LOW);
}
}
}
按照原来在树莓派上编译的方式,并用 -I
指定了头文件,最后发现还是编译失败
arm-linux-gnueabihf-gcc demo1.c -I /home/CLC/lessonPi/wiringPi/wiringPi -lwiringPi
②报错分析
报错信息如下
/home/CLC/lessonPi/tools-master/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin/../lib/gcc/arm-linux-gnueabihf/4.8.3/../../../../arm-linux-gnueabihf/bin/ld: cannot find -lwiringPi
collect2: error: ld returned 1 exit status
错误原因
- 因为链接的库的格式不对,是宿主机的平台
file /usr/local/lib/libwiringPi.so.2.46
③解决办法
a.交叉编译wiringPi库(略)
正常我们先要交叉编译wiringPi库,编译出的库适合树莓派,这时候交叉编译可执行程序的试试,链接库的格式也是正确的。
b.从树莓派上拷贝链接库
此时,同样进入/usr/local/lib
树莓派上是已经安装好了的,file查看
libwiringPi.so.2.70
文件属性发现是适用于ARM树莓派安装wiringPi库参考:https://blog.csdn.net/weixin_45444666/article/details/120589157 的方式二
-
把树莓派里的
libwiringPi.so.2.70
拷贝到当前lessonPi文件夹下,不一定是2.70 -
然后创建一个
软链接
来链接它(软链接如上图libwiringPi.so
,是蓝绿色) -
/* ln -s 要被链接的文件 软链接文件名字*/ ln -s libwiringPi.so.2.70 libwiringPi.so
-
ls -l
查看是否有libwiringPi.so -> libwiringPi.so.2.70
,若有,则创建成功 -
进行编译,发现编译成功,即可运行
-
// -L. 指定在当前目录链接库 -I 指定头文件路径 arm-linux-gnueabihf-gcc demo1.c -I /home/CLC/lessonPi/wiringPi/wiringPi -L. -lwiringPi
软链接:
参考文章: https://www.cnblogs.com/zhangna1998517/p/11347364.html
概念:
- 软链接文件有类似于Windows的快捷方式
- 在符号连接中,文件实际上是一个文本文件,其中包含的有另一文件的位置信息
- 你选定的位置上生成一个文件的镜像,不会占用磁盘空间
硬链接:
创建命令:
ln libwiringPi.so.2.50 libwiringPi.so
概念:
它会在你选定的位置上生成一个和源文件大小相同的文件