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