導航:首頁 > 源碼編譯 > 一步編譯分步編譯

一步編譯分步編譯

發布時間:2023-03-04 02:56:31

Ⅰ 請問C語言程序編譯過程中,單編譯和雙編譯有什麼聯系和區別

不是雙編譯,生成應用程序要經過兩步:編譯,鏈接。
第一步編譯:編譯器將每個.c文件編譯為對應的.obj文件,這個過程主要是做預處理,語法分析
第二步鏈接:將所有.obj綜合處理,生成二進制執行碼,即一個.exe應用程序

可以選擇僅編譯,只生成.obj文件,若有語法錯誤,則停止編譯,並報告錯誤

也可以選擇編鏈,若編譯期出錯,則停止編譯,若沒有出錯,則繼續生成.exe,一步到位

Ⅱ 「干貨」嵌入式linux系統移植的四大步驟(上)


在學習系統移植的相關知識,在學習和調試過程中,發現了很多問題,也解決了很多問題,但總是對於我們的開發結果有一種莫名其妙的感覺,糾其原因,主要對於我們的開發環境沒有一個深刻的認識,有時候幾個簡單的命令就可以完成非常復雜的功能,可是我們有沒有想過,為什麼會有這樣的效果?


如果沒有去追問,只是機械地完成,並且看到實驗效果,這樣做其實並沒有真正的掌握系統移植的本質。


在做每一個步驟的時候, 首先問問自己,為什麼要這樣做,然後再問問自己正在做什麼? 搞明白這幾個問題,我覺得就差不多了,以後不管更換什麼平台,什麼晶元,什麼開發環境,你都不會迷糊,很快就會上手。對於嵌入式的學習方法,我個人方法就是:從宏觀上把握(解決為什麼的問題),微觀上研究(解決正在做什麼的問題),下面以自己學習的arm-cortex_a8開發板為目標,介紹下自己的學習方法和經驗。


嵌入式Linux系統移植主要由四大部分組成:


一、搭建交叉開發環境
二、bootloader的選擇和移植
三、kernel的配置、編譯、和移植
四、根文件系統的製作


第一部分:搭建交叉開發環境


先介紹第一分部的內容:搭建交叉開發環境,首先必須得思考兩個問題,什麼是交叉環境? 為什麼需要搭建交叉環境?


先回答第一個問題,在嵌入式開發中,交叉開發是很重要的一個概念,開發的第一個環節就是搭建環境,第一步不能完成,後面的步驟從無談起,這里所說的交叉開發環境主要指的是:在開發主機上(通常是我的pc機)開發出能夠在目標機(通常是我們的開發板)上運行的程序。嵌入式比較特殊的是不能在目標機上開發程序(狹義上來說),因為對於一個原始的開發板,在沒有任何程序的情況下它根本都跑不起來,為了讓它能夠跑起來,我們還必須要藉助pc機進行燒錄程序等相關工作,開發板才能跑起來,這里的pc機就是我們說的開發主機,想想如果沒有開發主機,我們的目標機基本上就是無法開發,這也就是電子行業的一句名言:搞電子,說白了,就是玩電腦!


然後回答第二個問題,為什麼需要交叉開發環境?主要原因有以下幾點:


原因 1: 嵌入式系統的硬體資源有很多限制,比如cpu主頻相對較低,內存容量較小等,想想讓幾百MHZ主頻的MCU去編譯一個Linux kernel會讓我們等的不耐煩,相對來說,pc機的速度更快,硬體資源更加豐富,因此利用pc機進行開發會提高開發效率。


原因2: 嵌入式系統MCU體系結構和指令集不同,因此需要安裝交叉編譯工具進行編譯,這樣編譯的目標程序才能夠在相應的平台上比如:ARM、MIPS、 POWEPC上正常運行。


交叉開發環境的硬體組成主要由以下幾大部分


1.開發主機
2.目標機(開發板)
3.二者的鏈接介質,常用的主要有3種方式:(1)串口線 (2)USB線 (3)網線


對應的硬體介質,還必須要有相應的軟體「介質」支持:


1.對於串口,通常用的有串口調試助手,putty工具等,工具很多,功能都差不多,會用一兩款就可以;


2.對於USB線,當然必須要有USB的驅動才可以,一般晶元公司會提供,比如對於三星的晶元,USB下載主要由DNW軟體來完成;


3.對於網線,則必須要有網路協議支持才可以, 常用的服務主要兩個


第一:tftp服務:

主要用於實現文件的下載,比如開發調試的過程中,主要用tftp把要測試的bootloader、kernel和文件系統直接下載到內存中運行,而不需要預先燒錄到Flash晶元中,一方面,在測試的過程中,往往需要頻繁的下載,如果每次把這些要測試的文件都燒錄到Flash中然後再運行也可以,但是缺點是:過程比較麻煩,而且Flash的擦寫次數是有限的;另外一方面:測試的目的就是把這些目標文件載入到內存中直接運行就可以了,而tftp就剛好能夠實現這樣的功能,因此,更沒有必要把這些文件都燒錄到Flash中去。


第二: nfs服務:

主要用於實現網路文件的掛載,實際上是實現網路文件的共享,在開發的過程中,通常在系統移植的最後一步會製作文件系統,那麼這是可以把製作好的文件系統放置在我們開發主機PC的相應位置,開發板通過nfs服務進行掛載,從而測試我們製作的文件系統是否正確,在整個過程中並不需要把文件系統燒錄到Flash中去,而且掛載是自動進行掛載的,bootload啟動後,kernel運行起來後會根據我們設置的啟動參數進行自動掛載,因此,對於開發測試來講,這種方式非常的方便,能夠提高開發效率。


另外,還有一個名字叫 samba 的服務也比較重要,主要用於文件的共享,這里說的共享和nfs的文件共享不是同一個概念,nfs的共享是實現網路文件的共享,而samba實現的是開發主機上 Windows主機和Linux虛擬機之間的文件共享,是一種跨平台的文件共享 ,方便的實現文件的傳輸。


以上這幾種開發的工具在嵌入式開發中是必備的工具,對於嵌入式開發的效率提高做出了偉大的貢獻,因此,要對這幾個工具熟練使用,這樣你的開發效率會提高很多。等測試完成以後,就會把相應的目標文件燒錄到Flash中去,也就是等發布產品的時候才做的事情,因此對於開發人員來說,所有的工作永遠是測試。


通過前面的工作,我們已經准備好了交叉開發環境的硬體部分和一部分軟體,最後還缺少交叉編譯器,讀者可能會有疑問,為什麼要用交叉編譯器?前面已經講過,交叉開發環境必然會用到交叉編譯工具,通俗地講就是在一種平台上編譯出能運行在體系結構不同的另一種平台上的程序,開發主機PC平台(X86 CPU)上編譯出能運行在以ARM為內核的CPU平台上的程序,編譯得到的程序在X86 CPU平台上是不能運行的,必須放到ARM CPU平台上才能運行,雖然兩個平台用的都是Linux系統。相對於交叉編譯,平常做的編譯叫本地編譯,也就是在當前平台編譯,編譯得到的程序也是在本地執行。用來編譯這種跨平台程序的編譯器就叫交叉編譯器,相對來說,用來做本地編譯的工具就叫本地編譯器。所以要生成在目標機上運行的程序,必須要用交叉編譯工具鏈來完成。

這里又有一個問題,不就是一個交叉編譯工具嗎?為什麼又叫交叉工具鏈呢?原因很簡單,程序不能光編譯一下就可以運行,還得進行匯編和鏈接等過程,同時還需要進行調試,對於一個很大工程,還需要進行工程管理等等,所以,這里 說的交叉編譯工具是一個由 編譯器、連接器和解釋器 組成的綜合開發環境,交叉編譯工具鏈主要由binutils(主要包括匯編程序as和鏈接程序ld)、gcc(為GNU系統提供C編譯器)和glibc(一些基本的C函數和其他函數的定義) 3個部分組成。有時為了減小libc庫的大小,也可以用別的 c 庫來代替 glibc,例如 uClibc、dietlibc 和 newlib。

那麼,如何得到一個交叉工具鏈呢?是從網上下載一個「程序」然後安裝就可以使用了嗎?回答這個問題之前先思考這樣一個問題,我們的交叉工具鏈顧名思義就是在PC機上編譯出能夠在我們目標開發平台比如ARM上運行的程序,這里就又有一個問題了,我們的ARM處理器型號非常多,難道有專門針對我們某一款的交叉工具鏈嗎?若果有的話,可以想一想,這么多處理器平台,每個平台專門定製一個交叉工具鏈放在網路上,然後供大家去下載,想想可能需要找很久才能找到適合你的編譯器,顯然這種做法不太合理,且浪費資源!因此,要得到一個交叉工具鏈,就像我們移植一個Linux內核一樣,我們只關心我們需要的東西,編譯我們需要的東西在我們的平台上運行,不需要的東西我們不選擇不編譯,所以,交叉工具鏈的製作方法和系統移植有著很多相似的地方,也就是說,交叉開發工具是一個支持很多平台的工具集的集合(類似於Linux源碼),然後我們只需從這些工具集中找出跟我們平台相關的工具就行了,那麼如何才能找到跟我們的平台相關的工具,這就是涉及到一個如何製作交叉工具鏈的問題了。


通常構建交叉工具鏈有如下三種方法:


方法一 : 分步編譯和安裝交叉編譯工具鏈所需要的庫和源代碼,最終生成交叉編譯工具鏈。該方法相對比較困難,適合想深入學習構建交叉工具鏈的讀者。如果只是想使用交叉工具鏈,建議使用下列的方法二構建交叉工具鏈。


方法二: 通過Crosstool-ng腳本工具來實現一次編譯,生成交叉編譯工具鏈,該方法相對於方法一要簡單許多,並且出錯的機會也非常少,建議大多數情況下使用該方法構建交叉編譯工具鏈。


方法三 : 直接通過網上下載已經製作好的交叉編譯工具鏈。該方法的優點不用多說,當然是簡單省事,但與此同時該方法有一定的弊端就是局限性太大,因為畢竟是別人構建好的,也就是固定的,沒有靈活性,所以構建所用的庫以及編譯器的版本也許並不適合你要編譯的程序,同時也許會在使用時出現許多莫名其妙的錯誤,建議讀者慎用此方法。

crosstool-ng是一個腳本工具,可以製作出適合不同平台的交叉編譯工具鏈,在進行製作之前要安裝一下軟體:
$ sudo apt-get install g++ libncurses5-dev bison flex texinfo automake libtool patch gcj cvs cvsd gawk
crosstool腳本工具可以在http://ymorin.is-a-geek.org/projects/crosstool下載到本地,然後解壓,接下來就是進行安裝配置了,這個配置優點類似內核的配置。主要的過程有以下幾點:
1. 設定源碼包路徑和交叉編譯器的安裝路徑
2. 修改交叉編譯器針對的構架

3. 增加編譯時的並行進程數,以增加運行效率,加快編譯,因為這個編譯會比較慢。
4. 關閉JAVA編譯器 ,減少編譯時間
5. 編譯
6. 添加環境變數
7. 刷新環境變數。
8. 測試交叉工具鏈

到此,嵌入式Linux系統移植四大部分的第一部分工作全部完成,接下來可以進行後續的開發了。



第二部分:bootloader的選擇和移植


01 Boot Loader 概念


就是在操作系統內核運行之前運行的一段小程序。通過這段小程序,我們可以初始化硬體設備、建立內存空間的映射圖,從而將系統的軟硬體環境帶到一個合適的狀態,以便為最終調用操作系統內核准備好正確的環境,他就是所謂的引導載入程序(Boot Loader)。


02 為什麼系統移植之前要先移植BootLoader?


BootLoader的任務是引導操作系統,所謂引導操作系統,就是啟動內核,讓內核運行就是把內核載入到內存RAM中去運行,那先問兩個問題:第一個問題,是誰把內核搬到內存中去運行?第二個問題:我們說的內存是SDRAM,大家都知道,這種內存和SRAM不同,最大的不同就是SRAM只要系統上電就可以運行,而SDRAM需要軟體進行初始化才能運行,那麼在把內核搬運到內存運行之前必須要先初始化內存吧,那麼內存是由誰來初始化的呢?其實這兩件事情都是由bootloader來乾的,目的是為內核的運行准備好軟硬體環境,沒有bootloadr我們的系統當然不能跑起來。

03 bootloader的分類


首先更正一個錯誤的說法,很多人說bootloader就是U-boot,這種說法是錯誤的,確切來說是u-boot是bootloader的一種。也就是說bootloader具有很多種類,


由上圖可以看出,不同的bootloader具有不同的使用范圍,其中最令人矚目的就是有一個叫U-Boot的bootloader,是一個通用的引導程序,而且同時支持X86、ARM和PowerPC等多種處理器架構。U-Boot,全稱 Universal Boot Loader,是遵循GPL條款的開放源碼項目,是由德國DENX小組開發的用於多種嵌入式CPU的bootloader程序,對於Linux的開發,德國的u-boot做出了巨大的貢獻,而且是開源的。

u-boot具有以下特點:

① 開放源碼;
② 支持多種嵌入式操作系統內核,如Linux、NetBSD, VxWorks, QNX, RTEMS, ARTOS, LynxOS;
③ 支持多個處理器系列,如PowerPC、ARM、x86、MIPS、XScale;
④ 較高的可靠性和穩定性;
⑤ 高度靈活的功能設置,適合U-Boot調試、操作系統不同引導要求、產品發布等;
⑥ 豐富的設備驅動源碼,如串口、乙太網、SDRAM、FLASH、LCD、NVRAM、EEPROM、RTC、鍵盤等;
⑦ 較為豐富的開發調試文檔與強大的網路技術支持;
其實,把u-boot可以理解為是一個小型的操作系統。

04 u-boot的目錄結構


* board 目標板相關文件,主要包含SDRAM、FLASH驅動;
* common 獨立於處理器體系結構的通用代碼,如內存大小探測與故障檢測;
* cpu 與處理器相關的文件。如mpc8xx子目錄下含串口、網口、LCD驅動及中斷初始化等文件;
* driver 通用設備驅動,如CFI FLASH驅動(目前對INTEL FLASH支持較好)
* doc U-Boot的說明文檔;
* examples可在U-Boot下運行的示常式序;如hello_world.c,timer.c;
* include U-Boot頭文件;尤其configs子目錄下與目標板相關的配置頭文件是移植過程中經常要修改的文件;
* lib_xxx 處理器體系相關的文件,如lib_ppc, lib_arm目錄分別包含與PowerPC、ARM體系結構相關的文件;
* net 與網路功能相關的文件目錄,如bootp,nfs,tftp;
* post 上電自檢文件目錄。尚有待於進一步完善;
* rtc RTC驅動程序;
* tools 用於創建U-Boot S-RECORD和BIN鏡像文件的工具;

05 u-boot的工作模式


U-Boot的工作模式有 啟動載入模式和下載模式 。啟動載入模式是Bootloader的正常工作模式,嵌入式產品發布時,Bootloader必須工作在這種模式下,Bootloader將嵌入式操作系統從FLASH中載入到SDRAM中運行,整個過程是自動的。 下載模式 就是Bootloader通過某些通信手段將內核映像或根文件系統映像等從PC機中下載到目標板的SDRAM中運行,用戶可以利用Bootloader提供的一些令介面來完成自己想要的操作,這種模式主要用於測試和開發。

06 u-boot的啟動過程


大多數BootLoader都分為stage1和stage2兩大部分,U-boot也不例外。依賴於cpu體系結構的代碼(如設備初始化代碼等)通常都放在stage1且可以用匯編語言來實現,而stage2則通常用C語言來實現,這樣可以實現復雜的功能,而且有更好的可讀性和移植性。


1、 stage1(start.s代碼結構)
U-boot的stage1代碼通常放在start.s文件中,它用匯編語言寫成,其主要代碼部分如下:
(1) 定義入口。由於一個可執行的image必須有一個入口點,並且只能有一個全局入口,通常這個入口放在rom(Flash)的0x0地址,因此,必須通知編譯器以使其知道這個入口,該工作可通過修改連接器腳本來完成。
(2)設置異常向量(exception vector)。
(3)設置CPU的速度、時鍾頻率及中斷控制寄存器。
(4)初始化內存控制器 。
(5)將rom中的程序復制到ram中。
(6)初始化堆棧 。
(7)轉到ram中執行,該工作可使用指令ldrpc來完成。


2、 stage2(C語言代碼部分)

lib_arm/board.c中的start armboot是C語言開始的函數,也是整個啟動代碼中C語言的主函數,同時還是整個u-boot(armboot)的主函數,該函數主要完成如下操作:
(1)調用一系列的初始化函數。
(2)初始化flash設備。
(3)初始化系統內存分配函數。
(4)如果目標系統擁有nand設備,則初始化nand設備。
(5)如果目標系統有顯示設備,則初始化該類設備。
(6)初始化相關網路設備,填寫ip,c地址等。
(7)進入命令循環(即整個boot的工作循環),接受用戶從串口輸入的命令,然後進行相應的工作。

07 基於cortex-a8的s5pc100bootloader啟動過程分析


s5pc100支持兩種啟動方式,分別為USB啟動方式和NandFlash啟動方式:


1. S5PC100 USB啟動過程

[1] A8 reset, 執行iROM中的程序
[2] iROM中的程序根據S5PC100的配置管腳(SW1開關4,撥到4對面),判斷從哪裡啟動(USB)
[3] iROM中的程序會初始化USB,然後等待PC機下載程序
[4] 利用DNW程序,從PC機下載SDRAM的初始化程序到iRAM中運行,初始化SDRAM
[5] SDRAM初始化完畢,iROM中的程序繼續接管A8, 然後等待PC下載程序(BootLoader)
[6] PC利用DNW下載BootLoader到SDRAM
[7] 在SDRAM中運行BootLoader

2. S5PC100 Nandflash啟動過程

[1] A8 reset, 執行IROM中的程序
[2] iROM中的程序根據S5PC100的配置管腳(SW1開關4,撥到靠4那邊),判斷從哪裡啟動(Nandflash)
[3] iROM中的程序驅動Nandflash
[4] iROM中的程序會拷貝Nandflash前16k到iRAM
[5] 前16k的程序(BootLoader前半部分)初始化SDRAM,然後拷貝完整的BootLoader到SDRAM並運行
[6] BootLoader拷貝內核到SDRAM,並運行它
[7] 內核運行起來後,掛載rootfs,並且運行系統初始化腳本

08 u-boot移植(基於cortex_a8的s5pc100為例)


1.建立自己的平台

(1).下載源碼包2010.03版本,比較穩定
(2).解壓後添加我們自己的平台信息,以smdkc100為參考版,移植自己s5pc100的開發板
(3).修改相應目錄的文件名,和相應目錄的Makefile,指定交叉工具鏈。
(4).編譯
(5).針對我們的平台進行相應的移植,主要包括修改SDRAM的運行地址,從0x20000000
(6).「開關」相應的宏定義
(7).添加Nand和網卡的驅動代碼
(8).優化go命令
(9).重新編譯 make distclean(徹底刪除中間文件和配置文件) make s5pc100_config(配置我們的開發板) make(編譯出我們的u-boot.bin鏡像文件)
(10).設置環境變數,即啟動參數,把編譯好的u-boot下載到內存中運行,過程如下:
1. 配置開發板網路
ip地址配置:
$setenv ipaddr 192.168.0.6 配置ip地址到內存的環境變數
$saveenv 保存環境變數的值到nandflash的參數區

網路測試:
在開發開發板上ping虛擬機:
$ ping 192.168.0.157(虛擬機的ip地址)

如果網路測試失敗,從下面幾個方面檢查網路:
1. 網線連接好
2. 開發板和虛擬機的ip地址是否配置在同一個網段
3. 虛擬機網路一定要採用橋接(VM--Setting-->option)
4. 連接開發板時,虛擬機需要設置成 靜態ip地址

2. 在開發板上,配置tftp伺服器(虛擬機)的ip地址
$setenv serverip 192.168.0.157(虛擬機的ip地址)
$saveenv
3. 拷貝u-boot.bin到/tftpboot(虛擬機上的目錄)
4. 通過tftp下載u-boot.bin到開發板內存
$ tftp 20008000(內存地址即可) u-boot.bin(要下載的文件名)

如果上面的命令無法正常下載:
1. serverip配置是否正確
2. tftp服務啟動失敗,重啟tftp服務
#sudo service tftpd-hpa restart

5. 燒寫u-boot.bin到nandflash的0地址
$nand erase 0(起始地址) 40000(大小) 擦出nandflash 0 - 256k的區域
$nand write 20008000((緩存u-boot.bin的內存地址) 0(nandflash上u-boot的位置) 40000(燒寫大小)

6. 切換開發板的啟動方式到nandflash
1. 關閉開發板
2. 把SW1的開關4撥到4的那邊
3. 啟動開發板,它就從nandflash啟動

Ⅲ C語言代碼怎麼編譯成.o文件再怎麼變成.exe文件

linux下gcc -c wen.c -o wen.o 生成.o文件gcc wen.o -o wen 就變成.exe文件

Ⅳ 簡述將源程序編譯成可執行程序的過程

一個源程序到一個可執行程序的過程:預編譯、編譯、匯編、鏈接。其中,編譯是主要部分,其中又分為六個部分:詞法分析、語法分析、語義分析、中間代碼生成、目標代碼生成和優化。

預編譯:主要處理源代碼文件中的以「#」開頭的預編譯指令。處理規則如下:

1、刪除所有的#define,展開所有的宏定義。

2、處理所有的條件預編譯指令,如「#if」、「#endif」、「#ifdef」、「#elif」和「#else」。

3、處理「#include」預編譯指令,將文件內容替換到它的位置,這個過程是遞歸進行的,文件中包含其他文件。

4、刪除所有的注釋,「//」和「/**/」。

5、保留所有的#pragma 編譯器指令,編譯器需要用到他們,如:#pragma once 是為了防止有文件被重復引用。

6、添加行號和文件標識,便於編譯時編譯器產生調試用的行號信息,和編譯時產生編譯錯誤或警告是能夠顯示行號。

(4)一步編譯分步編譯擴展閱讀:

編譯過程中語法分析器只是完成了對表達式語法層面的分析,語義分析器則對表達式是否有意義進行判斷,其分析的語義是靜態語義——在編譯期能分期的語義,相對應的動態語義是在運行期才能確定的語義。

其中,靜態語義通常包括:聲明和類型的匹配,類型的轉換,那麼語義分析就會對這些方面進行檢查,例如將一個int型賦值給int*型時,語義分析程序會發現這個類型不匹配,編譯器就會報錯。

Ⅳ 如何在linux平台構建基於newlib工具鏈

交叉編譯通俗地講就是在一種平台上編譯出能運行在體系結構不同的另一種平台上的程式,比如在PC平台(X86 CPU)上編譯出能運行在以ARM為內核的CPU平台上的程式,編譯得到的程式在X86 CPU平台上是不能運行的,必須放到ARM CPU平台上才能運行,雖然兩個平台用的都是Linux系統。這種方法在異平台移植和嵌入式研發時非常有用。相對和交叉編譯,平常做的編譯叫本地編譯,也就是在當前平台編譯,編譯得到的程式也是在本地執行。用來編譯這種跨平台程式的編譯器就叫交叉編譯器,相對來說,用來做本地編譯的工具就叫本地編譯器。所以要生成在目標機上運行的程式,必須要用交叉編譯工具鏈來完成。在裁減和制定Linux內核用於嵌入式系統之前,由於一般嵌入式研發系統存儲大小有限,通常都要在性能優越的PC上建立一個用於目標機的交叉編譯工具鏈,用該交叉編譯工具鏈在PC上編譯目標機上要運行的程式。交叉編譯工具鏈是個由編譯器、連接器和解釋器組成的綜合研發環境,交叉編譯工具鏈主要由binutils、gcc和glibc 3個部分組成。有時出於減小 libc 庫大小的考慮,也能用別的 c 庫來代替 glibc,例如 uClibc、dietlibc 和 newlib。建立交叉編譯工具鏈是個相當復雜的過程,如果不想自己經歷復雜繁瑣的編譯過程,網上有一些編譯好的可用的交叉編譯工具鏈能下載,但就以學習為目的來說讀者有必要學習自己製作一個交叉編譯工具鏈。本章通過具體的實例講述基於ARM的嵌入式Linux交叉編譯工具鏈的製作過程。 構建交叉編譯器的第一個步驟就是確定目標平台。在GNU系統中,每個目標平台都有一個明確的格式,這些信息用於在構建過程中識別要使用的不同工具的正確版本。因此,當在一個特定目標機下運行GCC時,GCC便在目錄路徑中查找包含該目標規范的應用程式路徑。GNU的目標規范格式為CPU-PLATFORM-OS。例如x86/i386 目標機名為i686-pc-linux-gnu。本章的目的是講述建立基於ARM平台的交叉工具鏈,所以目標平台名為arm-linux-gnu。 通常構建交叉工具鏈有3種方法。 方法一 分步編譯和安裝交叉編譯工具鏈所需要的庫和原始碼,最終生成交叉編譯工具鏈。該方法相對比較困難,適合想深入學習構建交叉工具鏈的讀者。如果只是想使用交叉工具鏈,建議使用方法二或方法三構建交叉工具鏈。 方法二 通過Crosstool腳本工具來實現一次編譯生成交叉編譯工具鏈,該方法相對於方法一要簡單許多,並且出錯的機會也非常少,建議大多數情況下使用該方法構建交叉編譯工具鏈。 方法三 直接通過網上(ftp.arm.kernel.org.uk)下載已製作好的交叉編譯工具鏈。該方法的好處不用多說,當然是簡單省事,但和此同時該方法有一定的弊端就是局限性太大,因為畢竟是別人構建好的,也就是固定的沒有靈活性,所以構建所用的庫及編譯器的版本也許並不適合你要編譯的程式,同時也許會在使用時出現許多莫名的錯誤,建議讀者慎用此方法。 為了讓讀者真正的學習交叉編譯工具鏈的構建,下面將重點周詳地介紹前兩種構建ARM Linux交叉編譯工具鏈的方法。 2.2.1 分步構建交叉編譯鏈 分步構建,顧名思義就是一步一步地建立交叉編譯鏈,不同於2.2.2節中講述的Crosstool腳本工具一次編譯生成的方法,該方法適合那些希望深入學習了解構建交叉編譯工具鏈的讀者。該方法相對來說難度較大,通常情況下困難重重,猶如唐僧西天取經,不過本文會盡可能周詳地介紹構建的每一個步驟,讀者完萬能根據本節的內容自己獨立實踐,構建自己的交叉工具鏈。該過程所需的時間較長,希望讀者有較強的耐心和毅力去學習和實踐他,通過實踐能使讀者更加清晰交叉編譯器的構建過程及各個工具包的作用。該方法所需資源如表2.1所示。 表2.1 所需資源 安裝包 下載地址 安裝包 下載地址 linux-2.6.10.tar.gz ftp.kernel.org glibc-2.3.2.tar.gz ftp.gnu.org binutils-2.15.tar.bz2 ftp.gnu.org glibc-linuxthreads-2.3.2.tar.gz ftp.gnu.org gcc-3.3.6.tar.gz ftp.gnu.org 通過相關站點下載以上資源後,就能開始建立交叉編譯工具鏈了。 1.建立工作目錄 首先建立工作目錄,工作目錄就是在什麼目錄下構建交叉工具鏈,目錄的構建一般沒有特別的需求,能根據個人喜好建立。以下所建立的目錄是作者自定義的,當前的用戶定義為mike,因此用戶目錄為/home/mike,在用戶目錄下首先建立一個工作目錄(armlinux),建立工作目錄的命令行操作如下: # cd /home/mike # mkdir armlinux 再在這個工作目錄armlinux下建立3個目錄 build-tools、kernel 和 tools。具體操作如下: # cd armlinux # mkdir build-tools kernel tools 其中各目錄的作用如下。 ● build-tools 用來存放下載的binutils、gcc、glibc等原始碼和用來編譯這些原始碼的目錄; ● kernel 用來存放內核原始碼; ● tools 用來存放編譯好的交叉編譯工具和庫文件。 2.建立環境變數 該步驟的目的是為了方便重復輸入路徑,因為重復操作每件相同的事情總會讓人覺得非常麻煩,如果讀者不習慣使用環境變數就能略過該步,直接輸入絕對路徑就能。聲明以下環境變數的目的是在之後編譯工具庫的時候會用到,非常方便輸入,尤其是能降低輸錯路徑的風險。 # export PRJROOT=/home/mike/armlinux # export TARGET=arm-linux # export PREFIX=$PRJROOT/tools # export TARGET_PREFIX=$PREFIX/$TARGET # export PATH=$PREFIX/bin:$PATH 注意,用export聲明的變數是臨時的變數,也就是當注銷或更換了控制台,這些環境變數就消失了,如果還需要使用這些環境變數就必須重復export操作,所以有時會非常麻煩。值得慶幸的是,環境變數也能定義在bashrc文件中,這樣當注銷或更換控制台時,這些變數就一直有效,就不用老是export這些變數了。 3.編譯、安裝Binutils Binutils是GNU工具之一,他包括連接器、匯編器和其他用於目標文件和檔案的工具,他是二進制代碼的處理維護工具。安裝Binutils工具包含的程式有addr2line、ar、as、c++filt、gprof、ld、nm、obj、objmp、ranlib、readelf、size、strings、strip、libiberty、libbfd和libopcodes。對這些程式的簡單解釋如下。 ● addr2line 把程式地址轉換為文件名和行號。在命令行中給他一個地址和一個可執行文件名,他就會使用這個可執行文件的調試信息指出在給出的地址上是哪個文件及行號。 ● ar 建立、修改、提取歸檔文件。歸檔文件是包含多個文件內容的一個大文件,其結構確保了能恢復原始文件內容。 ● as 主要用來編譯GNU C編譯器gcc輸出的匯編文件,產生的目標文件由連接器ld連接。 ● c++filt 連接器使用他來過濾 C++ 和 Java 符號,防止重載函數沖突。 ● gprof 顯示程式調用段的各種數據。 ● ld 是連接器,他把一些目標和歸檔文件結合在一起,重定位數據,並連接符號引用。通常,建立一個新編譯程式的最後一步就是調用ld。 ● nm 列出目標文件中的符號。 ● obj 把一種目標文件中的內容復制到另一種類型的目標文件中。 ● objmp 顯示一個或更多目標文件的信息。使用選項來控制其顯示的信息,他所顯示的信息通常只有編寫編譯工具的人才感興趣。 ● ranlib 產生歸檔文件索引,並將其保存到這個歸檔文件中。在索引中列出了歸檔文件各成員所定義的可重分配目標文件。 ● readelf 顯示elf格式可執行文件的信息。 ● size 列出目標文件每一段的大小及總體的大小。默認情況下,對於每個目標文件或一個歸檔文件中的每個模塊只產生一行輸出。 ● strings 列印某個文件的可列印字元串,這些字元串最少4個字元長,也能使用選項-n設置字元串的最小長度。默認情況下,他只列印目標文件初始化和可載入段中的可列印字元;對於其他類型的文件他列印整個文件的可列印字元。這個程式對於了解非文本文件的內容非常有幫助。 ● strip 丟棄目標文件中的全部或特定符號。 ● libiberty 包含許多GNU程式都會用到的函數,這些程式有getopt、obstack、strerror、strtol和strtoul。 ● libbfd 二進制文件描述庫。 ● libopcode 用來處理opcodes的庫,在生成一些應用程式的時候也會用到他。 Binutils工具安裝依賴於Bash、Coreutils、Diffutils、GCC、Gettext、Glibc、Grep、Make、Perl、Sed、Texinfo等工具。 介紹完Binutils工具後,下面將分步介紹安裝binutils-2.15的過程。 首先解壓binutils-2.15.tar.bz2包,命令如下: # cd $PRJROOT/build-tools # tar -xjvf binutils-2.15.tar.bz2 接著設置Binutils工具,建議建立一個新的目錄用來存放設置和編譯文件,這樣能使源文件和編譯文件獨立開,具體操作如下: # cd $PRJROOT/build-tools # mkdir build-binutils # cd build-binutils # ../ binutils-2.15/configure --target=$TARGET --prefix=$PREFIX 其中選項?target的意思是制定生成的是 arm-linux 的工具,--prefix 是指出可執行文件安裝的位置。執行上述操作會出現非常多check信息,最後產生 Makefile 文件。接下來執行make和安裝操作,命令如下: # make # make install 該編譯過程較慢,需要數十分鍾,安裝完成後查看/home/mike/armlinux/tools/bin目錄下的文件,如果查看結果如下,表明此時Binutils工具已安裝結束。 # ls $PREFIX/bin arm-linux-addr2line arm-linux-ld arm-linux-ranlib arm-linux-strip arm-linux-ar arm-linux-nm arm-linux-readelf arm-linux-as arm-linux-obj arm-linux-size arm-linux-c++filt arm-linux-objmp arm-linux-strings 4.獲得內核頭文件 編譯器需要通過系統內核的頭文件來獲得目標平台所支持的系統函數調用所需要的信息。對於Linux內核,最佳的方法是下載一個合適的內核,然後復制獲得頭文件。需要對內核做一個基本的設置來生成正確的頭文件;不過,不必編譯內核。對於本例中的目標arm-linux,需要以下步驟。 (1)在kernel目錄下解壓linux-2.6.10.tar.gz內核包,執行命令如下: # cd $PRJROOT/kernel # tar -xvzf linux-2.6.10.tar.gz (2)接下來設置編譯內核使其生成正確的頭文件,執行命令如下: # cd linux-2.6.10 # make ARCH=arm CROSS_COMPILE=arm-linux- menuconfig 其中ARCH=arm表示是以arm為體系結構,CROSS_COMPILE=arm-linux-表示是以arm-linux-為前綴的交叉編譯器。也能用config和xconfig來代替menuconfig,推薦用make menuconfig,這也是內核研發人員用的最多的設置方法。注意在設置時一定要選擇處理器的類型,這里選擇三星的S3C2410(System Type->ARM System Type->/Samsung S3C2410),如圖2.1所示。設置完退出並保存,檢查一下內核目錄中的include/linux/version.h和include/linux/autoconf.h文件是不是生成了,這是編譯glibc時要用到的,如果version.h 和 autoconf.h 文件存在,說明生成了正確的頭文件。 screen.width*0.7) {this.resized=true; this.width=screen.width*0.7; this.alt=』Click here to open new window\nCTRL+Mouse wheel to zoom in/out』;}" border=0> 圖2.1 Linux 2.6.10內核設置界面 復制頭文件到交叉編譯工具鏈的目錄,首先需要在/home/mike/armlinux/tools/arm-linux目錄下建立工具的頭文件目錄inlcude,然後復制內核頭文件到此目錄下,具體操作如下: # mkdir -p $TARGET_PREFIX/include # cp -r $PRJROOT/kernel/linux-2.6.10/include/linux $TARGET_PREFIX/include # cp -r $PRJROOT/kernel/linux-2.6.10/include/asm-arm $TARGET_PREFIX/include/asm 5.編譯安裝boot-trap gcc 這一步的目的主要是建立arm-linux-gcc工具,注意這個gcc沒有glibc庫的支持,所以只能用於編譯內核、BootLoader等不必C庫支持的程式,後面創建C庫也要用到這個編譯器,所以創建他主要是為創建C庫做准備,如果只想編譯內核和BootLoader,那麼安裝完這個就能到此結束。安裝命令如下: # cd $PRJROOT/build-tools # tar -xvzf gcc-3.3.6.tar.gz # mkdir build-gcc # cd gcc-3.3.6 # vi gcc/config/arm/t-linux 由於是第一次安裝ARM交叉編譯工具,沒有支持libc庫的頭文件,所以在gcc/config/arm/t- linux文件中給變數TARGET_LIBGCC2_CFLAGS增加操作參數選項-Dinhibit_libc -D__gthr_ posix_h來屏蔽使用頭文件,否則一般默認會使用/usr/inlcude頭文件。 將TARGET_LIBGCC2-CFLAGS = -fomit-frame-pointer ?fPIC改為TARGET_LIBGCC2- CFLAGS=-fomit-frame-pointer-fPIC -Dinhibit_libc -D__gthr_posix_h 修改完t-linux文件後保存,緊接著執行設置操作,如下命令: # cd build-gcc # ../ build-gcc /configure --target=$TARGET --prefix=$PREFIX --enable-languages=c --disable-threads --disable-shared 其中選項--enable-languages=c表示只支持C語言,--disable-threads表示去掉thread功能,這個功能需要glibc的支持。--disable-shared表示只進行靜態庫編譯,不支持共享庫編譯。 接下來執行編譯和安裝操作,命令如下: # make # make install 安裝完成後,在/home/mike/armlinux/tools/bin下查看,如果arm-linux-gcc等工具已生成,表示boot-trap gcc工具已安裝成功。 6.建立glibc庫 glibc是GUN C庫,他是編譯Linux系統程式非常重要的組成部分。安裝glibc-2.3.2版本之前推薦先安裝以下的工具: ● GNU make 3.79或更新; ● GCC 3.2或更新; ● GNU binutils 2.13或更新。 首先解壓glibc-2.2.3.tar.gz和glibc-linuxthreads-2.2.3.tar.gz原始碼,操作如下: # cd $PRJROOT/build-tools # tar -xvzf glibc-2.2.3.tar.gz # tar -xzvf glibc-linuxthreads-2.2.3.tar.gz --directory=glibc-2.2.3 然後進行編譯設置,glibc-2.2.3設置前必須新建一個編譯目錄,否則在glibc-2.2.3目錄下不允許進行設置操作,此處在$PRJROOT/build-tools目錄下建立名為build-glibc的目錄,設置操作 如下: # cd $PRJROOT/build-tools # mkdir build-glibc # cd build-glibc # CC=arm-linux-gcc ../glibc-2.2.3 /configure --host=$TARGET --prefix="/usr" --enable-add-ons --with-headers=$TARGET_PREFIX/include 選項CC=arm-linux-gcc是把CC(Cross Compiler)變數設成剛編譯完的gcc,用他來編譯glibc。--prefix="/usr"定義了一個目錄用於安裝一些和目標機器無關的數據文件,默認情況下是/usr/local目錄。--enable-add-ons是告訴glibc用linuxthreads包,在上面已將他放入glibc原始碼目錄中,這個選項等價於-enable-add-ons=linuxthreads。--with-headers告訴glibc linux內核頭文件的目錄 位置。 設置完後就能編譯和安裝 glibc了,具體操作如下: # make # make install 7.編譯安裝完整的gcc 由於第一次安裝的gcc沒有交叉glibc的支持,目前已安裝了glibc,所以需要重新編譯來支持交叉glibc。並且上面的gcc也只支持C語言,目前能讓他同時支持C語言還要和C++語言。具體操作如下: # cd $PRJROOT/build-tools/gcc-2.3.6 # ./configure --target=arm-linux --enable-languages=c,c++ --prefix=$PREFIX # make # make install 安裝完成後會發目前$PREFIX/bin目錄下又多了arm-linux-g++ 、arm-linux-c++等文件。 # ls $PREFIX/bin arm-linux-addr2line arm-linux-g77 arm-linux-gnatbind arm-linux-ranlib arm-linux-ar arm-linux-gcc arm-linux-jcf-mp arm-linux-readelf arm-linux-as arm-linux-gcc-3.3.6 arm-linux-jv-scan arm-linux-size arm-linux-c++ arm-linux-gccbug arm-linux-ld arm-linux-strings arm-linux-c++filt arm-linux-gcj arm-linux-nm arm-linux-strip arm-linux-cpp arm-linux-gcjh arm-linux-obj grepjar arm-linux-g++ arm-linux-gcov arm-linux-objmp jar 8.測試交叉編譯工具鏈 到此為止,已介紹完了用分步構建的方法建立交叉編譯工具鏈。下面通過一個簡單的程式測試剛剛建立的交叉編譯工具鏈看是否能夠正常工作。寫一個最簡單的hello.c源文件,內容如下: #include int main( ) { printf(「Hello,world!\n」); return 0; } 通過以下命令進行編譯,編譯後生成名為hello的可執行文件,通過file命令能查看文件的類型。當顯示以下信息時表明交叉工具鏈正常安裝了,通過編譯生成了ARM體系可執行的文件。注意,通過該交叉編譯鏈編譯的可執行文件只能在ARM體系下執行,不能在基於X86的普通PC上執行。 # arm-linux-gcc -o hello hello.c # file hello hello: ELF 32-bit LSB executable, ARM, version 1 (ARM), for GNU/Linux 2.4.3, dynamically linked (uses shared libs), not stripped 2.2.2 用Crosstool工具構建交叉工具鏈 Crosstool是一組腳本工具集,可構建和測試不同版本的gcc和glibc,用於那些支持glibc的體系結構。他也是個開源項目,下載地址是http://kegel.com/crosstool。用Crosstool構建交叉工具鏈要比上述的分步編譯容易得多,並且也方便許多,對於僅僅為了工作需要構建交叉編譯工具鏈的讀者建議使用此方法。用Crosstool工具構建所需資源如表2.2所示。

Ⅵ 如何編譯成EXE應用程序

操作步驟:
第一步:打開VC++6.0;

第二步:選擇「文件」-》「新建」-》「工作區」-》「空白工作區」,然後為這個工作區起一個名字並選擇存放路徑,確定即可!
之所以要用工作區,因為可以在工作區中新建很多工程,每個工程可以獨立編譯、連接、執行,互補干擾,而在學習C語言過程中,時常要編輯一些小程序,把它們按工程都存放在一個工作區里,非常方便於查看、執行和管理;

第三步:右擊剛才新建的工作區,添加工程,這里選擇Win32 console Application並確定;

第四步:在新建的工程中添加文件,選擇C++ Source File,但是文件擴展名記得用「.c」;

第五步:編輯源代碼;

第六步:單擊工程,並選擇執行,即可一次性完成編譯、連接和執行工作,就可以看到程序運行結果了,當然也可以分步編譯、連接、執行!

Ⅶ 簡單描述編譯的幾個處理步驟

編譯過程分為分析和綜合兩個部分,並進一步劃分為詞法分析、語法分析、語義分析、代碼優化、存儲分配和代碼生成等六個相繼的邏輯步驟。這六個步驟只表示編譯程序各部分之間的邏輯聯系,而不是時間關系。

編譯過程既可以按照這六個邏輯步驟順序地執行,也可以按照平行互鎖方式去執行。在確定編譯程序的具體結構時,常常分若干遍實現。對於源程序或中間語言程序,從頭到尾掃視一次並實現所規定的工作稱作一遍。每一遍可以完成一個或相連幾個邏輯步驟的工作。

(7)一步編譯分步編譯擴展閱讀:

對於c編譯程序來說,其語言的特點如下:

1、c語言是一種結構化語言。它層次清晰,便於按模塊化方式組織程序,易於調試和維護,而且表現能力和處理能力極強。

2、c語言具有豐富的運算符和數據類型,便於實現各類復雜的數據結構。它還可以直接訪問內存的物理地址,進行位(bit)一級的操作。

3、由於c語言實現了對硬體的編程操作,因此集高級語言和低級語言的功能於一體。它既可用於系統軟體的開發,也適合於應用軟體的開發。

4、此外,c語言還具有效率高、可移植性強等特點。因此它廣泛地移植到了各類各型計算機上,從而形成了多種版本。

Ⅷ 開發一個c語言程序要經過哪四個步驟

開發一個C語言程序需要經過的四個步驟:編輯、編譯、連接、運行。

C語言程序可以使用在任意架構的處理器上,只要那種架構的處理器具有對應的C語言編譯器和庫,然後將C源代碼編譯、連接成目標二進制文件之後即可運行。

1、預處理:輸入源程序並保存(.C文件)。

2、編譯:將源程序翻譯為目標文件(.OBJ文件)。

3、鏈接:將目標文件生成可執行文件( .EXE文件)。

4、運行:執行.EXE文件,得到運行結果。

(8)一步編譯分步編譯擴展閱讀:

C語言代碼變為程序的幾個階段:

1、首先是源代碼文件test.c和相關的頭文件,如stdio.h等被預處理器cpp預處理成一個.i文件。經過預編譯後的.i文件不包含任何宏定義,因為所有的宏已經被展開,並且包含的文件也已經被插入到.i文件中。

2、編譯過程就是把預處理完的文件進行一系列的詞法分析、語法分析、語義分析以及優化後產生相應的匯編代碼文件,這個過程往往是我們所說的整個程序的構建的核心部分,也是最復雜的部分之一。

3、匯編器不直接輸出可執行文件而是輸出一個目標文件,匯編器可以調用ld產生一個能夠運行的可執行程序。即需要將一大堆文件鏈接起來才可以得到「a.out」,即最終的可執行文件。

4、在鏈接過程中,對其他定義在目標文件中的函數調用的指令需要被重新調整,對實用其他定義在其他目標文件的變數來說,也存在同樣問題。

參考資料來源:網路-c語言

Ⅸ 怎麼用DEV-C++編譯c語言

程序必段先編譯後運行的,編譯為「Compile」,運行為「Run」。

點擊菜單「Execute」——「Compile & Run」(快捷鍵:F9)即可一步完成編譯和運行;依據自己的情況,也可以將「Compile」和「Run」分步完成。

你是初學者的話,推薦使用Turbo C&C++作為入門的編程工具,C語系的DOS類頭文件很有可能無法在DEV上使用,例如:graphics.h這個Dos圖形庫頭文件在DEV中不可用,因為DEV是面向Windows的工具。

閱讀全文

與一步編譯分步編譯相關的資料

熱點內容
p在單片機里什麼意思 瀏覽:25
linuxwireshark使用教程 瀏覽:656
手機訪問阿里伺服器地址 瀏覽:678
程序員可以干什麼 瀏覽:70
績效考核權重分配演算法 瀏覽:524
android應用logo 瀏覽:898
光遇安卓服墓土商店什麼時候開 瀏覽:566
月收益翻倍的源碼 瀏覽:638
asop源碼放在哪裡 瀏覽:989
電腦伺服器密碼怎麼找 瀏覽:574
jdp轉換pdf 瀏覽:749
把pdf導入iphone 瀏覽:508
米哈游租賃的雲伺服器是哪個 瀏覽:524
android直接打電話 瀏覽:1018
ubuntu停止命令 瀏覽:285
cnc攻絲編程 瀏覽:870
換個手機號碼app怎麼注冊 瀏覽:321
怎麼下載小猴口算app 瀏覽:117
輕鏈app的貨怎麼樣 瀏覽:627
電腦里的u盤如何加密 瀏覽:372