Linux開發(fā)基礎(chǔ)_第1頁
Linux開發(fā)基礎(chǔ)_第2頁
Linux開發(fā)基礎(chǔ)_第3頁
Linux開發(fā)基礎(chǔ)_第4頁
Linux開發(fā)基礎(chǔ)_第5頁
已閱讀5頁,還剩45頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡介

1、Linux開發(fā)基礎(chǔ)開發(fā)基礎(chǔ) 主要內(nèi)容主要內(nèi)容 Linux函數(shù)庫 如何使用如何使用GCC GDB簡介 Makefile SVN/GIT版本控制軟件 Linux下函數(shù)庫(下函數(shù)庫(1/3) 一個(gè)“程序函數(shù)庫”就是一個(gè)文件包含了一些編譯好的代碼和數(shù) 據(jù),這些編譯好的代碼和數(shù)據(jù)可以在事后供其他的程序使用。程 序函數(shù)庫可以使整個(gè)程序更加模塊化,更容易重新編譯,而且更 方便升級??煞譃閮煞N類型: 靜態(tài)函數(shù)庫(static libraries):是一個(gè)普通的目標(biāo)文件的集合, 一般用“.a”作為文件的后綴。靜態(tài)函數(shù)庫和共享函數(shù)庫相比有 很多的缺點(diǎn),占用內(nèi)存空間多。但使用ELF格式的靜態(tài)庫函數(shù) 生成的代碼可以比

2、使用共享函數(shù)庫的程序運(yùn)行速度上快一些。 可以用ar這個(gè)程序來創(chuàng)建一個(gè)靜態(tài)函數(shù)庫文件,或者往一個(gè)已 經(jīng)存在地靜態(tài)函數(shù)庫文件添加新的目標(biāo)代碼。 例如, 把file1.o和file2.o加入到my_library.a這個(gè)函數(shù)庫文件: arm-linux-ar rcs my_library.a file1.o file2.o 然后運(yùn)行 arm-linux-ranlib,以給庫加入一些索引信息 Linux下函數(shù)庫(下函數(shù)庫(2/3) 共享函數(shù)庫(shared libraries):當(dāng)一個(gè)可執(zhí)行程序在啟動(dòng)的時(shí)候 被加載的函數(shù)。每個(gè)共享函數(shù)庫都有個(gè)特殊的名字,稱作 “soname”。soname名字命名必須

3、以“l(fā)ib”作為前綴,然后是函 數(shù)庫的名字,然后是“.so”,最后是版本號信息。 優(yōu)點(diǎn):多進(jìn)程使用同一函數(shù)庫;修改函數(shù)庫不需重新連編。 安裝一個(gè)新版本的函數(shù)庫的時(shí)候,要先將這些函數(shù)庫文件拷貝 到一些特定的目錄中,運(yùn)行l(wèi)dconfig就可以。ldconfig檢查已經(jīng) 存在的庫文件,然后創(chuàng)建soname的符號鏈接到真正的函數(shù)庫, 同時(shí)設(shè)置/etc/ld.so.cache這個(gè)緩沖文件。 例如,創(chuàng)建兩個(gè)目標(biāo)文件(a.o和b.o),然后創(chuàng)建一個(gè)包含a.o和 b.o的共享函數(shù)庫。 arm-linux-gcc -fPIC -g -c -Wall a.c arm-linux-gcc -fPIC -g -c -

4、Wall b.c arm-linux-gcc -shared Wl -o liblusterstuff.so.1.0.1 a.o b.o 注:” -fPIC ”是位置無關(guān)參數(shù), ”-g”和“Wall”參數(shù)不是必須的。 Linux下函數(shù)庫(下函數(shù)庫(3/3) 函數(shù)庫和頭文件的保存位置 a. 函數(shù)庫 /lib:系統(tǒng)必備共享函數(shù)庫:系統(tǒng)必備共享函數(shù)庫 /usr/lib:標(biāo)準(zhǔn)共享函數(shù)庫和靜態(tài)函數(shù)庫 /usr/i486-linux-libc5/lib:libc5 兼容性函數(shù)庫 /usr/X11R6/lib:X11R6 的函數(shù)庫 /usr/local/lib:本地函數(shù)庫 b. 頭文件 /usr/inclu

5、de:系統(tǒng)頭文件:系統(tǒng)頭文件 /usr/local/include:本地頭文件 c. 共享函數(shù)庫的相關(guān)配置和命令 /etc/ld.so.conf:包含共享庫的搜索位置 ldconfig:共享庫管理工具,一般在更新了共享庫之后要運(yùn)行該命令 ldd:可查看可執(zhí)行文件所使用的共享函數(shù)庫 使用使用GNU cc開發(fā)應(yīng)用程序開發(fā)應(yīng)用程序 gcc的簡介 可執(zhí)行文件的格式可執(zhí)行文件的格式 gcc的使用 gcc的簡介的簡介 gcc 是 GNU 的 C 和 C+ 編譯器。實(shí)際上,gcc 能夠編譯多種多種語 言:C、C+ 和 Object C等。利用 gcc 命令可同時(shí)編譯并連接 C 和 C+ 源程序。也可以對幾個(gè)

6、 C 源文件利用 gcc 編譯、連接并 生成可執(zhí)行文件。 gcc可以使程序員靈活地控制編譯過程。編譯過程一般可以分為 下面四個(gè)階段,每個(gè)階段分別調(diào)用不同的工具進(jìn)行處理 預(yù)處理鏈接編譯組譯源 程 序 (*.c) 可執(zhí)行文件 預(yù)處理器編譯器組譯器連接器 gcc的四個(gè)階段的四個(gè)階段 命令gcc首先調(diào)用cpp進(jìn)行預(yù)處理,在預(yù)處理過程中,對源代碼 文件中的文件包含(include)、預(yù)編譯語句(如宏定義define等)進(jìn)行 分析。 接著調(diào)用cc1進(jìn)行編譯,這個(gè)階段根據(jù)輸入文件生成以.o為后綴 的目標(biāo)文件。 匯編過程是針對匯編語言的步驟,調(diào)用as進(jìn)行工作,一般來 講,.S或.s為后綴的匯編語言源代碼文件匯

7、編之后都生成以.o為 后綴的目標(biāo)文件。 當(dāng)所有的目標(biāo)文件都生成之后,gcc就調(diào)用ld來完成最后的關(guān)鍵 性工作,這個(gè)階段就是連接。在連接階段,所有的目標(biāo)文件被安 排在可執(zhí)行程序中的恰當(dāng)?shù)奈恢?,同時(shí),該程序所調(diào)用到的庫函 數(shù)也從各自所在的函數(shù)庫中連到合適的地方。 可執(zhí)行文件格式 Linux系統(tǒng)中可執(zhí)行文件有兩種格式。 第一種格式是a.out格式,這種格式用于早期的Linux系統(tǒng)以及 Unix系統(tǒng)的原始格式。a.out來自于Unix C編譯程序默認(rèn)的可執(zhí) 行文件名。當(dāng)使用共享庫時(shí),a.out格式就會(huì)發(fā)生問題。把a(bǔ).out 格式調(diào)整為共享庫是一種非常復(fù)雜的操作。 因此,一種新的文件格式被引入U(xiǎn)nix系

8、統(tǒng)5的第四版本和 Solaris系統(tǒng)中。它被稱為可執(zhí)行和連接的格式(ELF)。這種 格式很容易實(shí)現(xiàn)共享庫。 ELF格式已經(jīng)被格式已經(jīng)被Linux系統(tǒng)作為標(biāo)準(zhǔn)的格式采用。系統(tǒng)作為標(biāo)準(zhǔn)的格式采用。 gcc編譯程序產(chǎn)生的所有的二進(jìn)制文件都是ELF格式的文件(即 使可執(zhí)行文件的默認(rèn)名仍然是a.out)。較舊的a.out格式的程序 仍然可以運(yùn)行在支持ELF格式的系統(tǒng)上。 GNU C 的使用的使用 基本語法 gcc options filenames 說明: 在gcc后面可以有多個(gè)編譯選項(xiàng),同時(shí)進(jìn)行多個(gè)編譯操作。很 多的gcc選項(xiàng)包括一個(gè)以上的字符。因此你必須為每個(gè)選項(xiàng)指 定各自的連字符。例如,下面的兩個(gè)

9、命令是不同的: gcc -p -g test1.c gcc -pg test1.c 當(dāng)你不用任何選項(xiàng)編譯一個(gè)程序時(shí),GCC將會(huì)建立(假定編譯成 功)一個(gè)名為a.out的可執(zhí)行文件。 gcc選項(xiàng)選項(xiàng) -o選項(xiàng)選項(xiàng) 你能用你能用 -o 編譯選項(xiàng)來為將產(chǎn)生的可執(zhí)行文件指定一個(gè)文件名編譯選項(xiàng)來為將產(chǎn)生的可執(zhí)行文件指定一個(gè)文件名 來代替來代替 a.out。 例:例:gcc o count count.c -c選項(xiàng):告訴GCC僅把源代碼編譯為目標(biāo)代碼而跳過匯編和連接 的步驟。這個(gè)選項(xiàng)使用的非常頻繁,因?yàn)樗沟镁幾g多個(gè)C程 序時(shí)速度更快并且更易于管理。缺省時(shí)GCC建立的目標(biāo)代碼 文件有一個(gè).o的擴(kuò)展名。 例

10、:gcc c test2.c -E 只運(yùn)行 C 預(yù)編譯器。 -S 編譯選項(xiàng)告訴 gcc 在為 C 代碼產(chǎn)生了匯編語言文件后停止編 譯。 -shared 生成共享目標(biāo)文件。通常用在建立共享庫時(shí)。 -static 禁止使用共享連接。 警告選項(xiàng) 在在gccgcc中用開關(guān)中用開關(guān)-Wall-Wall控制警告信息,使用示例命令如下:控制警告信息,使用示例命令如下: gcc gcc Wall -o test3_1 test3_1.cWall -o test3_1 test3_1.c -w -w 不生成任何警告信息。不生成任何警告信息。 查找選項(xiàng)查找選項(xiàng) gcc一般使用默認(rèn)路徑查找頭文件和庫文件。如果文件所

11、用的 頭文件或庫文件不在缺省目錄下,則編譯時(shí)要指定它們的 查找路徑。 -I選項(xiàng):指定頭文件的搜索目錄 例: gcc I/export/home/st o test1 test1.c -L選項(xiàng):指定庫文件的搜索目錄 例: gcc L/usr/X11/R6/lib o test1 test1.c 多個(gè)源文件生成一個(gè)可執(zhí)行文件多個(gè)源文件生成一個(gè)可執(zhí)行文件 問題:有多個(gè)源文件時(shí),如何生成一個(gè)可執(zhí)行文件? 方法1:gcc Wall o mytest test1.c test2.c test3.c 方法2: gcc-Wall -c test1.c gcc-Wall c test2.c gcc-Wall c

12、 test3.c gcc o mytest test1.o test2.o test3.o 優(yōu)化選項(xiàng)優(yōu)化選項(xiàng) 優(yōu)化選項(xiàng)可以使GCC在耗費(fèi)更多編譯時(shí)間和犧牲易調(diào)試性的基礎(chǔ) 上產(chǎn)生更小更快的可執(zhí)行文件。這些選項(xiàng)中最典型的是-O和-O2 選項(xiàng)。 -O0 不進(jìn)行優(yōu)化處理。 -O選項(xiàng):告訴GCC對源代碼進(jìn)行基本優(yōu)化。這些優(yōu)化在大多數(shù) 情況下都會(huì)使程序執(zhí)行的更快。 -O2選項(xiàng):告訴GCC 產(chǎn)生盡可能小和盡可能快的代碼。-O2選 項(xiàng)將使編譯的速度比使用-O時(shí)慢。但通常產(chǎn)生的代碼執(zhí)行速度 會(huì)更快。 -O3選項(xiàng):比 -O2 更進(jìn)一步優(yōu)化,包括 inline 函數(shù)。 版本選項(xiàng)版本選項(xiàng) -v選項(xiàng) 用戶將會(huì)得到自己目

13、前正在使用的gcc的版本及與版本相關(guān)的 一些信息。 gcc -v 將得到如下結(jié)果: Reading specs from /usr/lib/gcc-lib/i486-box-linux/2.7.2/specs gcc version 2.7.2 -V 選項(xiàng) 如果安裝了多個(gè)版本的gcc,并且想強(qiáng)制執(zhí)行其中的某個(gè)版本, 可以用命令通知系統(tǒng)用戶要使用的版本。 gcc -V2.6.3 -v 宏定義選項(xiàng)宏定義選項(xiàng) -D MACRO 以字符串以字符串“1”定義定義 MACRO 宏。宏。 -D MACRO=DEFN 以字符串“DEFN”定義 MACRO 宏。 -U MACRO 取消對 MACRO 宏的定義。

14、 調(diào)試和剖析選項(xiàng)調(diào)試和剖析選項(xiàng) 使用調(diào)試選項(xiàng)后,gcc在進(jìn)行編譯的時(shí)候,在目標(biāo)文件(.o)和 創(chuàng)建的可執(zhí)行文件中插入額外信息,這些額外信息使gdb能夠判 斷編譯過的代碼和源代碼之間的關(guān)系。 -g選項(xiàng):告訴GCC產(chǎn)生能被 GNU 調(diào)試器使用的調(diào)試信息以便調(diào) 試你的程序。 例:例:gcc g o test3 test3.c -pg選項(xiàng):告訴GCC在你的程序里加入額外的代碼,執(zhí)行時(shí),產(chǎn) 生gprof用的剖析信息以顯示你的程序的耗時(shí)情況。 使用gdb調(diào)試工具,命令行如下: 例:gcc ggdb3 o test3 test3.c 調(diào)試工具調(diào)試工具gdb GDB調(diào)試器簡介 gdb 的常用命令 gdb應(yīng)用實(shí)

15、例 gdb 簡介簡介 Linux系統(tǒng)中包含了GNU 調(diào)試程序gdb,它是一個(gè)用來調(diào)試C和 C+ 程序的調(diào)試器??梢允钩绦蜷_發(fā)者在程序運(yùn)行時(shí)觀察程序的 內(nèi)部結(jié)構(gòu)和內(nèi)存的使用情況。 gdb 所提供的一些功能如下所示: 運(yùn)行程序,設(shè)置所有的能影響程序運(yùn)行的參數(shù)和環(huán)境; 控制程序在指定的條件下停止運(yùn)行; 當(dāng)程序停止時(shí),可以檢查程序的狀態(tài); 修改程序的錯(cuò)誤,并重新運(yùn)行程序; 動(dòng)態(tài)監(jiān)視程序中變量的值; 可以單步逐行執(zhí)行代碼,觀察程序的運(yùn)行狀態(tài)。 分析崩潰程序的產(chǎn)生的core文件 gdb的特點(diǎn)的特點(diǎn) gdb的功能非常強(qiáng)大 到目前為止,gdb已能夠支持Moduls-2、Chill、Pascal和 FORTRA

16、N程序的調(diào)試,但是調(diào)試這些語言的源程序時(shí)有一些 功能還不能使用。 例如調(diào)試FORTRAN程序時(shí)還不支持表達(dá)式的輸入、輸出變量 或類FORTRAN的詞法。 gdb程序調(diào)試的對象是可執(zhí)行文件,而不是程序的源代碼文件。 然而,并不是所有的可執(zhí)行文件都可以用gdb調(diào)試。如果要讓產(chǎn) 生的可執(zhí)行文件可以用來調(diào)試,需在執(zhí)行g(shù)cc指令編譯程序時(shí), 加上-g參數(shù),指定程序在編譯時(shí)包含調(diào)試信息。 調(diào)試信息包含程序里的每個(gè)變量的類型和在可執(zhí)行文件里的地址 映射以及源代碼的行號。 gdb 利用這些信息使源代碼和機(jī)器碼相關(guān)聯(lián)。 gdb是一個(gè)用來調(diào) 試C和C+程序的常用調(diào)試工具之一。 gdb的啟動(dòng)的啟動(dòng) 在命令行上輸入g

17、db并按回車鍵就可以運(yùn)行g(shù)db了,如果一切正常 的話,將啟動(dòng)gdb gdb filename 出現(xiàn) (gdb) 在這里,可以輸入調(diào)試命令 在可以使用 gdb 調(diào)試程序之前,必須使用 -g 選項(xiàng)編譯源文件。 可在 makefile 中如下定義 CFLAGS 變量: CFLAGS = -g 運(yùn)行 獲取幫助信息獲取幫助信息 啟動(dòng)gdb后,可以在命令行上指定很多的選項(xiàng)。輸入: help 可以獲得gdb的幫助信息。 如果想要了解某個(gè)具體命令(比如break)的幫助信息,在gdb提 示符下輸入下面的命令: break 屏幕上會(huì)顯示關(guān)于break的幫助信息。從返回的信息可知,break 是用于設(shè)置斷點(diǎn)的命令

18、。 另一個(gè)獲得gdb幫助的方法是瀏覽gdb的手冊頁。在Linux Shell提 示符輸入: man gdb 可以看到man的手冊頁 gdb命令的分類命令的分類 在 gdb 提示符處鍵入help,將列出命令的分類,主要的分類有: aliases:命令別名 breakpoints:斷點(diǎn)定義; data:數(shù)據(jù)查看; files:指定并查看文件; internals:維護(hù)命令; running:程序執(zhí)行; stack:調(diào)用棧查看; statu:狀態(tài)查看; tracepoints:跟蹤程序執(zhí)行。 后跟命令的分類名,可獲得該類命令的詳細(xì)清單 基本基本gdb命令(命令(1/2) file命令:裝入想要調(diào)試的

19、可執(zhí)行文件。 cd命令:改變工作目錄。 pwd命令:返回當(dāng)前工作目錄。 run命令:執(zhí)行當(dāng)前被調(diào)試的程序。 kill命令:停止正在調(diào)試的應(yīng)用程序。 list命令:列出正在調(diào)試的應(yīng)用程序的源代碼。 break命令:設(shè)置斷點(diǎn)。 watch命令:設(shè)置監(jiān)視點(diǎn),監(jiān)視表達(dá)式的變化。 awatch命令:設(shè)置讀寫監(jiān)視點(diǎn)。當(dāng)要監(jiān)視的表達(dá)式被讀或?qū)憰r(shí)將 應(yīng)用程序掛起。它的語法與watch命令相同。 rwatch命令:設(shè)置讀監(jiān)視點(diǎn),當(dāng)監(jiān)視表達(dá)式被讀時(shí)將程序掛起, 等侍調(diào)試。此命令的語法與watch相同。 next命令:執(zhí)行下一條源代碼,但是不進(jìn)入函數(shù)內(nèi)部。也就是說, 將一條函數(shù)調(diào)用作為一條語句執(zhí)行。執(zhí)行這個(gè)命令的前

20、提是已經(jīng) run,開始了代碼的執(zhí)行。 基本基本gdb命令(命令(2/2) step命令:執(zhí)行下一條源代碼,進(jìn)入函數(shù)內(nèi)部。如果調(diào)用了某個(gè) 函數(shù),會(huì)跳到函數(shù)所在的代碼中等候一步步執(zhí)行。執(zhí)行這個(gè)命令 的前提是已經(jīng)用run開始執(zhí)行代碼。 display命令:在應(yīng)用程序每次停止運(yùn)行時(shí)顯示表達(dá)式的值。 info break命令:顯示當(dāng)前斷點(diǎn)列表,包括每個(gè)斷點(diǎn)到達(dá)的次數(shù) 16)info files命令:顯示調(diào)試文件的信息。 17)info func命令:顯示所有的函數(shù)名。 18)info local命令:顯示當(dāng)前函數(shù)的所有局部變量的信息。 19)info prog命令:顯示調(diào)試程序的執(zhí)行狀態(tài)。 20)pri

21、nt命令;顯示表達(dá)式的值。 21)delete命令:刪除斷點(diǎn)。指定一個(gè)斷點(diǎn)號碼,則刪除指定斷 點(diǎn)。不指定參數(shù)則刪除所有的斷點(diǎn)。 22)Shell命令:執(zhí)行Linux Shell命令。 23)make命令:不退出gdb而重新編譯生成可執(zhí)行文件。 24)Quit命令:退出gdb。 gdb 使用實(shí)例(使用實(shí)例(1/2) /* 一個(gè)有錯(cuò)誤的 C 源程序 */ #include #include static char buff 256; static char* string; int main () printf (Please input a string: ); gets (string); p

22、rintf (nYour string is: %sn, string); 上面這個(gè)程序非常簡單,其目的是接受用戶的輸入,然后將用戶 的輸入打印出來。該程序使用了 一個(gè)未經(jīng)過初始化的字符串地址 string,因此,編譯并運(yùn)行之后,將出現(xiàn) Segment Fault 錯(cuò)誤: $ gcc -o test -g test.c $ ./test Please input a string: asfd Segmentation fault (core dumped) gdb 使用實(shí)例(使用實(shí)例(2/2) 為了查找該程序中出現(xiàn)的問題,我們利用 gdb,并按如下的步驟 進(jìn)行: 1運(yùn)行 gdb bugging

23、 命令,裝入 bugging 可執(zhí)行文件; 2執(zhí)行裝入的 bugging 命令; 3使用 where 命令查看程序出錯(cuò)的地方; 4利用 list 命令查看調(diào)用 gets 函數(shù)附近的代碼; 5唯一能夠?qū)е?gets 函數(shù)出錯(cuò)的因素就是變量 string。用 print 命令查看 string 的值; 6在 gdb 中,我們可以直接修改變量的值,只要將 string 取 一個(gè)合法的指針值就可以了,為 此,我們在第 11 行處設(shè)置斷 點(diǎn); 7程序重新運(yùn)行到第 11 行處停止,這時(shí),我們可以用 set variable 命令修改 string 的取值; 8然后繼續(xù)運(yùn)行,將看到正確的程序運(yùn)行結(jié)果。 GN

24、U make和和makefile GNU make概述 Makefile 的基本結(jié)構(gòu) Makefile中的變量 GNU make 的主要預(yù)定義變量 Makefile的隱含規(guī)則 make命令行選項(xiàng) 使用automake和autoconf產(chǎn)生Makefile GNU make概述概述 在大型的開發(fā)項(xiàng)目中,人們通常利用 make 工具來自動(dòng)完成編譯 工作。這些工作包括: 如果僅修改了某幾個(gè)源文件,則只重新編譯這幾個(gè)源文件; 如果某個(gè)頭文件被修改了,則重新編譯所有包含該頭文件的源 文件。 利用這種自動(dòng)編譯可大大簡化開發(fā)工作,避免不必要的重新編 譯。 實(shí)際上,make 工具通過一個(gè)稱為 makefile

25、 的文件來完成并自動(dòng) 維護(hù)編譯工作。makefile 需要按照某種語法進(jìn)行編寫,其中說明 了如何編譯各個(gè)源文件并連接生成可執(zhí)行文件,并定義了源文件 之間的依賴關(guān)系。 當(dāng)修改了其中某個(gè)源文件時(shí),如果其他源文件 依賴于該文件,則也要重新編譯所有依賴該文件的源文件。 默認(rèn)情況下,GNU make 工具在當(dāng)前工作目錄按如下順序搜索 makefile: GNUmakefile makefile Makefile makefile舉例舉例 Linux程序員使用第三種文件名Makefile。因?yàn)榈谝粋€(gè)字母是大寫, 通常被列在一個(gè)目錄的文件列表的最前面。 如果要使用其他文件作為 makefile,則可利用類

26、似下面的 make 命令選項(xiàng)指定 makefile 文件: $ make -f Makefile.debug 例1:一個(gè)簡單的makefile prog:prog1.o prog2.o gcc prog1.o prog2.o -o prog prog1.o:prog1.c lib.h gcc -c -I. -o prog1.o prog1.c prog2.o:prog2.c gcc -c prog2.c Makefile 的基本結(jié)構(gòu)(的基本結(jié)構(gòu)(1/2) Makefile是一個(gè)文本形式的數(shù)據(jù)庫文件,其中包含一些規(guī)則來告 訴make處理哪些文件以及如何處理這些文件。 規(guī)則主要是描述哪些文件(稱為

27、target目標(biāo)文件,不要和編譯時(shí) 產(chǎn)生的目標(biāo)文件相混淆)是從哪些別的文件(稱為dependency 依賴文件)中產(chǎn)生的,以及用什么命令(command)來執(zhí)行這 個(gè)過程。 依靠這些信息,make會(huì)對磁盤上的文件進(jìn)行檢查,如果目標(biāo)文 件的生成或被改動(dòng)時(shí)的時(shí)間(稱為該文件時(shí)間戳)至少比它的一 個(gè)依賴文件還舊的話,make就執(zhí)行相應(yīng)的命令,以更新目標(biāo)文 件。 目標(biāo)文件不一定是最后的可執(zhí)行文件,可以是任何一個(gè)中間文件 并可以作為其他目標(biāo)文件的依賴文件。 Makefile 的基本結(jié)構(gòu)(的基本結(jié)構(gòu)(2/2) Makefile規(guī)則的一般形式如下: target:dependency dependency

28、(tab) 一個(gè)Makefile文件主要含有一系列的規(guī)則,每條規(guī)則包含以下內(nèi)容。 一個(gè)目標(biāo)(target),即make最終需要?jiǎng)?chuàng)建的文件,如可執(zhí)行文件和目標(biāo) 文件;目標(biāo)也可以是要執(zhí)行的動(dòng)作,如“clean”。 一個(gè)或多個(gè)依賴文件(dependency)列表,通常是編譯目標(biāo)文件所需要的 其他文件。 一系列命今(command),是make執(zhí)行的動(dòng)作,通常是把指定的相關(guān)文件編 譯成目標(biāo)文件的編譯命令,每個(gè)命令占一行,且每個(gè)命令行的起始字符必 須為TAB字符。 除非特別指定,否則make的工作目錄就是當(dāng)前目錄。target是需要?jiǎng)?chuàng)建的二進(jìn) 制文件或目標(biāo)文件,dependency是在創(chuàng)建target時(shí)

29、需要用到的一個(gè)或多個(gè)文件 的列表,命令序列是創(chuàng)建target文件所需要執(zhí)行的步驟,比如編譯命令。 Makefile實(shí)例(實(shí)例(1/3) # 以#開頭的為注釋行 test:prog.o code.o gcc o test prog.o code.o prog.o:prog.c prog.h code.h gcc c prog.c o prog.o code.o:code.c code.h gcc c code.c o code.o clean: rm f *.o 上面的Makefile文件中共定義了四個(gè)目標(biāo):test、prog.o、code.o 和clean。 目標(biāo)從每行的最左邊開始寫,后面跟一

30、個(gè)冒號(:),如果有與 這個(gè)目標(biāo)有依賴性的其他目標(biāo)或文件,把它們列在冒號后面,并 以空格隔開。然后另起一行開始寫實(shí)現(xiàn)這個(gè)目標(biāo)的一組命令。 在Makefile中,可使用續(xù)行號()將一個(gè)單獨(dú)的命令行延續(xù)成幾 行。但要注意在續(xù)行號()后面不能跟任何字符(包括空格和鍵) Makefile實(shí)例(實(shí)例(2/3) 一般情況下,調(diào)用make命令可輸入: # make target target是Makefile文件中定義的目標(biāo)之一,如果省略target, make就將生成Makefile文件中定義的第一個(gè)目標(biāo)。 對于上面Makefile的例子,單獨(dú)的一個(gè)“make”命令等價(jià)于: # make test 因?yàn)閠

31、est是Makefile文件中定義的第一個(gè)目標(biāo),make首先將其 讀入,然后從第一行開始執(zhí)行,把第一個(gè)目標(biāo)test作為它的最 終目標(biāo),所有后面的目標(biāo)的更新都會(huì)影響到test的更新。 第一條規(guī)則說明只要文件test的時(shí)間戳比文件prog.o或code.o中 的任何一個(gè)舊,下一行的編譯命令將會(huì)被執(zhí)行。 Makefile實(shí)例(實(shí)例(3/3) 但是,在檢查文件prog.o和code.o的時(shí)間戳之前,make會(huì)在下面 的行中尋找以prog.o和code.o為目標(biāo)的規(guī)則,在第三行中找到了 關(guān)于prog.o的規(guī)則,該文件的依賴文件是prog.c、prog.h和 code.h。同樣,make會(huì)在后面的規(guī)則行中

32、繼續(xù)查找這些依賴文 件的規(guī)則,如果找不到,則開始檢查這些依賴文件的時(shí)間戳,如 果這些文件中任何一個(gè)的時(shí)間戳比prog.o的新,make將執(zhí)行 “gcc c prog.c o prog.o”命令,更新prog.o文件。 以同樣的方法,接下來對文件code.o做類似的檢查,依賴文件是 code.c和code.h。當(dāng)make執(zhí)行完所有這些套嵌的規(guī)則后,make 將處理最頂層的test規(guī)則。如果關(guān)于prog.o和code.o的兩個(gè)規(guī)則 中的任何一個(gè)被執(zhí)行,至少其中一個(gè).o目標(biāo)文件就會(huì)比test新, 那么就要執(zhí)行test規(guī)則中的命令,因此make去執(zhí)行g(shù)cc命令將 prog.o和code.o連接成目標(biāo)文

33、件test。 在上面Makefile的例子中,還定義了一個(gè)目標(biāo)clean,它是 Makefile中常用的一種專用目標(biāo),即刪除所有的目標(biāo)模塊 make的工作過程的工作過程 現(xiàn)在來看一下make做的工作: 首先make按順序讀取makefile中的規(guī)則, 然后檢查該規(guī)則中的依賴文件與目標(biāo)文件的時(shí)間戳哪個(gè)更新 如果目標(biāo)文件的時(shí)問戳比依賴文件還早,就按規(guī)則中定義的命令更新目 標(biāo)文件。 如果該規(guī)則中的依賴文件又是其他規(guī)則中的目標(biāo)文件,那么依照規(guī)則鏈 不斷執(zhí)行這個(gè)過程,直到Makefile文件的結(jié)束,至少可以找到一個(gè)不是規(guī) 則生成的最終依賴文件,獲得此文件的時(shí)間戳 然后從下到上依照規(guī)則鏈執(zhí)行目標(biāo)文件的時(shí)間

34、戳比此文件時(shí)間戳舊的規(guī) 則,直到最頂層的規(guī)則 通過以上的分析過程,可以看到make的優(yōu)點(diǎn),因?yàn)?o目標(biāo)文件依賴.c源文件, 源碼文件里一個(gè)簡單改變都會(huì)造成那個(gè)文件被重新編譯,并根據(jù)規(guī)則鏈依次由 下到上執(zhí)行編譯過程,直到最終的可執(zhí)行文件被重新連接。 例如,當(dāng)改變一個(gè)頭文件的時(shí)候,由于所有的依賴關(guān)系都在Makefile里,因 此不再需要記住依賴此頭文件的所有源碼文件,make可以自動(dòng)的重新編譯 所有那些因依賴這個(gè)頭文件而改變了的源碼文件,如果需要,再進(jìn)行重新 連接 Makefile中的變量中的變量 Makefile里的變量就像一個(gè)環(huán)境變量。事實(shí)上,環(huán)境變量在make中也被解釋 成make的變量。這

35、些變量對大小寫敏感,一般使用大寫宇母。幾乎可以從任 何地方引用定義的變量,變量的主要作用如下: 保存文件名列表。在前面的例子里,作為依賴文件的一些目標(biāo)文件名出現(xiàn) 在可執(zhí)行文件的規(guī)則中,而在這個(gè)規(guī)則的命令行里同樣包含這些文件并傳 遞給gcc做為命令參數(shù)。如果使用一個(gè)變量來保存所有的目標(biāo)文件名,則可 以方便地加入新的目標(biāo)文件而且不易出錯(cuò)。 保存可執(zhí)行命令名,如編譯器。在不同的Linux系統(tǒng)中存在著很多相似的編 譯器系統(tǒng),這些系統(tǒng)在某些地方會(huì)有細(xì)微的差別,如果項(xiàng)目被用在一個(gè)非 gcc的系統(tǒng)里,則必須將所有出現(xiàn)編譯器名的地方改成用新的編譯器名。但 是如果使用一個(gè)變量來代替編譯器名,那么只需要改變該變量

36、的值。其他 所有地方的命令名就都改變了。 保存編譯器的參數(shù)。在很多源代碼編譯時(shí),gcc需要很長的參數(shù)選項(xiàng),在很 多情況下,所有的編譯命令使用一組相同的選項(xiàng),如果把這組選項(xiàng)使用一 個(gè)變量代表,那么可以把這個(gè)變量放在所有引用編譯器的地方。當(dāng)要改變 選項(xiàng)的時(shí)候,只需改變一次這個(gè)變量的內(nèi)容即可。 變量的定義和使用變量的定義和使用 Makefile中的變量是用一個(gè)文本串在Makefile中定義的,這個(gè)文 本串就是變量的值。只要在一行的開始寫下這個(gè)變量的名字,后 面跟一個(gè)“”號,以及要設(shè)定這個(gè)變量的值即可定義變量,下 面是定義變量的語法: VARNAME=string 使用時(shí),把變量用括號括起來,并在前面

37、加上$符號,就可以引 用變量的值: $VARNAME make解釋規(guī)則時(shí),VARNAME在等式右端展開為定義它的字符串。 變量一般都在Makefile的頭部定義。按照慣例,所有的Makefile 變量都應(yīng)該是大寫。如果變量的值發(fā)生變化,就只需要在一個(gè)地 方修改,從而簡化了Makefile的維護(hù)。 Makefile變量舉例變量舉例 現(xiàn)在利用變量把前面的Makefile重寫一遍: OBJS=prog.o code.o CC=gcc test:$ OBJS $ CC o test $ OBJS prog.o:prog.c prog.h code.h $ CC c prog.c o prog.o co

38、de.o:code.c code.h $ CC c code.c o code.o clean: rm f *.o 變量的類型變量的類型 除用戶自定義的變量外,make還允許使用 環(huán)境變量 使用環(huán)境變量的方法很簡單,在make啟動(dòng)時(shí),make讀取系統(tǒng)當(dāng)前已定 義的環(huán)境變量,并且創(chuàng)建與之同名同值的變量,因此用戶可以像在shell 中一樣在Makefile中方便的引用環(huán)境變量。 需要注意的是,如果用戶在Makefile中定義了同名的變量,用戶自定義變 量將覆蓋同名的環(huán)境變量 自動(dòng)變量 預(yù)定義變量 GNU make 的主要預(yù)定義變量(的主要預(yù)定義變量(1/2) $* 不包含擴(kuò)展名的目標(biāo)文件名稱。 $

39、+ 所有的依賴文件,以空格分開,并以出現(xiàn)的先后為序,可能包含重復(fù)的依賴文 件。 $ 第一個(gè)依賴文件的名稱。 $? 所有的依賴文件,以空格分開,這些依賴文件的修改日期比目標(biāo)的創(chuàng)建日期晚。 $ 目標(biāo)的完整名稱。 $ 所有的依賴文件,以空格分開,不包含重復(fù)的依賴文件。 $% 如果目標(biāo)是歸檔成員,則該變量表示目標(biāo)的歸檔成員名稱。例如,如果目標(biāo)名 稱 為 mytarget.so(image.o),則 $ 為 mytarget.so,而 $% 為 image.o。 AR 歸檔維護(hù)程序的名稱,默認(rèn)值為 ar。 ARFLAGS 歸檔維護(hù)程序的選項(xiàng)。 AS 匯編程序的名稱,默認(rèn)值為 as。 ASFLAGS 匯編

40、程序的選項(xiàng)。 GNU make 的主要預(yù)定義變量(的主要預(yù)定義變量(2/2) CC C 編譯器的名稱,默認(rèn)值為 cc。 CFLAGS C 編譯器的選項(xiàng)。 CPP C 預(yù)編譯器的名稱,默認(rèn)值為 $(CC) -E。 CPPFLAGS C 預(yù)編譯的選項(xiàng)。 CXX C+ 編譯器的名稱,默 認(rèn)值為 g+。 CXXFLAGS C+ 編譯器的選項(xiàng)。 FC FORTRAN 編譯器的名稱,默認(rèn)值為 f77。 FFLAGS FORTRAN 編譯器的選項(xiàng)。 Makefile的隱含規(guī)則的隱含規(guī)則 在上面的例子中,幾個(gè)產(chǎn)生目標(biāo)文件的命令都是從“.c”的C語言源文件和相關(guān) 文件通過編譯產(chǎn)生“.o”目標(biāo)文件,這也是一般的步

41、驟。實(shí)際上,make可以使 工作更加自動(dòng)化,也就是說,make知道一些默認(rèn)的動(dòng)作,它有一些稱作隱含 規(guī)則的內(nèi)置的規(guī)則,這些規(guī)則告訴make當(dāng)用戶沒有完整地給出某些命令的時(shí) 候,應(yīng)該怎樣執(zhí)行。 例如,把生成prog.o和code.o的命令從規(guī)則中刪除,make將會(huì)查找隱含規(guī)則, 然后會(huì)找到并執(zhí)行一個(gè)適當(dāng)?shù)拿?。由于這些命令會(huì)使用一些變量,因此可以 通過改變這些變量來定制make。象在前面的例子中所定義的那樣,make使用 變量CC來定義編譯器,并且傳遞變量CFLAGS(編譯器參數(shù))、CPPFLAGS (C語言預(yù)處理器參數(shù))、TARGET_ARCH(目標(biāo)機(jī)器的結(jié)構(gòu)定義)給編譯 器,然后加上參數(shù)-c

42、,后面跟變量$(第一個(gè)依賴文件名),然后是參數(shù)-o加 變量$(目標(biāo)文件名)。 綜上所述,一個(gè)C編譯的具體命令將會(huì)是: $ CC $ CFLAGS $ CPPFLAGS $ TARGET_ARCH c $ -o $ 隱含規(guī)則舉例隱含規(guī)則舉例 在上面的例子中,利用隱含規(guī)則,可以簡化為: OBJS=prog.o code.o CC=gcc test:$ OBJS $ CC o $ $ prog.o:prog.c prog.h code.h code.o:code.c code.h clean: rm f *.o make命令行選項(xiàng)命令行選項(xiàng) 直接在 make 命令的后面鍵入目標(biāo)名可建立指定的目標(biāo),如果直接運(yùn)行 make, 則建立第一個(gè)目標(biāo)。還可以用 make -f mymakefile 這樣的命令指定 make 使用 特定的 makefile,而不是 默認(rèn)的 GNUmakefile、makefile 或 Makefile。 GNU make 命令還有一些其他選項(xiàng),下面是 GNU make 命令的常用命令行選 項(xiàng)命令行選項(xiàng)含義

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論