文章目錄
- 一、交叉編譯是什麼?為什麼要交叉編譯?
-
- 1.交叉編譯
- 2.為什麼要交叉編譯
- 二、(樹莓派)交叉編譯工具鍊的安裝
-
- 1.臨時有效
- 2.永久有效
- 三、帶wiringPi庫的交叉編譯
一、交叉編譯是什麼?為什麼要交叉編譯?
1.交叉編譯
交叉編譯是在一個平台上生成另一個平台上的可執行代碼。
比如:
在windows上面編寫C51代碼,并編譯成可執行代碼,如xx.hex,是在c51上面運作,不是在windows上面運作;
在ubuntu上面編寫樹莓派的代碼,并編譯成可執行代碼,是在樹莓派Linux上面運作,不是在ubuntu linux上面運作。
之前我們在學習C51、STM32的時候,并沒有進行交叉編譯,那是因為交叉編譯發生在keil等(內建環境)裡面,內建環境已經幫我們做好了,不需要我們關心。
2.為什麼要交叉編譯
平台上不允許或不能夠安裝我們所需要的編譯器:
① 目的平台上的資源貧乏,無法運作我們所需要編譯器,比如C51。
② 目的平台還沒有建立,連作業系統都沒有,根本談不上運作什麼編譯器。(作業系統也是代碼,也要編譯)
是以即使是樹莓派這樣高配置的平台,也需要交叉編譯工具,因為平台運作至少需要兩樣東西:bootloader(啟動引導代碼)以及作業系統核心。
因為要進行作業系統的安裝,首先要進行編譯,即在主控端上利用交叉編譯工具鍊進行編譯,在移植到目标機上運作,這裡引入了兩個名詞:
主控端(host) :編輯和編譯程式的平台,一般是基于X86的PC機,通常也被稱為主機。
目标機(target):使用者開發的系統,通常都是非X86平台,host編譯得到的可執行代碼在target上運作。
二、(樹莓派)交叉編譯工具鍊的安裝
這裡介紹基于樹莓派開發時交叉編譯工具鍊的安裝,其它平台上的安裝類似。
首先在https://github.com/raspberrypi/下載下傳樹莓派交叉編譯工具鍊:
将下載下傳下來的交叉編譯工具安裝包傳給主控端Ubuntu,并進行後續的安裝和配置:
首先将安裝包解壓,進入以下檔案夾:tools-master/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin
其中
arm-linux-gnueabihf-gcc
就是我們需要的交叉編譯工具鍊,注意到這是一個軟連結。(文章後面會講什麼是軟連結和硬連結),接下來我們來配置一下交叉編譯工具鍊。
1.臨時有效
我們需要将交叉編譯工具鍊的檔案路徑加到環境變量當中
echo $PATH
檢視系統環境變量:
pwd
檢視目前目錄
使用
export PATH
指令将目前目錄加到環境變量中去(環境變量==最後一個冒号後==加上目前路徑),即終端執行以下指令:
export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/home/cai/lessonPi/tools-master/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin
配置完成後,我們回到使用者目錄,執行
arm-linux-gnueabihf-gcc -v
指令看是否配置成功
配置完成,但僅限于目前終端,重新打開一個終端,仍然不能使用交叉編譯工具。
此種方法臨時有效。
2.永久有效
修改工作目錄下的 .bashrc 隐藏檔案,配置指令終端。
打開.bashrc檔案,在檔案最後加上配置好的環境變量,儲存退出。
執行
source .bashrc
指令,加載配置檔案,使配置檔案馬上生效。
此時,交叉編譯工具鍊永久生效了,即使我們打開新的終端,也能使用。
(注意:以上指令是在使用者目錄下執行)
三、帶wiringPi庫的交叉編譯
配置好交叉編譯工具鍊後,我們使用它在Ubuntu下編譯好代碼,然後拿到樹莓派上面去運作。
之前我們樹莓派外設開發中,通過樹莓派對繼電器進行控制,代碼 demo0.c 如下:
#include <stdio.h>
#include "wiringPi.h"
#define SWITCHER 7
int main()
{
int cmd = 0;
if(wiringPiSetup() == -1)
{
printf("硬體接口初始化失敗\n");
return -1;
}
pinMode(SWITCHER,OUTPUT);
digitalWrite(SWITCHER,HIGH);
while(1)
{
printf("請輸入0/1:0-斷開開關,1-導通開關\n");
scanf("%d",&cmd);
getchar();
if(cmd == 1)
{
digitalWrite(SWITCHER,LOW);
}else if(cmd == 0)
{
digitalWrite(SWITCHER,HIGH);
}
cmd = 10;
}
return 0;
}
由于使用了wiringPi庫,我們在編譯時需要連結該庫:
gcc demo0.c -lwiringPi
注:關于樹莓派外設開發,參考文章:樹莓派wiringPi庫詳解
現在我們假如樹莓派上不能使用gcc工具進行編譯,又要使編譯的代碼能夠在樹莓派上運作,這時就需要用到交叉編譯了,在Ubuntu上使用交叉編譯工具鍊編譯好代碼,拿到樹莓派上運作。
注意:
1.正常情況下我們先要交叉編譯wiringPi庫,編譯出适合樹莓派的庫,這時候交叉編譯可執行程式,連結庫的格式才是正确的。
2. 進行程式編譯,交叉編譯時通過-I -L來指定所需的頭檔案和庫(已經交叉編譯好的庫)。
下面具體示範一下帶wiringPi庫的交叉編譯:
由于wiringPi庫的官網無法下載下傳,我們在網上找到了一份wiringPi庫檔案,嘗試一下能否正常使用。将wiringPi庫檔案傳輸給Ubuntu,先看一下INSTALL檔案,即怎麼安裝的問題。賦予build檔案可執行權限,wiringPi庫目錄下執行.build指令進行安裝:
wiringPi庫在 /usr/local/lib目錄下
嘗試使用一下這個wiringPi庫:
arm-linux-gnueabihf-gcc demo0.c -L /usr/local/lib/ -lwiringPi
發現缺少頭檔案wiringPi.h
頭檔案在上面這個目錄下,我們連結上這個頭檔案再次進行編譯:
arm-linux-gnueabihf-gcc demo0.c -L /usr/local/lib/ -lwiringPi -I /home/cai/lessonPi/WiringPi/wiringPi
我們發現,編譯還是不成功,實際上這是因為我們在網上下載下傳的這個wiringPi庫不是基于arm平台編譯的,不妨看一下它的檔案類型,很明顯是基于x86架構的。
為了解決這個問題,我們隻能将樹莓派上現成的wiringPi庫拿過來。樹莓派下的wiringPi庫如下:
注意:libwiringPi.so是 軟連結,拿過去是不能用的,而應該把真正的庫libwiringPi.so.2.50拿過去。
将樹莓派上的庫拿過去之後(
chmod +x libwiringPi
),為了友善使用,需要重新生成軟連結,生成軟連結指令:
ln -s libwiringPi.so.2.50 libwiringPi.so
再次交叉編譯demo0.c,編譯成功
但是無法執行,這是肯定的,因為我們編譯的是在arm平台上運作的代碼,不妨查一下檔案類型
是在arm架構下運作的。我們把它拿到樹莓派上看看是否運作成功
運作成功。
補充知識點:軟連結和硬連結
軟連結:
- 軟連結檔案有類似于Windows的快捷方式。
- 在符号連接配接中,檔案實際上是一個文本檔案,其中包含的有另一檔案的位置資訊。
- 你標明的位置上生成一個檔案的鏡像,不會占用磁盤空間
如何生成:
ln -s libwiringPi.so.2.50 libwiringPi.so
指令 參數 要被連結的檔案 軟連結檔案名字
硬連結:
ln libwiringPi.so.2.50 libwiringPi.so
它會在你標明的位置上生成一個和源檔案大小相同的檔案
關于軟連結和硬連結的詳細介紹參考文章:
Linux建立連接配接指令 ln -s建立軟連接配接