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