树莓派(六)树莓派交叉编译
嵌入式之路,贵在日常点滴
---阿杰在线送代码
目录
一、概念
是什么?
列子
为什么需要交叉编译?
宿主机(host)与目标机(target)
需要用到什么工具?
二、交叉编译工具链的安装
安装
临时解决方法在本窗口直接添加环境变量
永久有效的方法修改.bashrc 隐藏文件
三、交叉编译的使用
对比g与armg
在上位机(VMare)写程序,到树莓派运行
检查网络配置
从上位机发送编译后的可执行文件到树莓派工作目录
四、带WiringPi库的交叉编译如何处理
探索链接下载的库不能正确交叉编译
解决用树莓派上的库进行交叉编译
软硬链接
概念
生成
交叉编译
五、其他
简述可移植性高
带有.h文件的怎么进行编译
巧用history和管道,查看对目标文件做了哪些操作
一、概念
是什么?
交叉编译是在一个平台上生成另一个平台上的可执行代码。
列子
- C51的交叉编译发生在keil的集成环境上,在indos编写C51代码,并编译成可执行代码,如xx.hex,是为了在C51平台运行,而不是在indos运行。
- 在ubuntu上面编写树莓派的代码,并编译成可执行代码,如a.out,是在树莓派上运行,不是在ubuntu linux上运行
为什么需要交叉编译?
虽然已经有了主机编译,但目的平台上不允许或不能够安装我们所需要的编译器。
有时是因为目的平台上的①资源贫乏,无法运行我们所需要编译器;
有时又是因为②目的平台还没有建立,连操作系统都没有,根本谈不上运行什么编译器。
树莓派有时因为目的平台还没有建立,连操作系统都没有,操作系统也是代码,也要编译!也要进行交叉编译。
平台运行需要两样至少东西bootloader(启动引导代码)以及操作系统核心
在工作中使用的设备基本需要进行交叉编译,设备考虑成本问题资源贫乏,没有编译工具
宿主机(host)与目标机(target)
- 宿主机编辑和编译程序的平台,一般是基于X86的PC机。
- 目标机用户开发的系统,通常都是非X86平台。host编译得到的可执行代码在target上运行。
需要用到什么工具?
交叉编译器、交叉编译工具链
二、交叉编译工具链的安装
下载
【tools】>【Code】>【Donload Zip】
安装
①将压缩包拷贝进虚拟机linux(直接拖入、共享文件夹、filezilla)
②解压
unzip tools-master.zip
③进入解压后的文件夹
cd tools-master/
④进入arm-bcm2708
cd arm-bcm2708/
⑤进入g-linaro-arm-linux-gnueabihf-raspbian-x64
cd g-linaro-arm-linux-gnueabihf-raspbian-x64/
⑥进入bin目录
cd bin/
可以看到有很多的可执行文件(绿色),软链接(蓝色)
用ls -l查看
看到这个软链接实际用的是它所指向的一个可执行文件,软链接不占内存只是一个符号指向了这个位置。
⑦使用
./arm-linux-gnueabihf-g -v
以前使用的g是在本电脑上运行,使用软链接的是在树莓派上运行。
当要使用这个工具时,“藏”得太深,不方便怎么办?作为环境变量即可。
临时解决方法在本窗口直接添加环境变量
- 显示当下的环境变量
echo $PATH
可以看到各个路径是以作为分隔符
/usr/lib/lightdm/lightdm:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/opt/FriendlyARM/toolschain/4.5.1/bin
-
复制想要添加为环境变量的路径(pd后复制)
- 在冒号后面添加复制的路径
export PATH=/usr/lib/lightdm/lightdm:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/home/CLC/tools-master/arm-bcm2708/g-linaro-arm-linux-gnueabihf-raspbian-x64/bin
- 使用 echo $PATH 查看是否添加成功
/usr/lib/lightdm/lightdm:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/home/CLC/tools-master/arm-bcm2708/g-linaro-arm-linux-gnueabihf-raspbian-x64/bin
已经添加成功。
这样,在其他路径下也能使用交叉编译的g,查看版本号。
arm-linux-gnueabihf-g -v
不建议使用,换一个窗口就不行了。下面还介绍永久有效的方法。
永久有效的方法修改.bashrc 隐藏文件
1、修改工作目录下的.bashrc 隐藏文件,配置命令终端
vi /home/CLC/.bashrc
2、把上面用到的配置环境变量的代码在末尾(shift+g快捷键)加入即可
export PATH=/usr/lib/lightdm/lightdm:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/home/CLC/tools-master/arm-bcm2708/g-linaro-arm-linux-gnueabihf-raspbian-x64/bin
3、使其立即生效(之前没有这步也成功了)
source .bashrc
4、验证
arm-linux-gnueabihf-g -v
三、交叉编译的使用
对比g与armg
- 创建.c文件,使用g进行编译,用file ./a.out查看文件信息
- 创建.c文件,使用g进行编译,用file ./a.out查看文件信息
可在电脑上运行
- 使用arm-linux-gnueabihf-g进行编译,用file ./a.out查看文件信息
可在树莓派运行
在上位机(VMare)写程序,到树莓派运行
检查网络配置
树莓派与虚拟机的网络必须在同一个网段
如果不相同,继续执行会出现如下错误。
可用下面的指令修改虚拟机的ip地址
sudo ifconfig eth0 192.168.43.240
从上位机发送编译后的可执行文件到树莓派工作目录
scp a.out pi@192.168.225.10:/home/pi
后输入密码
raspberry
在树莓派中运行即可。
EG使用交叉编译,让树莓派作为服务器端,VM作为客户端,对树莓派的文件进行访问。
把服务端的代码通过交叉编译发送给树莓派,树莓派运行,VM运行客户端连接上即可。
g server.c -o serverInX86
arm-linux-gnueabihf-g client.c -o clientInPI
从上位机发送编译后的可执行文件到树莓派工作目录
scp clientInPI pi@192.168.225.10:/home/pi
运行结果
四、带WiringPi库的交叉编译如何处理
虚拟机原来是没有WiringPi库的,需从网上下载。
解压后,拷贝至PC的共享文件夹(也可以在虚拟机中unzip解压)
再从共享文件夹中拷贝至当前目录(树莓派学习目录)
cp /mnt/hgfs/share/iringPi . -rf
cp -rf : 强制递归复制
-r若给出的源文件是一个目录文件,此时将复制该目录下所有的子目录和文件。
-f覆盖已经存在的目标文件而不给出提示。
没有则错误提示cp: omitting directory(删除目录)
一般拿到一个库,应该先看一下它的README.TXT和INSTALL
从INSTALL中我们可以得知库安装的方法以及默认路径
探索链接下载的库不能正确交叉编译
下面这个方法是不能正确交叉编译带iringPi库的程序,仅为查看为什么会失败
在WiringPi目录下直接./build,看到【install】All Done.即为安装成功
进入默认安装目录查看
ls /usr/local/lib/
的确安装有
>>那就尝试使用它
- 从树莓派中向VMare发送需要链接iringPi库的程序
scp demo1.c CLC@192.168.178.123:/home/CLC/lessonPI
- 尝试使用交叉编译
arm-linux-gnueabihf-g demo1.c
提示找不到
- 那就指定给他iringPi头文件所在的路径
arm-linux-gnueabihf-g demo1.c -I /home/CLC/lessonPI/WiringPi/iringPi
现在错误提示变为“没有链接iringPi库”
- 那我们现在就给他链接库!
arm-linux-gnueabihf-g demo1.c -I /home/CLC/lessonPI/WiringPi/iringPi -liringPi
- 还是不行,查看一下链接的库
ls /usr/local/lib/
可以看到软链接真正指向的库是这个
- 查看库的详细信息(必须加上库的绝对路径,否则找不到)
错误写法file /usr/local/lib libiringPi.so.2.46
file /usr/local/lib/libiringPi.so.2.46
问题显而易见我们使用的是一个交叉编译工具,链接的应该是树莓派上ARM平台的库,否则工具不认识这个库。
- 问题剖析
,是链接的库的格式不对,是宿主机的平台。
厂家做的库不够完善,没有类似“configure”这样的文件可以进行配置。
vi build进入安装脚本,发现没有任何配置直接编译
查看包含g的字段,发现这个脚本都是用g进行编译,生成的自然是只可在PC运行的程序
grep g -nir
》》在所有文件中去匹配g字段
所有文件
-n 显示行号
-i 不区分大小写
-r 递归,一个个目录全部翻进去
解决用树莓派上的库进行交叉编译
登陆树莓派,进入库目录
cd /usr/lib/
可用ls大致查看
检索关键字“iringPi”(区分大小写)
ls -l | grep iringPi
可以看到软链接真正指向的库
把两个文件都用scp传输到VMare
scp libiringPi.so.2.50 CLC@192.168.178.123:/home/CLC/lessonPI
scp libiringPi.so CLC@192.168.178.123:/home/CLC/lessonPI
在VM中查看发现软连接失效了,没有指向执行文件了,那就要自己创建软链接了。
软硬链接
参考博文
概念
无论是软链接还是硬链接,文件都保持同步变化。
- 软链接
又称之为符号连接(Symbolic Link)。类似于Windos的快捷方式。在选定的位置上生成一个文件的镜像,不会占用磁盘空间,包含有位置信息。
- 硬链接
选定的位置上生成一个和源文件大小相同的文件,作用是允许一个文件拥有多个有效路径名,这样用户就可以建立硬连接到重要文件,以防止“误删”的功能。
生成
- 软连接
指令 参数 要被链接的文件 软链接文件名字
ln -s libiringPi.so.2.50 libiringPi.so
居然报错,
ln: failed to create symbolic link `libiringPi.so': File exists
解决方案
翻译过来的意思就是创建符号链接失败,文件存在。
-s 命令的意思是增加符号链接,起到一个链接的作用
把 -s 命令修改成 -sf 命令;-f 命令的意思是强制执行,也就意味着如果不存在就执行创建,存在就执行覆盖掉
至此,软连接创建完成...
ln -sf libiringPi.so.2.50 libiringPi.so
- 硬链接
指令 参数 要被链接的文件 软链接文件名
ln libiringPi.so.2.50 libiringPi.so
ln -s 是linux中一个非常重要命令。功能是为某一个文件在一个位置建立一个不同的链接。
》用途当我们需要在不同的目录,用到相同的文件时,我们不需要在每一个需要的目录下都放一个必须相同的文件,我们只要在某个固定的目录,放上该文件,然后在其它的目录下用ln命令链接,不必重复的占用磁盘空间。
交叉编译
arm-linux-gnueabihf-g demo1.c -I /home/CLC/lessonPI/WiringPi/iringPi -L. -liringPi -o crossCompRelay
两个-I和-L不可互换。
Linux下g -I(i的大写)、-L和-l比较。
①-I(i的大写): include头文件是在非标准库中存在的也不是在当前文件夹下的,需要将地址用-i(大写)包含。
②-L:用到的函数或操作非标准库下的,需要将库存在的地址用-L包含,库文件一般为.a或.so文件
③-l 链接库。eg:-lpthread
两个-I和-L不可互换。
Linux下g -I(i的大写)、-L和-l比较。
①-I(i的大写): include头文件是在非标准库中存在的也不是在当前文件夹下的,需要将地址用-i(大写)包含。
②-L:用到的函数或操作非标准库下的,需要将库存在的地址用-L包含,库文件一般为.a或.so文件
③-l 链接库。eg:-lpthread
发送可执行文件到树莓派可以直接运行
./crossCompRelay
五、其他
简述可移植性高
一段代码通过不同的编译工具,编译后可以跑在不同的平台上,代码的修改不需要特别多。
带有.h文件的怎么进行编译
如果某.c文件包含了头文件.h,并且.h文件在相同的目录下,使用g 文件.c编译提示
fata error:config.h: No such file or directory
则在编译的时候需要指定路径去寻找.h即可
g server.c -I ./ -o serverInX86
巧用history和管道,查看对目标文件做了哪些操作
history | grep relay.c
》》以history指令得到的结果作为源,流入管道中,匹配含有relay.c的字段
| 管道
grep 检索
》》以history指令得到的结果作为源,流入管道中,匹配含有relay.c的字段
| 管道
grep 检索