armgcc交叉编译的文件无法运行_认识GCC交叉编译器
一、GCC?簡(jiǎn)介
GCC(GNU Compiler Collection)是一套功能強(qiáng)大、性能優(yōu)越的編程語(yǔ)言編譯器,它是GNU計(jì)劃的代表作品之一。GCC 是 Linux 平臺(tái)下最常用的編譯器,GCC 原名為 GNU C Compiler,即 GNU C 語(yǔ)言編譯器,隨著 GCC 支持的語(yǔ)言越來(lái)越多,它的名稱也逐漸變成了GNU Compiler Collection。
二、什么是交叉編譯
簡(jiǎn)單地說(shuō),我們?cè)?PC 機(jī)上編譯程序時(shí),這些程序應(yīng)該是在 PC 機(jī)上運(yùn)行的。那如果我們想讓一個(gè)程序在 ARM 板子上運(yùn)行,怎么辦?
ARM 板性能越來(lái)越強(qiáng),可以認(rèn)為 ARM 板就相當(dāng)于一臺(tái) PC,當(dāng)然可以在 ARM 板上安裝開(kāi)發(fā)工具,比如安裝 ARM 版本的 GCC,這樣就可以在 ARM 板上編譯程序,在 ARM 板上直接運(yùn)行這個(gè)程序。
但是,有些 ARM 板性能弱,或者即使它的性能很強(qiáng)也強(qiáng)不過(guò) PC 機(jī),所以更多時(shí)候我們是在 PC 機(jī)上開(kāi)發(fā)、編譯程序,再把這個(gè)程序下載到 ARM 板上去運(yùn)行。
這就引入一個(gè)問(wèn)題:
我們使用工具比如說(shuō) gcc 編譯出的程序是給 PC 機(jī)用的,這程序里的指令是 X86 指令。?那么能否使用同一套工具給 ARM 板編譯程序?
顯然是不行,因?yàn)?X86 的指令肯定不能在 ARM 板子上運(yùn)行。所以我們需要使用另一套工具:?交叉編譯工具鏈。
為何叫“交叉”?
首先,我們是在 PC 機(jī)上使用這套工具鏈來(lái)編譯程序;然后再把程序下載到 ARM 板運(yùn)行;如果程序不對(duì),需要回到 PC 機(jī)修改程序、編譯程序,再把程序下載到 ARM 板上運(yùn)行、驗(yàn)證。如此重復(fù)。在這個(gè)過(guò)程中,我們一會(huì)在 PC 上寫(xiě)程序、編譯程序,一會(huì)在 ARM 板上運(yùn)行、驗(yàn)證,中間來(lái)來(lái)回回不斷
重復(fù),所以稱之為“交叉”。對(duì)于所用的工具鏈,它是在 PC 機(jī)上給 ARM 板編譯程序,稱之為“交叉工具鏈”。
交叉工具鏈其實(shí)有很多種,常見(jiàn)的如下:
Ubuntu平臺(tái):交叉工具鏈有arm-linux-gcc編譯器、arm-linux-gnueabihf編譯器。?
Windows平臺(tái):?利用ADS(ARM 開(kāi)發(fā)環(huán)境),使用 armcc 編譯器。
Windows平臺(tái): 利用cygwin環(huán)境,運(yùn)行arm-elf-gcc編譯器。
三、gcc?編譯過(guò)程詳解
一個(gè) C/C++文件要經(jīng)過(guò)預(yù)處理(preprocessing)、編譯(compilation)、匯編(assembly)和連接(linking)?等 4 步才能生成可執(zhí)行文件,編譯流程圖如下:
預(yù)處理:
C/C++源文件中,以“#”開(kāi)頭的命令被稱為預(yù)處理命令,如包含命令“#include”、宏定義命令 “#define”、條件編譯命令“#if”、“#ifdef”等。預(yù)處理就是將要包含(include)的文件插入原文件中、 將宏定義展開(kāi)、根據(jù)條件編譯命令選擇要使用的代碼,最后將這些東西輸出到一個(gè)“.i”文件中等待進(jìn)一步處理。
編譯:?
對(duì)預(yù)處理后的源碼進(jìn)行詞法和語(yǔ)法分析,生成目標(biāo)系統(tǒng)的匯編代碼文件,后綴名為“.s”。
匯編:
對(duì)匯編代碼進(jìn)行優(yōu)化,生成目標(biāo)代碼文件,后綴名為“.o”。
鏈接:
解析目標(biāo)代碼中的外部引用,將多個(gè)目標(biāo)代碼文件連接為一個(gè)可執(zhí)行文件。
編譯器利用這?4?個(gè)步驟中的一個(gè)或多個(gè)來(lái)處理輸入文件,源文件的后綴名表示源文件所用的語(yǔ)言,后綴名控制著編譯器的缺省動(dòng)作
其他后綴名的文件被傳遞給連接器(linker),通常包括:
.o:?目標(biāo)文件(Object file,OBJ?文件)
.a:?歸檔庫(kù)文件(Archive file)
在編譯過(guò)程中,除非使用了“-c”,“-S”或“-E”選項(xiàng)(或者編譯錯(cuò)誤阻止了完整的過(guò)程),否則最后的步驟總是連接。在連接階段中,所有對(duì)應(yīng)于源程序的.o 文件,“-l”選項(xiàng)指定的庫(kù)文件,無(wú)法識(shí)別的文件名(包括指定的“.o”目標(biāo)文件和“.a”庫(kù)文件)按命令行中的順序傳遞給連接器。
四、gcc?命令
gcc 的命令格式如下:
gcc [選項(xiàng)] 文件列表gcc 命令用于實(shí)現(xiàn) c 程序編譯的全過(guò)程。文件列表參數(shù)指定了 gcc 的輸入文件;選項(xiàng)用于定制 gcc 的行為。gcc 根據(jù)選項(xiàng)的規(guī)則將輸入文件編譯生成適當(dāng)?shù)妮敵鑫募?/p>
gcc 的選項(xiàng)非常多,常用的選項(xiàng),它們大致可以分為以下幾類 。并且使用一個(gè)例子來(lái)描述這些選項(xiàng)。
#include #define COUNT 10int main(){ printf("COUNTS:%d\n", COUNT);????return?0;}過(guò)程控制選項(xiàng)
過(guò)程控制選項(xiàng)用于控制 gcc 的編譯過(guò)程。無(wú)過(guò)程控制選項(xiàng)時(shí),gcc 將默認(rèn)執(zhí)行全部編譯過(guò)程,產(chǎn)生可執(zhí)行代碼。常用的過(guò)程控制選項(xiàng)有:
(1)?預(yù)處理選項(xiàng)(-E)?
C/C++源文件中,以“#”開(kāi)頭的命令被稱為預(yù)處理命令,如包含命令“#include”、宏定義命令“#define”、條件編譯命令“#if”、“#ifdef”等。預(yù)處理就是將要包含(include)的文件插入原文件中、 將宏定義展開(kāi)、根據(jù)條件編譯命令選擇要使用的代碼,最后將這些東西輸出到一個(gè)“.i”文件中等待進(jìn)一步處理。使用例子如下:
[root@localhost test]# arm-linux-gcc -E main.c -o main.i?
運(yùn)行結(jié)果,生成?main.i,main.i?的內(nèi)容如下(由于頭文件展開(kāi)內(nèi)容過(guò)多,我將截取部分關(guān)鍵代碼):
extern char *ctermid (char *__s) __attribute__ ((__nothrow__));# 882 "/usr/local/arm/4.3.2/bin/../arm-none-linux-gnueabi/libc/usr/include/stdio.h" 3 4extern?void?flockfile?(FILE?*__stream)?__attribute__?((__nothrow__));extern?int?ftrylockfile?(FILE?*__stream)?__attribute__?((__nothrow__))?;extern void funlockfile (FILE *__stream) __attribute__ ((__nothrow__));# 912 "/usr/local/arm/4.3.2/bin/../arm-none-linux-gnueabi/libc/usr/include/stdio.h" 3 4# 2 "main.c" 2int main(){ printf("COUNTS:%d\n", 10); return 0;}你會(huì)發(fā)現(xiàn)頭文件被展開(kāi)和 printf 函數(shù)中調(diào)用 COUNT 這個(gè)宏被展開(kāi)。
(2) 編譯選項(xiàng)(-S)
編譯就是把 C/C++代碼(比如上述的“.i”文件)“翻譯”成匯編代碼。使用例子如下:
[root@localhost test]# arm-linux-gcc -S main.i -o main.s運(yùn)行結(jié)果,生成?main.s,main.s?的內(nèi)容如下:
(3)?匯編選項(xiàng)(-c)
匯編就是將上述的“.s”文件匯編代碼翻譯成符合一定格式的機(jī)器代碼,在?Linux?系統(tǒng)上一般表現(xiàn)為?ELF?目標(biāo)文件(OBJ?文件)
[root@localhost test]# arm-linux-gcc -c main.s -o main.o運(yùn)行結(jié)果,生成 main.o(將源文件轉(zhuǎn)為一定格式的機(jī)器代碼)。
輸出選項(xiàng)
輸出選項(xiàng)用于指定?gcc?的輸出特性等,常用的選項(xiàng)有:
(1)?輸出目標(biāo)選項(xiàng)(-o filename)
-o 選項(xiàng)指定生成文件的文件名為 filename。使用例子如下:
其中,如果無(wú)此選項(xiàng)時(shí)使用默認(rèn)的文件名,各編譯階段有各自的默認(rèn)文件名,可執(zhí)行文件的默認(rèn)名為 a.out。使用例子如下:
(2)?輸出所有警告選項(xiàng)(-Wall)
顯示所有的警告信息,而不是只顯示默認(rèn)類型的警告。建議使用。我們把上面的 main.c 稍微修改一下。
?
頭文件選項(xiàng)
頭文件選項(xiàng):?-I dirname。
將 dirname 目錄加入到頭文件搜索目錄列表中。當(dāng) gcc 在默認(rèn)的路徑中沒(méi)有找到頭文件時(shí),就到本選項(xiàng)指定的目錄中去找。
在上面的例子中創(chuàng)建一個(gè) inc 目錄,并在里面創(chuàng)建一個(gè)頭文件 test.h。
然后 main.c 里面增加#include“test.h”。
鏈接庫(kù)選項(xiàng)
1.?添加庫(kù)文件搜索目錄(-L dirname)
將 dirname 目錄加入到庫(kù)文件的搜索目錄列表中。
2.?加載庫(kù)名選項(xiàng)(-l?name)
加載名為 libname.a 或 libname.so 的函數(shù)庫(kù)。
例如:-lm 表示鏈接名為 libm.so 的函數(shù)庫(kù)。
3. 靜態(tài)庫(kù)選項(xiàng)(-static) 使用靜態(tài)庫(kù)。
注意:?在命令行中,靜態(tài)庫(kù)必須放在目標(biāo)文件之后。
[root@localhost test]# gcc test.cpp -o test libexample.a -static代碼優(yōu)化選項(xiàng)
gcc 提供幾種不同級(jí)別的代碼優(yōu)化方案,用“-Olevel”選項(xiàng)表示。level 取值可以是?0、1、2、3 和 s。默認(rèn)?0?級(jí),即不進(jìn)行優(yōu)化。典型的優(yōu)化選項(xiàng):
(1)?-O 或-O1:?基本優(yōu)化,使代碼執(zhí)行的更快
(2)?-O2: 產(chǎn)生盡可能小和快的代碼。如無(wú)特殊要求,不建議使用 O2 以上的優(yōu)化。
(3)?-Os:生成最小的可執(zhí)行文件,適合用于嵌入式軟件。
調(diào)試選項(xiàng)及調(diào)試示例
gcc 支持?jǐn)?shù)種調(diào)試選項(xiàng):?
-g:?產(chǎn)生能被 GDB 調(diào)試器使用的調(diào)試信息。
舉個(gè)例子,首先需要在編譯時(shí)加上“-g”選項(xiàng),操作步驟如下:
[root@localhost test]# arm-linux-gcc main.c -I inc -g -o mainGDB?調(diào)試示例:
(1)?run?命令
調(diào)試運(yùn)行,使用 run 命令開(kāi)始執(zhí)行被調(diào)試的程序;
run?命令的格式:?run [運(yùn)行參數(shù)]
(2)?list?命令
列出源代碼,使用 list 命令來(lái)查看源程序以及行號(hào)信息;
list?命令的格式:?list [行號(hào)]
(3)?設(shè)置斷點(diǎn)
1)?break?命令,設(shè)置斷點(diǎn)命令,break?命令的格式:?break |
2) info break 命令,查看斷點(diǎn)命令;
3) delete breakpoint 命令,刪除斷點(diǎn)命令;delete breakpoint 命令的格式: delete breakpoint
(4)?跟蹤運(yùn)行結(jié)果
1)?print?命令,顯示變量的值,print?命令的格式:print[/格式]
2)?display?命令,設(shè)置自動(dòng)顯示命令,display?命令的格式:?display
3)?step?和?next?命令,單步執(zhí)行命令,step?和?next?命令的格式:step ?或?next
4) continue 命令,繼續(xù)執(zhí)行命令。
總結(jié)
以上是生活随笔為你收集整理的armgcc交叉编译的文件无法运行_认识GCC交叉编译器的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 【Android】关于参数的传递问题
- 下一篇: python随机生成20个数字_pyth