版權說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權,請進行舉報或認領
文檔簡介
1、 跟我一起寫 Makefile作者:陳皓跟我一起寫Makefile作者:陳皓 整理:祝冬華第 1 頁共 78 頁2005 年 10 月 14 日整理:祝冬華 跟我一起寫 Makefile作者:陳皓第一部分、概述6第二部分、關于程序的編譯和鏈接6第三部分、Makefile 介紹7一、Makefile的規(guī)則7二、一個示例8三、make是如何工作的9四、makefile中使用變量10五、讓make自動推導11六、另類風格的makefile12七、清空目標文件的規(guī)則13第四部分、Makefile 總述13一、Makefile里有什么?131、顯式規(guī)則。142、隱晦規(guī)則。143、變量的定義。144、文件
2、指示。145、注釋。14二、Makefile的文件名15三、引用其它的Makefile15四、環(huán)境變量 MAKEFILES16五、make的工作方式16第五部分、書寫規(guī)則17一、規(guī)則舉例17二、規(guī)則的語法17三、在規(guī)則中使用通配符18四、文件搜尋19五、偽目標20六、多目標22七、靜態(tài)模式22八、自動生成依賴性24第六部分 書寫命令25一、顯示命令26二、命令執(zhí)行26三、命令出錯27四、嵌套執(zhí)行make28五、定義命令包30第七部分 使用變量30一、變量的基礎31二、變量中的變量32三、變量高級用法34四、追加變量值37五、override 指示符37六、多行變量38第 2 頁共 78 頁20
3、05 年 10 月 14 日整理:祝冬華 跟我一起寫 Makefile作者:陳皓七、環(huán)境變量38八、目標變量39九、模式變量40第八部分 使用條件判斷40一、示例40二、語法42第九部分 使用函數(shù)43一、函數(shù)的調(diào)用語法44二、字符串處理函數(shù)441、subst442、patsubst453、strip454、findstring465、filter466、filter-out467、sort478、word479、wordlist4710、words4711、firstword4812、字符串函數(shù)實例48三、文件名操作函數(shù)481、dir482、notdir483、suffix494、basena
4、me495、addsuffix496、addprefix497、join50四、foreach 函數(shù)50五、if 函數(shù)50六、call函數(shù)51七、origin函數(shù)51“undefined”52“default”52“file”52“command line”52“override”52“automatic”52八、shell函數(shù)53九、控制make的函數(shù)531、error532、warning54第十部分 make 的運行54第 3 頁共 78 頁2005 年 10 月 14 日整理:祝冬華 跟我一起寫 Makefile作者:陳皓一、make的退出碼54二、指定Makefile54三、指定目標
5、55“all”56“clean”56“install”56“print”56“tar”56“dist”56“TAGS”56五、make的參數(shù)57第十一部分 隱含規(guī)則61一、使用隱含規(guī)則61二、隱含規(guī)則一覽621、編譯C程序的隱含規(guī)則632、編譯C+程序的隱含規(guī)則633、編譯Pascal程序的隱含規(guī)則634、編譯Fortran/Ratfor程序的隱含規(guī)則635、預處理Fortran/Ratfor程序的隱含規(guī)則636、編譯Modula-2 程序的隱含規(guī)則637、匯編和匯編預處理的隱含規(guī)則648、鏈接Object文件的隱含規(guī)則649、Yacc C程序時的隱含規(guī)則6410、Lex C程序時的隱含規(guī)則6
6、411、Lex Ratfor程序時的隱含規(guī)則6512、從C程序、Yacc文件或Lex文件創(chuàng)建Lint庫的隱含規(guī)則65三、隱含規(guī)則使用的變量651、關于命令的變量。65五、定義模式規(guī)則681、模式規(guī)則介紹682、模式規(guī)則示例693、自動化變量704、模式的匹配725、重載內(nèi)建隱含規(guī)則72六、老式風格的后綴規(guī)則73七、隱含規(guī)則搜索算法74第十二部分 使用make更新函數(shù)庫文件75一、函數(shù)庫文件的成員75二、函數(shù)庫成員的隱含規(guī)則75三、函數(shù)庫文件的后綴規(guī)則76第 4 頁共 78 頁2005 年 10 月 14 日整理:祝冬華 跟我一起寫 Makefile作者:陳皓四、注意事項76第十三部分后序77第
7、 5 頁共 78 頁2005 年 10 月 14 日整理:祝冬華 跟我一起寫 Makefile作者:陳皓第一部分、概述什么是 makefile?或許很多 Winodws 的程序員都不知道這個東西,因為那些 Windows 的 IDE 都為你做了這個工作,但我覺得要作一個好的和 professional 的程序員,makefile 還是要懂。這就好像現(xiàn)在有這么多的 HTML 的編輯器,但如果你想成為一個專業(yè),你還是要了解 HTML 的標識的含義。特別在 Unix 下的軟件編譯,你就不能不自己寫 makefile 了, 會不會寫 makefile,從一個側(cè)面說明了一個人是否具備完成大型工程的能力。
8、 因為, makefile 關系到了整個工程的編譯規(guī)則。一個工程中的源文件不計數(shù),其按類型、功能、模塊分別放在若干個目錄中,makefile 定義了一系列的規(guī)則來指定,哪些文件需要先編譯, 哪些文件需要后編譯,哪些文件需要重新編譯,甚至于進行更復雜的功能操作,因為makefile 就像一個 Shell 腳本一樣,其中也可以執(zhí)行操作系統(tǒng)的命令。 makefile 帶來的好處就是“自動化編譯”,一旦寫好,只需要一個 make 命令,整個工程完全自動編譯, 極大的提高了軟件開發(fā)的效率。make 是一個命令工具,是一個解釋 makefile 中指令的命令工具, 一般來說,大多數(shù)的 IDE 都有這個命令
9、,比如:Delphi 的 make,Visual C+的 nmake, Linux 下GNU 的 make??梢姡琺akefile 都成為了一種在工程方面的編譯方法。 現(xiàn)在講述如何寫 makefile 的文章比較少,這是我想寫這篇文章的原因。當然,不同產(chǎn)商的 make 各不相同,也有不同的語法,但其本質(zhì)都是在“文件依賴性”上做文章,這里, 我僅對 GNU 的 make 進行講述,我的環(huán)境是 RedHat Linux 8.0,make 的版本是 3.80。必竟, 這個make 是應用最為廣泛的,也是用得最多的。而且其還是最遵循于 IEEE 1003.2-1992 標 準的(POSIX.2)。 在
10、這篇文檔中,將以 C/C+的源碼作為我們基礎,所以必然涉及一些關于 C/C+的編譯的知識,相關于這方面的內(nèi)容,還請各位查看相關的編譯器的文檔。這里所默認的編譯器是UNIX 下的 GCC 和CC。 第二部分、關于程序的編譯和鏈接在此,我想多說關于程序編譯的一些規(guī)范和方法,一般來說,無論是 C、C+、還是 pas, 首先要把源文件編譯成中間代碼文件,在 Windows 下也就是 .obj 文件,UNIX 下是 .o 文件,即 Object File,這個動作叫做編譯(compile)。然后再把大量的 Object File 合成執(zhí)行文件,這個動作叫作鏈接(link)。 編譯時,編譯器需要的是語法的
11、正確,函數(shù)與變量的聲明的正確。對于后者,通常是你需要告訴編譯器頭文件的所在位置(頭文件中應該只是聲明, 而定義應該放在 C/C+文件中),只要所有的語法正確,編譯器就可以編譯出中間目標文 件。一般來說,每個源文件都應該對應于一個中間目標文件(O 文件或是 OBJ 文件)。鏈接時,主要是鏈接函數(shù)和全局變量,所以,我們可以使用這些中間目標文件(O 文件或是OBJ 文件)來鏈接我們的應用程序。鏈接器并不管函數(shù)所在的源文件,只管函數(shù)的中間目標文件 (Object File),在大多數(shù)時候,由于源文件太多,編譯生成的中間目標文件太多,而在鏈 第 6 頁共 78 頁2005 年 10 月 14 日整理:祝
12、冬華 跟我一起寫 Makefile作者:陳皓接時需要明顯地指出中間目標文件名,這對于編譯很不方便,所以,我們要給中間目標文件打個包,在 Windows 下這種包叫“庫文件”(Library File),也就是 .lib 文件,在 UNIX 下,是 Archive File,也就是 .a 文件。 總結(jié)一下,源文件首先會生成中間目標文件,再由中間目標文件生成執(zhí)行文件。在編譯時,編譯器只檢測程序語法,和函數(shù)、變量是否被聲明。如果函數(shù)未被聲明,編譯器會給出一個警告,但可以生成 Object File。而在鏈接程序時,鏈接器會在所有的 Object File 中找尋函數(shù)的實現(xiàn),如果找不到,那到就會報鏈接
13、錯誤碼(Linker Error),在 VC 下,這種錯誤一般是:Link 2001 錯誤,意思說是說,鏈接器未能找到函數(shù)的實現(xiàn)。你需要指定函數(shù)的 Object File. 好,言歸正傳,GNU 的make 有許多的內(nèi)容,閑言少敘,還是讓我們開始吧。 第三部分、Makefile介紹make 命令執(zhí)行時,需要一個 Makefile 文件,以告訴 make 命令需要怎么樣的去編譯和 鏈接程序。 首先,我們用一個示例來說明 Makefile 的書寫規(guī)則。以便給大家一個感興認識。這個示例來源于 GNU 的 make 使用手冊,在這個示例中,我們的工程有 8 個 C 文件,和 3 個頭文件, 我們要寫一
14、個 Makefile 來告訴 make 命令如何編譯和鏈接這幾個文件。我們的規(guī)則是: 1) 如果這個工程沒有編譯過,那么我們的所有 C 文件都要編譯并被鏈接。 2) 如果這個工程的某幾個 C 文件被修改,那么我們只編譯被修改的 C 文件,并鏈接目標程。 3) 如果這個工程的頭文件被改變了,那么我們需要編譯引用了這幾個頭文件的 C 文件, 并鏈接目標程序。 只要我們的 Makefile 寫得夠好,所有的這一切,我們只用一個 make 命令就可以完成, make 命令會自動智能地根據(jù)當前的文件修改的情況來確定哪些文件需要重編譯,從而自己編譯所需要的文件和鏈接目標程序。 一、Makefile 的規(guī)則
15、在講述這個 Makefile 之前,還是讓我們先來粗略地看一看 Makefile 的規(guī)則。 target . : prerequisites .command 第 7 頁共 78 頁2005 年 10 月 14 日整理:祝冬華 跟我一起寫 Makefile作者:陳皓.target 也就是一個目標文件,可以是 Object File,也可以是執(zhí)行文件。還可以是一個標簽(Label),對于標簽這種特性,在后續(xù)的“偽目標”章節(jié)中會有敘述。 prerequisites 就是,要生成那個 target 所需要的文件或是目標。 command 也就是 make 需要執(zhí)行的命令。(任意的 Shell 命令)
16、 這是一個文件的依賴關系, 也就是說, target 這一個或多個的目標文件依賴于prerequisites 中的文件,其生成規(guī)則定義在 command 中。說白一點就是說,prerequisites 中如果有一個以上的文件比 target 文件要新的話,command 所定義的命令就會被執(zhí)行。這 就是 Makefile 的規(guī)則。也就是 Makefile 中最核心的內(nèi)容。 說到底,Makefile 的東西就是這樣一點,好像我的這篇文檔也該結(jié)束了。呵呵。還不盡然,這是 Makefile 的主線和核心,但要寫好一個 Makefile 還不夠,我會以后面一點一點地結(jié)合我的工作經(jīng)驗給你慢慢到來。內(nèi)容還
17、多著呢。:) 二、一個示例正如前面所說的,如果一個工程有 3 個頭文件,和 8 個C 文件,我們?yōu)榱送瓿汕懊嫠?的那三個規(guī)則,我們的 Makefile 應該是下面的這個樣子的。 edit : main.o kbd.o command.o display.o insert.o search.o files.o utils.o kbd.o command.o display.ofiles.o utils.o cc -o edit main.oinsert.o search.omain.o : main.c defs.hcc -c kbd.occ -cmain.c : kbd.c defs.h c
18、ommand.hkbd.c command.o : command.c defs.h command.h cc -c command.c display.o : display.c defs.h buffer.h cc -c display.c insert.o : insert.c defs.h buffer.h cc -c insert.c search.o : search.c defs.h buffer.h cc -c search.c files.o : files.c defs.h buffer.h command.hcc -c files.c 第 8 頁共 78 頁2005 年
19、10 月 14 日整理:祝冬華 跟我一起寫 Makefile作者:陳皓utils.o : utils.c defs.h cc -c utils.c clean : rm edit main.o kbd.o command.o display.o insert.o search.o files.o utils.o 反斜杠()是換行符的意思。這樣比較便于 Makefile 的易讀。我們可以把這個內(nèi)容保存在文件為“Makefile”或“makefile”的文件中,然后在該目錄下直接輸入命令“make” 就可以生成執(zhí)行文件 edit。如果要刪除執(zhí)行文件和所有的中間目標文件,那么,只要簡單 地執(zhí)行一下“
20、make clean”就可以了。 在這個 makefile 中,目標文件(target)包含:執(zhí)行文件 edit 和中間目標文件(*.o),依賴文件(prerequisites)就是冒號后面的那些 .c 文件和 .h 文件。每一個 .o 文件都有一組依賴文件,而這些 .o 文件又是執(zhí)行文件 edit 的依賴文件。依賴關系的實質(zhì)上就是 說明了目標文件是由哪些文件生成的,換言之,目標文件是哪些文件更新的。 在定義好依賴關系后,后續(xù)的那一行定義了如何生成目標文件的操作系統(tǒng)命令,一定要以一個 Tab 鍵作為開頭。記住,make 并不管命令是怎么工作的,他只管執(zhí)行所定義的命令。make 會比較 targ
21、ets 文件和 prerequisites 文件的修改日期,如果 prerequisites 文件的日期要比 targets 文件的日期要新,或者 target 不存在的話,那么,make 就會執(zhí)行后續(xù)定 義的命令。 這里要說明一點的是,clean 不是一個文件,它只不過是一個動作名字,有點像 C 語言中的 lable 一樣,其冒號后什么也沒有,那么,make 就不會自動去找文件的依賴性,也就不會自動執(zhí)行其后所定義的命令。要執(zhí)行其后的命令,就要在 make 命令后明顯得指出這個lable 的名字。這樣的方法非常有用,我們可以在一個 makefile 中定義不用的編譯或是和 編譯無關的命令,比如
22、程序的打包,程序的備份,等等。 三、make 是如何工作的在默認的方式下,也就是我們只輸入 make 命令。那么, 1、make 會在當前目錄下找名字叫“Makefile”或“makefile”的文件。 2、如果找到,它會找文件中的第一個目標文件(target),在上面的例子中,他會找到 “edit”這個文件,并把這個文件作為最終的目標文件。 3、如果 edit 文件不存在,或是 edit 所依賴的后面的 .o 文件的文件修改時間要比edit 這個文件新,那么,他就會執(zhí)行后面所定義的命令來生成 edit 這個文件。 4、如果 edit 所依賴的.o 文件也存在,那么 make 會在當前文件中找
23、目標為.o 文件的依賴性,如果找到則再根據(jù)那一個規(guī)則生成.o 文件。(這有點像一個堆棧的過程) 5、當然,你的 C 文件和H 文件是存在的啦,于是 make 會生成 .o 文件,然后再用 .o 文 件生命 make 的終極任務,也就是執(zhí)行文件 edit 了。 這就是整個 make 的依賴性,make 會一層又一層地去找文件的依賴關系,直到最終編譯 第 9 頁共 78 頁2005 年 10 月 14 日整理:祝冬華 跟我一起寫 Makefile作者:陳皓出第一個目標文件。在找尋的過程中,如果出現(xiàn)錯誤,比如最后被依賴的文件找不到,那么make 就會直接退出,并報錯,而對于所定義的命令的錯誤,或是編
24、譯不成功,make 根本不理。make 只管文件的依賴性,即,如果在我找了依賴關系之后,冒號后面的文件還是不在, 那么對不起,我就不工作啦。 通過上述分析,我們知道,像 clean 這種,沒有被第一個目標文件直接或間接關聯(lián),那么它后面所定義的命令將不會被自動執(zhí)行,不過,我們可以顯示要 make 執(zhí)行。即命令 “make clean”,以此來清除所有的目標文件,以便重編譯。 于是在我們編程中,如果這個工程已被編譯過了,當我們修改了其中一個源文件,比如file.c,那么根據(jù)我們的依賴性,我們的目標 file.o 會被重編譯(也就是在這個依性關系后面所定義的命令),于是 file.o 的文件也是最新
25、的啦,于是 file.o 的文件修改時間要比 edit 要新,所以 edit 也會被重新鏈接了(詳見 edit 目標文件后定義的命令)。 而如果我們改變了“command.h”,那么,kdb.o、command.o 和files.o 都會被重編譯,并且,edit 會被重鏈接。 四、makefile 中使用變量在上面的例子中,先讓我們看看 edit 的規(guī)則:edit : main.o kbd.o command.o display.o insert.o search.o cc -o edit main.oinsert.o search.ofiles.o utils.o kbd.o command
26、.o display.o files.o utils.o 我們可以看到.o文件的字符串被重復了兩次,如果我們的工程需要加入一個新的.o 文件,那么我們需要在兩個地方加(應該是三個地方,還有一個地方在 clean 中)。當然, 我們的 makefile 并不復雜,所以在兩個地方加也不累,但如果 makefile 變得復雜,那么我們就有可能會忘掉一個需要加入的地方,而導致編譯失敗。所以,為了 makefile 的易維護, 在makefile 中我們可以使用變量。makefile 的變量也就是一個字符串,理解成 C 語言中的 宏可能會更好。 比如,我們聲明一個變量,叫 objects, OBJECT
27、S, objs, OBJS, obj, 或是 OBJ,反正不管什么啦,只要能夠表示 obj 文件就行了。我們在 makefile 一開始就這樣定義: objects = main.o kbd.o command.o display.o insert.o search.o files.o utils.o 于是,我們就可以很方便地在我們的 makefile 中以“$(objects)”的方式來使用這個變量了,于是我們的改良版 makefile 就變成下面這個樣子: 第 10 頁共 78 頁2005 年 10 月 14 日整理:祝冬華 跟我一起寫 Makefile作者:陳皓objects = mai
28、n.o kbd.o command.o display.o insert.o search.o files.o utils.o edit : $(objects) cc -o edit $(objects) main.o : main.c defs.hcc -c main.c kbd.occ -c: kbd.c defs.h command.hkbd.c command.o : command.c defs.h command.h cc -c command.c display.o : display.c defs.h buffer.h cc -c display.c insert.o : i
29、nsert.c defs.h buffer.h cc -c insert.c search.o : search.c defs.h buffer.h cc -c search.c files.o : files.c defs.h buffer.h command.h cc -c files.c utils.o : utils.c defs.h cc -c utils.c clean : rm edit $(objects) 于是如果有新的 .o 文件加入,我們只需簡單地修改一下objects 變量就可以了。關于變量更多的話題,我會在后續(xù)給你一一道來。五、讓 make 自動推導GNU 的 mak
30、e 很強大,它可以自動推導文件以及文件依賴關系后面的命令,于是我們就沒必要去在每一個.o文件后都寫上類似的命令,因為,我們的 make 會自動識別,并自己推導命令。 只要 make 看到一個.o文件,它就會自動的把.c文件加在依賴關系中,如果 make 找到一個 whatever.o,那么 whatever.c,就會是 whatever.o 的依賴文件。并且 cc -c whatever.c 也會被推導出來,于是,我們的 makefile 再也不用寫得這么復雜。我們的是新 的 makefile 又出爐了。 第 11 頁共 78 頁2005 年 10 月 14 日整理:祝冬華 跟我一起寫 Mak
31、efile作者:陳皓objects = main.o kbd.o command.o display.oinsert.o search.o files.o utils.o edit : $(objects) cc -o edit $(objects)main.o : defs.h kbd.o : defs.h command.h command.o : defs.h command.h display.o : defs.h buffer.h insert.o : defs.h buffer.h search.o : defs.h buffer.h files.o : defs.h buffer
32、.h command.hutils.o : defs.h .PHONY : clean clean : rm edit $(objects)這種方法,也就是 make 的“隱晦規(guī)則”。上面文件內(nèi)容中,“.PHONY”表示,clean是個偽目標文件。 關于更為詳細的“隱晦規(guī)則”和“偽目標文件”,我會在后續(xù)給你一一道來。六、另類風格的 makefile即然我們的 make 可以自動推導命令,那么我看到那堆.o和.h的依賴就有點不爽, 那么多的重復的.h,能不能把其收攏起來,好吧,沒有問題,這個對于 make 來說很容易, 誰叫它提供了自動推導命令和文件的功能呢?來看看最新風格的 makefile
33、吧。 objects = main.o kbd.o command.o display.o insert.o search.o files.o utils.o edit : $(objects) cc -o edit $(objects)$(objects) : defs.h kbd.o command.o files.o : command.h display.o insert.o search.o files.o : buffer.h.PHONY : clean clean : rm edit $(objects)第 12 頁共 78 頁2005 年 10 月 14 日整理:祝冬華 跟我一
34、起寫 Makefile作者:陳皓這種風格,讓我們的 makefile 變得很簡單,但我們的文件依賴關系就顯得有點凌亂了。魚和熊掌不可兼得。還看你的喜好了。我是不喜歡這種風格的,一是文件的依賴關系看不清 楚,二是如果文件一多,要加入幾個新的.o 文件,那就理不清楚了。 七、清空目標文件的規(guī)則每個 Makefile 中都應該寫一個清空目標文件(.o 和執(zhí)行文件)的規(guī)則,這不僅便于重編譯,也很利于保持文件的清潔。這是一個“修養(yǎng)”(呵呵,還記得我的編程修養(yǎng)嗎)。一般的風格都是: clean: rm edit $(objects)更為穩(wěn)健的做法是:.PHONY : clean clean : -rm e
35、dit $(objects)前面說過,.PHONY 意思表示 clean 是一個“偽目標”,。而在 rm 命令前面加了一個小減號的意思就是,也許某些文件出現(xiàn)問題,但不要管,繼續(xù)做后面的事。當然,clean 的規(guī)則不要放在文件的開頭,不然,這就會變成 make 的默認目標,相信誰也不愿意這樣。不成 文的規(guī)矩是“clean 從來都是放在文件的最后”。 上面就是一個 makefile 的概貌,也是 makefile 的基礎,下面還有很多 makefile 的相 關細節(jié),準備好了嗎?準備好了就來。 第四部分、Makefile總述一、Makefile 里有什么?第 13 頁共 78 頁2005 年 10
36、 月 14 日整理:祝冬華 跟我一起寫 Makefile作者:陳皓Makefile 里主要包含了五個東西:顯式規(guī)則、隱晦規(guī)則、變量定義、文件指示和注釋。 1、顯式規(guī)則。顯式規(guī)則說明了,如何生成一個或多的的目標文件。這是由 Makefile 的書寫者明顯指出,要生成的文件,文件的依賴文件,生成的命令。 2、隱晦規(guī)則。由于我們的 make 有自動推導的功能,所以隱晦的規(guī)則可以讓我們比較粗糙地簡略地書 寫 Makefile,這是由 make 所支持的。 3、變量的定義。在 Makefile 中我們要定義一系列的變量,變量一般都是字符串,這個有點你 C 語言中 的宏,當 Makefile 被執(zhí)行時,其
37、中的變量都會被擴展到相應的引用位置上。 4、文件指示。其包括了三個部分,一個是在一個 Makefile 中引用另一個 Makefile,就像 C 語言中的include 一樣;另一個是指根據(jù)某些情況指定 Makefile 中的有效部分,就像 C 語言中的預編譯#if 一樣;還有就是定義一個多行的命令。有關這一部分的內(nèi)容,我會在后續(xù)的部分中 講述。 5、注釋。Makefile 中只有行注釋,和 UNIX 的 Shell 腳本一樣,其注釋是用“#”字符,這個就像 C/C+中的“/”一樣。如果你要在你的 Makefile 中使用“#”字符,可以用反斜框進行轉(zhuǎn)義,如:“#”。 最后,還值得一提的是,在
38、 Makefile 中的命令,必須要以Tab鍵開始。 第 14 頁共 78 頁2005 年 10 月 14 日整理:祝冬華 跟我一起寫 Makefile作者:陳皓二、Makefile 的文件名默認的情況下,make 命令會在當前目錄下按順序找尋文件名為“GNUmakefile”、“makefile”、“Makefile”的文件,找到了解釋這個文件。在這三個文件名中,最好使用“Makefile”這個文件名,因為,這個文件名第一個字符為大寫,這樣有一種顯目的感覺。最好不要用“GNUmakefile”,這個文件是 GNU 的 make 識別的。有另外一些 make 只對全小寫的“makefile”文
39、件名敏感,但是基本上來說,大多數(shù)的 make 都支持“makefile”和 “Makefile”這兩種默認文件名。 當然,你可以使用別的文件名來書寫 Makefile , 比如: “Make.Linux” , “Make.Solaris”,“Make.AIX”等,如果要指定特定的 Makefile,你可以使用 make 的“-f”和“-file”參數(shù),如:make -f Make.Linux 或 make -file Make.AIX。 三、引用其它的 Makefile在 Makefile 使用 include 關鍵字可以把別的 Makefile 包含進來,這很像 C 語言的#include,
40、被包含的文件會原模原樣的放在當前文件的包含位置。include 的語法是: include filename 可以是當前操作系統(tǒng) Shell 的文件模式(可以保含路徑和通配符)在 include 前面可以有一些空字符,但是絕不能是Tab鍵開始。include 和可以用一個或多個空格隔開。舉個例子,你有這樣幾個 Makefile:a.mk、b.mk、c.mk,還有一個文件叫 foo.make,以及一個變量$(bar),其包含了 e.mk 和f.mk,那么,下面的語句: include foo.make *.mk $(bar) 等價于: include foo.make a.mk b.mk c.m
41、k e.mk f.mkmake 命令開始時,會把找尋 include 所指出的其它 Makefile,并把其內(nèi)容安置在當前的位。就好像 C/C+的#include 指令一樣。如果文件都沒有指定絕對路徑或是相對路徑的話, make 會在當前目錄下首先尋找,如果當前目錄下沒有找到,那么,make 還會在下面的幾個 目錄下找: 1、如果 make 執(zhí)行時,有“-I”或“-include-dir”參數(shù),那么 make 就會在這個參數(shù)所指定的目錄下去尋找。 2、如果目錄/include(一般是:/usr/local/bin 或/usr/include)存在的話, make 也會去找。如果有文件沒有找到的
42、話,make 會生成一條警告信息,但不會馬上出現(xiàn)致命錯誤。它會繼續(xù)載入其它的文件,一旦完成 makefile 的讀取,make 會再重試這些沒有找到, 或是不能讀取的文件,如果還是不行,make 才會出現(xiàn)一條致命信息。如果你想讓 make 不理那些無法讀取的文件,而繼續(xù)執(zhí)行,你可以在 include 前加一個減號“-”。 第 15 頁共 78 頁2005 年 10 月 14 日整理:祝冬華 跟我一起寫 Makefile作者:陳皓如: -include 其表示,無論 include 過程中出現(xiàn)什么錯誤,都不要報錯繼續(xù)執(zhí)行。和其它版本 make 兼 容的相關命令是 sinclude,其作用和這一個
43、是一樣的。 四、環(huán)境變量 MAKEFILES如果你的當前環(huán)境中定義了環(huán)境變量 MAKEFILES,那么,make 會把這個變量中的值做一個類似于 include 的動作。這個變量中的值是其它的 Makefile,用空格分隔。只是,它和 include 不同的是,從這個環(huán)境變中引入的 Makefile 的“目標”不會起作用,如果環(huán)境變量中定義 的文件發(fā)現(xiàn)錯誤,make 也會不理。 但是在這里我還是建議不要使用這個環(huán)境變量,因為只要這個變量一被定義,那么當你使用 make 時,所有的 Makefile 都會受到它的影響,這絕不是你想看到的。在這里提這個事, 只是為了告訴大家,也許有時候你的 Mak
44、efile 出現(xiàn)了怪事,那么你可以看看當前環(huán)境中有 沒有定義這個變量。 五、make 的工作方式GNU 的make 工作時的執(zhí)行步驟入下:(想來其它的 make 也是類似) 1、讀入所有的 Makefile。2、讀入被 include 的其它 Makefile。3、初始化文件中的變量。 4、推導隱晦規(guī)則,并分析所有規(guī)則。 5、為所有的目標文件創(chuàng)建依賴關系鏈。 6、根據(jù)依賴關系,決定哪些目標要重新生成。7、執(zhí)行生成命令。 1-5 步為第一個階段,6-7 為第二個階段。第一個階段中,如果定義的變量被使用了,那么, make 會把其展開在使用的位置。但 make 并不會完全馬上展開,make 使用的
45、是拖延戰(zhàn)術,如果變量出現(xiàn)在依賴關系的規(guī)則中,那么僅當這條依賴被決定要使用了,變量才會在其內(nèi)部展 開。 當然,這個工作方式你不一定要清楚,但是知道這個方式你也會對 make 更為熟悉。有了這個基礎,后續(xù)部分也就容易看懂了。 第 16 頁共 78 頁2005 年 10 月 14 日整理:祝冬華 跟我一起寫 Makefile作者:陳皓第五部分、書寫規(guī)則規(guī)則包含兩個部分,一個是依賴關系,一個是生成目標的方法。 在 Makefile 中,規(guī)則的順序是很重要的,因為,Makefile 中只應該有一個最終目標, 其它的目標都是被這個目標所連帶出來的,所以一定要讓 make 知道你的最終目標是什么。一般來說,
46、定義在 Makefile 中的目標可能會有很多,但是第一條規(guī)則中的目標將被確立為最終的目標。如果第一條規(guī)則中的目標有很多個,那么,第一個目標會成為最終的目標。make 所完成的也就是這個目標。 好了,還是讓我們來看一看如何書寫規(guī)則。一、規(guī)則舉例foo.o : foo.c defs.h # foo 模塊cc -c -g foo.c 看到這個例子,各位應該不是很陌生了,前面也已說過,foo.o 是我們的目標,foo.c 和 defs.h 是目標所依賴的源文件,而只有一個命令“cc -c -g foo.c”(以 Tab 鍵開頭)。這個規(guī)則告訴我們兩件事: 1、文件的依賴關系,foo.o 依賴于 fo
47、o.c 和 defs.h 的文件,如果 foo.c 和 defs.h 的文件日期要比 foo.o 文件日期要新,或是 foo.o 不存在,那么依賴關系發(fā)生。 2、如果生成(或更新)foo.o 文件。也就是那個 cc 命令,其說明了,如何生成 foo.o 這個文件。(當然 foo.c 文件 include 了defs.h 文件) 二、規(guī)則的語法targets : prerequisites command . 或是這樣: targets : prerequisites ; command command . 第 17 頁共 78 頁2005 年 10 月 14 日整理:祝冬華 跟我一起寫 Mak
48、efile作者:陳皓targets 是文件名,以空格分開,可以使用通配符。一般來說,我們的目標基本上是一個文件,但也有可能是多個文件。 command 是命令行,如果其不與“target:prerequisites”在一行,那么,必須以Tab 鍵開頭,如果和 prerequisites 在一行,那么可以用分號做為分隔。(見上) prerequisites 也就是目標所依賴的文件(或依賴目標)。如果其中的某個文件要比目標文件要新,那么,目標就被認為是“過時的”,被認為是需要重生成的。這個在前面已經(jīng)講過了。 如果命令太長,你可以使用反斜框()作為換行符。make 對一行上有多少個字符 沒有限制。規(guī)
49、則告訴 make 兩件事,文件的依賴關系和如何成成目標文件。 一般來說,make 會以 UNIX 的標準 Shell,也就是/bin/sh 來執(zhí)行命令。 三、在規(guī)則中使用通配符如果我們想定義一系列比較類似的文件,我們很自然地就想起使用通配符。make 支持三各通配符:“*”,“?”和“.”。這是和 Unix 的B-Shell 是相同的。波浪號(“”) 字符在文件名中也有比較特殊的用途。如果是“/test”,這就表示當前用戶的$HOME 目錄下的 test 目錄。而“hchen/test”則表示用戶 hchen 的宿主目錄下的 test 目錄。(這些都是Unix 下的小知識了,make 也支持)
50、而在 Windows 或是 MS-DOS 下,用戶沒有宿主目錄, 那么波浪號所指的目錄則根據(jù)環(huán)境變量“HOME”而定。 通配符代替了你一系列的文件,如“*.c”表示所以后綴為 c 的文件。一個需要我們注意的是,如果我們的文件名中有通配符,如:“*”,那么可以用轉(zhuǎn)義字符“”,如“*” 來表示真實的“*”字符,而不是任意長度的字符串。 好吧,還是先來看幾個例子吧: clean: rm -f *.o 上面這個例子我不不多說了,這是操作系統(tǒng) Shell 所支持的通配符。這是在命令中的通配符。 print: *.c lpr -p $? touch print 上面這個例子說明了通配符也可以在我們的規(guī)則中
51、,目標 print 依賴于所有的.c文件。其中的“$?”是一個自動化變量,我會在后面給你講述。 objects = *.o 上面這個例子,表示了,通符同樣可以用在變量中。并不是說*.o會展開,不!objects的值就是“*.o”。Makefile 中的變量其實就是 C/C+中的宏。如果你要讓通配符在變量中展開,也就是讓 objects 的值是所有.o的文件名的集合,那么,你可以這樣: 第 18 頁共 78 頁2005 年 10 月 14 日整理:祝冬華 跟我一起寫 Makefile作者:陳皓objects := $(wildcard *.o)這種用法由關鍵字“wildcard”指出,關于 Ma
52、kefile 的關鍵字,我們將在后面討論。 四、文件搜尋在一些大的工程中,有大量的源文件,我們通常的做法是把這許多的源文件分類,并存放在不同的目錄中。所以,當 make 需要去找尋文件的依賴關系時,你可以在文件前加上路徑,但最好的方法是把一個路徑告訴 make,讓make 在自動去找。 Makefile 文件中的特殊變量“VPATH”就是完成這個功能的,如果沒有指明這個變量, make 只會在當前的目錄中去找尋依賴文件和目標文件。如果定義了這個變量,那么,make 就會在當當前目錄找不到的情況下,到所指定的目錄中去找尋文件了。 VPATH = src:./headers上面的的定義指定兩個目錄
53、,“src”和“./headers”,make 會按照這個順序進行搜 索。目錄由“冒號”分隔。(當然,當前目錄永遠是最高優(yōu)先搜索的地方) 另一個設置文件搜索路徑的方法是使用 make 的“vpath”關鍵字(注意,它是全小寫的),這不是變量,這是一個 make 的關鍵字,這和上面提到的那個 VPATH 變量很類似,但是它更為靈活。它可以指定不同的文件在不同的搜索目錄中。這是一個很靈活的功能。它的使 用方法有三種: 1、vpath 為符合模式的文件指定搜索目錄。2、vpath 清除符合模式的文件的搜索目錄。3、vpath 清除所有已被設置好了的文件搜索目錄。vapth 使用方法中的需要包含“%”
54、字符?!?”的意思是匹配零或若干字符, 例如,“%.h”表示所有以“.h”結(jié)尾的文件。 指定了要搜索的文件集,而 則指定了的文件集的搜索的目錄。例如: vpath %.h ./headers該語句表示,要求 make 在“./headers”目錄下搜索所有以“.h”結(jié)尾的文件。(如果 某文件在當前目錄沒有找到的話) 第 19 頁共 78 頁2005 年 10 月 14 日整理:祝冬華 跟我一起寫 Makefile作者:陳皓我們可以連續(xù)地使用 vpath 語句,以指定不同搜索策略。如果連續(xù)的 vpath 語句中出現(xiàn)了相同的,或是被重復了的,那么,make 會按照 vpath 語句的先后順序來執(zhí)行搜索。如: vpath %.c foo% blish%.c barvpathvpath其表示“.c”結(jié)尾的文件,先在“foo”目錄,然后是“blish”,最后是“bar”目錄。vpath %.c foo:barvpath % blish 而上面的語句則表示“.c”結(jié)尾的文件,先在“foo”目錄,然后是“bar”目錄,最后 才是“blish”目錄。 五、偽目標最早先的一個例子中,我們提到過一個“clean”的目標,這是一個“偽目標”,clean: rm *.o temp正像我們前面
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經(jīng)權益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
- 6. 下載文件中如有侵權或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 護理教育:護理實習生帶教與管理
- 護理審美意識在臨床實踐中的應用
- 2025-2026學年度重慶市萬州區(qū)高一上學期12月月考歷史試題(含答案)
- 急性中毒患兒的康復護理與指導
- 護理用藥錯誤的管理策略
- 小兒腸套疊的腸粘連護理與預防
- 牙周病患者的藥物使用與護理
- 護理分級管理中的溝通與協(xié)作
- 北京市大興2024-2025學年四年級上冊期末考試數(shù)學試卷(含答案)
- 肋軟骨回顧性讀片
- 醫(yī)防融合視角下家庭醫(yī)生簽約慢病管理策略
- 江蘇省揚州市江都區(qū)2025-2026學年八年級第一學期第二次月考語文答案
- 2025中原農(nóng)業(yè)保險股份有限公司招聘67人筆試備考重點試題及答案解析
- 2025中原農(nóng)業(yè)保險股份有限公司招聘67人備考考試試題及答案解析
- 2025年違紀違法典型案例個人學習心得體會
- 2025年度河北省機關事業(yè)單位技術工人晉升高級工考試練習題附正確答案
- 2025-2026學年人教版地理選擇性必修一期末質(zhì)量檢測練習卷(解析版)
- 配電室高低壓設備操作規(guī)程
- GB/T 17981-2025空氣調(diào)節(jié)系統(tǒng)經(jīng)濟運行
- 2025 年高職酒店管理與數(shù)字化運營(智能服務)試題及答案
- 《公司治理》期末考試復習題庫(含答案)
評論
0/150
提交評論