S5PV210开发 -- 交叉编译器
如需轉載請注明出處:https://blog.csdn.net/qq_29350001/article/details/78464208
交叉編譯器我們講了不少,
Hi3516A開發--安裝交叉編譯器??
DM368開發 -- 環境搭建??
MQTT再學習 -- 交叉編譯與移植
LIVE555再學習 -- DM368/Hi3516A 交叉編譯
但都未系統的總結一下。
接下來,先講一下S5PV210的交叉編譯器的安裝,然后再總結。
一、安裝交叉編譯器
(1)下載
下載:arm-none-linux-gnueabi-gcc下載
(2)安裝
交叉編譯所需軟件包為?arm-2009q3.tar.bz2
《1》解壓
在 /usr/local/ 目錄下建立目錄 arm,將軟件解壓至該目錄。
? ? #tar -xvf?arm-2009q3.tar.bz2 -C /usr/local/arm/
PS:按理說是可以解壓在任意目錄下的,但提供的kernel源碼編譯器默認設置的位置是??/usr/local/arm/?
《2》增加環境變量
環境變量之前講過,參看:UNIX再學習 -- 環境變量
修改 /etc/profile 文件?
? ? #gedit /etc/profile ?
在最末尾添加:
? ? export PATH=/usr/local/arm/arm-2009q3/bin/:$PATH
執行如下指令讓環境變量生效:
? ? #source /etc/profile
檢驗:
which arm-none-linux-gnueabi-gcc ?查看所在位置
echo $PATH ?查看環境變量
二、交叉編譯器詳解
參看:交叉編譯詳解
參看:交叉編譯詳解 一 概念篇
(1)什么是交叉編譯
在講交叉編譯之前,可以先回顧一下之前講的 gcc 編譯,參看:C語言再學習 -- GCC編譯過程
這個 gcc 編譯,可以理解為“本地編譯”,直接將源文件編譯出來的程序,編譯出來的程序可以在當前平臺下進行運行。
而所謂的交叉編譯器正好與本地編譯相對應,在當前編譯平臺下,編譯出來的程序能運行在體系結構不同的另一種目標平臺上,但是編譯平臺本身卻不能運行該程序。
舉個栗子:
參看:MQTT再學習 -- 交叉編譯與移植
然后我門再看一下,gcc 和?arm-none-linux-gnueabi-gcc 編譯生成的文件到底有啥不同。
gcc編譯:
?
[cpp]?view plain?copy
arm-none-linux-gnueabi-gcc?交叉編譯:
[cpp]?view plain?copy
看出來了么? 是類型啦,主要是在 Intel 80386 執行還是在 ARM 執行的。
?
參看:PM2.5檢測 -- PMS7003 采集和 MQTT 傳輸
生成可執行文件 client
[cpp]?view plain?copy
arm-none-linux-gnueabi-gcc 在Ubuntu下編譯生成的文件,不能在Ubuntu下運行,只能在ARM開發板下執行。
(2)為什么會有交叉編譯器
之所以要有交叉編譯,主要原因是:
速度: 目標平臺的運行速度往往比主機慢得多,許多專用的嵌入式硬件被設計為低成本和低功耗,沒有太高的性能
能力: 整個編譯過程是非常消耗資源的,嵌入式系統往往沒有足夠的內存或磁盤空間
可用性: 即使目標平臺資源很充足,可以本地編譯,但是第一個在目標平臺上運行的本地編譯器總需要通過交叉編譯獲得
靈活性: 一個完整的Linux編譯環境需要很多支持包,交叉編譯使我們不需要花時間將各種支持包移植到目標板上
為什么交叉編譯比較困難,參看:Introduction to cross-compiling for Linux
(3)交叉編譯鏈
參看:C語言再學習 -- GCC編譯過程
編譯過程可分為四個階段:預處理->>編譯->>匯編->>鏈接 ? ?看參看文章即可,這里就不多講了。
(4)交叉編譯器的名字的命名規則
?
?
參看:arm交叉編譯器gnueabi、none-eabi、arm-eabi、gnueabihf、gnueabi區別
《1》命名規則
交叉編譯器的(前綴)的名字的命名規則是: arch-vendor-kernel-system
arch,即系統架構
表示交叉編譯器,是用于哪個目標系統架構中,用于那個平臺中的。即,用此交叉編譯器編譯出來的程序,是運行在哪種CPU上面的。arch的值,常見的有很多種,比如arm,x86,mips等等。
vendor,即生成廠家,提供商
表示誰提供的,即誰制作出來這個交叉編譯器的。但是這一組命名好像比較靈活,在其它廠家提供的交叉編譯鏈中,有以廠家名稱命名的,也有以開發板命名的,或者直接是none或cross的。
kernel,直譯為,內核
其實指的是,你用此交叉編譯器,編譯出來的程序,所運行的目標系統。即,此交叉編譯器,編譯出來的程序,在什么系統中,什么環境中,運行。見過的有 Linux,uclinux,bare(無OS)。
system,直譯為,系統
其實主要表示的,交叉編譯器所選擇的庫函數和目標系統。最常見的一些值有,gnu,gnueabi,uclibcgnueabi等等。
?
擴展:
ABI:二進制應用程序接口(Application Binary Interface (ABI) for the ARM Architecture)。在計算機中,應用二進制接口描述了應用程序(或者其他類型)和操作系統之間或其他應用程序的低級接口。
EABI:嵌入式ABI。嵌入式應用二進制接口指定了文件格式、數據類型、寄存器使用、堆積組織優化和在一個嵌入式軟件中的參數的標準約定。開發者使用自己的匯編語言也可以使用 EABI 作為與兼容的編譯器生成的匯編語言的接口。
兩者主要區別是,ABI是計算機上的,EABI是嵌入式平臺上(如ARM,MIPS等)。
《2》分類和說明
參看:ARM交叉編譯工具鏈
從授權上,分為免費授權版和付費授權版。
免費版目前有三大主流工具商提供,第一是GNU(提供源碼,自行編譯制作),第二是 Codesourcery,第三是Linora。
收費版有ARM原廠提供的armcc、IAR提供的編譯器等等,因為這些價格都比較昂貴,不適合學習用戶使用,所以不做講述。
arm-none-linux-gnueabi-gcc:是 Codesourcery 公司(目前已經被Mentor收購)基于GCC推出的的ARM交叉編譯工具。可用于交叉編譯ARM(32位)系統中所有環節的代碼,包括裸機程序、u-boot、Linux kernel、filesystem和App應用程序。
arm-linux-gnueabihf-gcc:是由 Linaro 公司基于GCC推出的的ARM交叉編譯工具。可用于交叉編譯ARM(32位)系統中所有環節的代碼,包括裸機程序、u-boot、Linux kernel、filesystem和App應用程序。
aarch64-linux-gnu-gcc:是由 Linaro 公司基于GCC推出的的ARM交叉編譯工具。可用于交叉編譯ARMv8 64位目標中的裸機程序、u-boot、Linux kernel、filesystem和App應用程序。
arm-none-elf-gcc:是 Codesourcery 公司(目前已經被Mentor收購)基于GCC推出的的ARM交叉編譯工具。可用于交叉編譯ARM MCU(32位)芯片,如ARM7、ARM9、Cortex-M/R芯片程序。
arm-none-eabi-gcc:是 GNU 推出的的ARM交叉編譯工具。可用于交叉編譯ARM MCU(32位)芯片,如ARM7、ARM9、Cortex-M/R芯片程序。
(5)包含的工具
查看 arm-2009q3/bin 可以看到其包含很多工具,那么這些工具都是干哈的,我們來看一下。
《1》GNU Binutils 簡介
參看:GNU Binutils
參看:GNU Binary Utilities
GNU Binutils是二進制工具的集合。 主要的是:
ld - GNU鏈接器。
as - GNU匯編程序。
addr2line - 將地址轉換為文件名和行號。
ar - 用于創建,修改和從檔案中提取的實用程序。
c++ filt - 過濾到demangle編碼的 C++ 符號。
dlltool - 創建用于構建和使用DLL的文件。
gold - 一個新的,更快的ELF鏈接器,仍在測試中。
gprof - 顯示分析信息。
nlmconv - 將目標代碼轉換為 NLM。
nm - 列出來自目標文件的符號。
objcopy - 復制和翻譯目標文件。
objdump - 顯示來自對象文件的信息。
ranlib - 生成一個檔案內容的索引。
readelf - 顯示來自任何 ELF 格式對象文件的信息。
size - 列出對象或歸檔文件的節大小。
strings - 列出文件中可打印的字符串。
strip - 丟棄符號。
windmc - Windows兼容的消息編譯器。
windres - Windows資源文件的編譯器。
《2》使用示例
匯編器
arm-linux-as led.o -o led.s -g
鏈接器
arm-linux-ld -o led led.o
文件格式轉換
arm-linux-objcopy binary -O led led.bin
反匯編
arm-linux-objdump -S led.o>led.asm
elf格式文件查看
arm-linux-readelf -a led.elf
符號表生成指令
arm-linux-nm led.elf?
去掉elf文件中不需要的信息和代碼
arm-linux-strip led.elf ? ? ?arm-linux-strip led.o
三、會遇到的問題
如果是對gcc編譯不熟悉的人可能會遇到一個問題:
上傳到板子的“可執行文件”,運行后出現 line 1: syntax error: unexpected word (expecting ")")?
?
問題分析:
1. 編譯器的問題
用arm-linux-gcc編譯,可能原來是用gcc編譯的。假如是腳本,#!/bin/sh 改 #!/bin/bash試試
2. 文件完整性
重新燒寫或上傳一遍
3. 編譯命令問題
比如我的一個測試程序 test.c
編譯:arm-none-linux-gnueabi-gcc -c i2c_test.c -o i2c_test? ? ?//i2c_test 為目標文件
使用file查看:
# file i2c_test i2c_test: ELF 32-bit LSB relocatable, ARM, version 1 (SYSV), not stripped使用 readelf 查看:
# readelf -h i2c_test ELF Header:Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 Class: ELF32Data: 2's complement, little endianVersion: 1 (current)OS/ABI: UNIX - System VABI Version: 0Type: REL (Relocatable file)Machine: ARMVersion: 0x1Entry point address: 0x0Start of program headers: 0 (bytes into file)Start of section headers: 1008 (bytes into file)Flags: 0x5000000, Version5 EABISize of this header: 52 (bytes)Size of program headers: 0 (bytes)Number of program headers: 0Size of section headers: 40 (bytes)Number of section headers: 15Section header string table index: 12這相當于將 i2c_test.o 重命名為 i2c_test 其本質還是目標文件。
如果此時你將?i2c_test 拷貝到開發板,執行的話,當然就會出現問題
line 1: syntax error: unexpected word (expecting ")")?
編譯:arm-none-linux-gnueabi-gcc i2c_test.c -o i2c_test ? ? //i2c_test 為可執行文件
使用 file 查看:
# file i2c_test i2c_test: ELF 32-bit LSB executable, ARM, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.16, not stripped使用 readelf 查看:
# readelf -h i2c_test ELF Header:Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 Class: ELF32Data: 2's complement, little endianVersion: 1 (current)OS/ABI: UNIX - System VABI Version: 0Type: EXEC (Executable file)Machine: ARMVersion: 0x1Entry point address: 0x84a0Start of program headers: 52 (bytes into file)Start of section headers: 3132 (bytes into file)Flags: 0x5000002, has entry point, Version5 EABISize of this header: 52 (bytes)Size of program headers: 32 (bytes)Number of program headers: 8Size of section headers: 40 (bytes)Number of section headers: 31Section header string table index: 28readelf 指令以前有講過,參看:C語言再學習-- readelf、objdump、nm使用詳解
-h選項讀取ELF文件的文件頭信息,注意其中的兩項值:Type 和 Entry point address。
Type信息就是file中的文件類型,而 Entry point address表示文件的執行入口點,只有可執行文件該項才有值,而目標文件是可重定向文件,還不可以直接執行,因此該項值為0.
file指令,參看:file 指令
主要查看是目標文件(Relocatable)還是可執行文件(Executable)
還有查看是GCC編譯(Intel 80386)還是交叉編譯(ARM)
如需轉載請注明出處:https://blog.csdn.net/qq_29350001/article/details/78464208
總結
以上是生活随笔為你收集整理的S5PV210开发 -- 交叉编译器的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: S5PV210开发 -- 启动流程
- 下一篇: Word2Vec学习笔记(一)