• 树莓派之交叉编译,如何获得交叉编译工具链,以及带有wiringPi库的交叉编译如何处理


    一、首先我们来认清楚交叉编译是什么,为什么要进行交叉编译?
    (1)什么是交叉编译?
    答:交叉编译是在一个平台上生成另一个平台上的可执行代码。
    例如:我们在Windows平台上编写的C51的代码,并编译成在C51上可执行的代码,例xxx.hex文件,这个文件是在C51上运行的并不是在Windows上运行的

    什么是编译呢?
    答:编译就是在一个平台上生成在该平台上的可执行代码
    例如:C51和stm32 的交叉编译发生在keil(集成环境上面)
    
    • 1
    • 2
    • 3

    (2)为什么要进行交叉编译呢?
    原因:平台上不允许或不能够安装我们所需要的编译器,比如C51
    a.因为目的平台上的资源贫乏,无法运行我们所需要的编译器
    b.既然树莓派有自己的操作系统(linux),那么树莓派是不是不需要进行交叉编译呢?
    答:这是错的,树莓派也要进行交叉编译
    树莓派有时候也是因为目的平台还没有建立,连操作系统都没有,根本谈不上运行什么编译器,操作系统也是代码,也是需要进行编译的。

    平台运行至少需要两样东西:BootLoader(启动引导代码)以及操作系统核心

    c.那么什么是宿主机(host)和目标机(target)呢?
    答:宿主机:编辑和编译程序的平台,一般是基于X86PC机,通常也被称为i而主机
    目标机:用户开发的系统,通常都是非X86平台,宿主机编译得到的可执行的代码在目标机上运行

    d.交叉编译需要用到的 工具有哪些?
    交叉编译器、交叉编译工具链
    那么接下来我们就来讲一下交叉编译工具链

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

    1.交叉编译工具链的安装网址
    进入网址后选tools
    在这里插入图片描述
    选择tools之后选右上角的Code,再选择Code底下的Download ZIP,这样就能够将交叉编译工具链的压缩包下载回来了
    在这里插入图片描述

    2.交叉编译工具链的压缩包下载好了之后,我们就来解压一下压缩包(这些操作都是在linux虚拟机下进行的)
    a.记得在上面的交叉编译工具链压缩包的下载的时候尽量将压缩包下载回到windowslinux的共享文件夹中,这样方便进行解压,用FileZilla进行文件的传输也是可以的,无论是共享文件夹还是FileZilla都只是文件传输的一种手段而已

    b.在linux的工作目录下新建一个新的目录lessonPi(这个都是随意的啦,每个人都不一样的,到时候配置环境变量的时候能够找到这个路径即可)
    1)进入新建的目录/home/CLC/lessonPi
    从共享文件夹中拷贝交叉编译工具链的压缩包到当前目录
    cp /mnt/hgfs/sharefromwindows/tools-master.zip . 千万别漏了这个.,这个.的意思是表示当前目录的意思(上面那个路径是我虚拟机上跟Windows的共享文件夹的路径,每个人的都不尽相同)

    2)将压缩包拷贝过来了之后就是将压缩包进行解压了
    用指令 unzip tools-master.zip 进行解压

    3)解压完了之后进入到交叉编译工具链所在的路径
    cd /home/CLC/lessonPi/tools-master/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin
    进入到这个路径底下之后,用pwd指令打印出这个路径,然后复制下来
    我们看到很多可执行文件(绿色),和软链接(蓝色),红框内的那个软链接就是我们要用到的

    在这里插入图片描述
    ls -l来查看一下,软链接实际用的是它所指向的一个可执行文件,软链接不占内存只是一个符号指向了这个位置
    在这里插入图片描述

    4)在获得了交叉编译工具链的软链接之后就是,接下来就是环境变量的配置,其实它有两种方式进行配置,一是临时的环境变量的配置,二是永久有效的环境变量的配置
    a.首先用echo $PATH获得当前环境变量的值
    /usr/lib/lightdm/lightdm:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:
    记得无论环境变量多长,只需要取到games:这里即可

    b.进行环境变量的配置
    临时有效的环境变量的配置:
    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
    把a这个步骤取得的环境变量拿下来,然后再把(3)步骤取得的路径接着在games:后面
    这样就完成了临时环境变量的配置,这样有点不好的就是,这只是仅限这个终端窗口而已,在另一个终端这个环境变量就失效了

    永久有效的环境变量的配置:
    首先修改工作目录下的隐藏文件.bashrc,配置命令终端的vi/home/CLC/.bashrc
    进入该隐藏文件之后,在文件的末尾添加
    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 /home/CLC/.bashrc 命令加载配置文件,马上生效配置

    5)我们来检查一下交叉编译工具对不对
    在这里插入图片描述
    在这里插入图片描述
    我们查看交叉编译工具链的版本,出现了第二张图那样的4.8.3的版本号就是说明已经安装成功了

    三、交叉编译工具链的使用
    1.首先我们来简单对比一下gcc和交叉编译工具arm-linux-gnueabihf-gcc两者编译出来的可执行文件有什么不一样
    那么现在我们就对ftptest1.c 这个文件进行编译出来的test1,用file来查看一下两者分别编译出来的可执行文件test1有什么不同
    gcc:
    在这里插入图片描述
    我们可以看到这里显示的是X86-64的属性,这就是表示能在Windows(linux虚拟机)下运行,但在树莓派上是跑不起来的

    arm-linux-gnueabihf-gcc
    在这里插入图片描述用交叉编译的方式编译出来的可执行文件可看出是ARM属性的,这就说明这只能是在树莓派上跑在windows(linux虚拟机)上是跑不起来的

    2.经过上面的介绍,那么现在我们就来实地的实战一下
    在虚拟机上利用交叉编译的方式编译出可执行的文件,再把可执行文件传送到树莓派上运行
    arm-linux-gnueabihf-gcc xxx.c -o xxx
    在这里插入图片描述
    在这里插入图片描述
    我们可看到编译出的test1是可执行文件x就是表示可执行的意思

    如何把编译生成的可执行文件下载到开发板:
    方式一:
    通过scp的方式

    scp  test1   pi@192.168.191.4:/home/pi
    指令  文件名  开发板用户名@开发板地址:开发板的绝对路径
    
    • 1
    • 2

    不幸的是我的出现了这个问题,连接请求超时,刚开始以为是ssh还没开启,查看了一下虚拟机跟树莓派两边都已经开启了ssh,但还是会出现这个情况,那么我们就先遗留一下这个问题在这里,我们到时候解决,其实有些人的是可以的
    在这里插入图片描述
    方式二:
    通过FileZilla的方式进行传输
    这个方式有点冗余,为什么呢,因为要把文件移动到windows底下,再从windows移动到树莓派下,这样就显得有点麻烦了,但是上面那种办法暂时没解决,就先用这个先吧
    在这里插入图片描述
    像图片里的那样开多个窗口,先把文件移动到windows下,再移动到树莓派下
    我们发现通过这种方式移动的可执行文件到树莓派下,竟然是没有执行权限的
    在这里插入图片描述
    在这里插入图片描述
    所以我们执行的时候就会出现权限被拒接的提示,那么出现这种情况该怎么办呢?
    我们通过指令chmod +x来为文件test1赋予可执行的权限,x就是可执行的意思

    chmod +x test1
    
    • 1

    我们再来看一下现在test1已经有了可执行的权限了
    在这里插入图片描述
    现在我们再来运行一下test1,已经是可以跑起来的了
    在这里插入图片描述

    四、带WiringPi库的交叉编译如何处理
    (1)我们在上面对交叉编译工具链进行了安装并使用,那么现在我们就来学习一下带WiringPi库的交叉编译该如何处理。
    首先我们要明白在虚拟机上本来是没有wiringPi库的,所以当我们要在虚拟机上使用这个库的时候,我们首先要对这个库进行安装
    所以在下面我已经将wiringPi库的压缩包上传到网盘上,直接提取即可
    由于wiringPi的那个官网已经失效,所以好好珍惜这个文件

    wiringPi库提取
    提取码:2j5k

    (2)在下载完wiringPi库的压缩包之后,我们斗胆来试一下在虚拟机上安装这个wiringPi
    首先我们可以这个压缩包拿进虚拟机里(用unzip xxx的方式进行解压),其次我们也可以在windows下进行解压,将文件夹放进windowslinux的共享文件夹中

    2.1 我们从共享文件夹中复制文件夹到当前路径

    cp /mnt/hgfs/sharefromwindows/WiringPi -rf .
    
    • 1

    我的共享文件夹是/mnt/hgfs/sharefromwindows,所以cp /mnt/hgfs/sharefromwindows/WiringPi 的意思就是将文件夹WiringPi的所有内容都复制到当前目录来,.在上面有提及过,是代表当前目录的意思。

    -rf:强制递归复制
    -r:若给出的源文件是一个目录文件,此时将复制该目录底下所有的子目录和文件
    -f:覆盖已经存在的目标文件而不给出提示
    没有则错误提示cp: omitting directory(删除目录)
    
    • 1
    • 2
    • 3
    • 4

    2.2 拿到一个库后,我们习惯要看一下 README.TXTINSTALL这两个文件
    INSTALL在这里插入图片描述
    从上面内容中我们可以看出这个库是通过./build的方式来进行安装,在安装完这个库之后,我们可以在/usr/local/lib底下查看这个库的所有内容

    安装出现一下黄框内的字符就是说明已经安装成功了
    在这里插入图片描述
    我们来/usr/local/lib底下看一下确实是有这个库相关的东西在
    在这里插入图片描述
    即使这样,但是安装上的wiringPi库还是用不了的,原因是什么,我们继续往下看。

    2.3 既然在上面我们库已经装上了,那么我们就斗胆的从树莓派下拿个文件过来进行交叉编译看一下
    能不能跑起来
    linux虚拟机与树莓派之间怎么进行文件的传输在上面已经讲过了,所以在这里就不再进行讲解了

    a. 对文件进行编译 arm-linux-gnueabihf-gcc demo1.c
    在这里插入图片描述
    在上图中我们可以看到提示不认识wiringPi.h这个头文件,这个问题还是好解决的,在之前linux动态库那里有说过怎么让它找头文件的位置,那么接下来我们就来解决一下这个问题

    b. 我们通过指定头文件的路径去再编译一遍看看会再出现什么问题

    arm-linux-gnueabihf-gcc demo1.c -I /home/CLC/lessonPi/WiringPi/WiringPi/wiringPi
    -I(大写i):指定头文件的路径
    -L(大写l):指定库的路径
    这个意思是指定从 /home/CLC/lessonPi/WiringPi/WiringPi/wiringPi 这个路径底下去找头文件<wiringPi.h>
    
    • 1
    • 2
    • 3
    • 4

    在这里插入图片描述
    我们从上图中可以看到,指定了头文件的路径之后就不再是第一次的错误了,现在是提示对这些函数没定义,也就是不认识的意思,那么这个跟在树莓派下没指定库名的错误是一样的

    在树莓派下
    在这里插入图片描述
    在linux虚拟机中的错误跟在树莓派下的错误是一样的,从下面的图中我们可以看出,在后面链接上wiringPi这个库之后就不再会提示错误了,那么我们在虚拟机下也来指定一下这个库
    在这里插入图片描述

    c.再上面我们发现了不仅要指定头文件的路径还要指定库的名字,那么现在我们就来指定一下库名看看能不能编译通过

    arm-linux-gnueabihf-gcc demo1.c -I /home/CLC/lessonPi/WiringPi/WiringPi/wiringPi -lwiringPi
    -l(小写的L):指定要用的库的名字
    这里的意思就是指定要用wiringPi这个库
    
    • 1
    • 2
    • 3

    在这里插入图片描述
    我们从上图中依然看到还是出现错误,那么到底是什么回事呢?

    d. 接着上面的问题继续探究下去
    既然出现以上的问题,那么我们就要来考虑一下是不是库本身的问题了,我们来看一下库的内容

    ls /usr/local/lib/ ls -l   查看库的内容
    
    • 1

    在这里插入图片描述
    我们从上图中可以看出软链接真正指向的库是libwiringPi.so.2.46,那么我们来看一下这个库的属性

    file libwiringPi.so.2.46
    
    • 1

    在这里插入图片描述
    来到这,原因已经找到了,这个库的是x86平台的,即在windows下可使用,在arm下是不可以使用的。

    问题总结:我们不要忘记,我们使用的是一个交叉编译的工具链,在进行交叉编译的时候所要链接的库也应该是对应平台的,即我们在windows虚拟机上交叉编译在ARM平台上运行的可执行程序,所以我们链接的库也应该是ARM平台的,否则这个工具不认识这个库,正常的我们是应该先要交叉编译wiringPi库,编译出的库适合树莓派,在这个时候交叉编译可执行程序的时候,链接的库的格式也是正确的

    来到这里,我们问题已经找到了,关于如何解决这个问题,请关注下一篇博文软链接与硬链接

    学习笔记,仅供参考

  • 相关阅读:
    C++标准模板(STL)- 类型支持 (数值极限,is_modulo,digits,digits10)
    windows批处理命令
    心理咨询软件开发系统分析
    Labview CIE ColorTool Lib (源码vi)
    微服务使用SockJs+Stomp实现Websocket 前后端实例 | Vuex形式断开重连、跨域等等问题踩坑(一)
    CSAPP Lab5:Shell
    大语言模型的学习路线和开源模型的学习材料《一》
    EXPLIAN查询type
    solr快速上手:managed-schema标签详解(三)
    Apache Hudi初探(五)(与flink的结合)--Flink 中hudi clean操作
  • 原文地址:https://blog.csdn.net/weixin_51976284/article/details/125401040