小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

GNU make中文手冊-第二章: GNU make 介紹

 todaytomo 2006-12-30
GNU make中文手冊-第二章: GNU make 介紹 作者: hew  發(fā)布日期: 2006-3-21    查看數(shù): 151   出自: http://www.
第二章: GNU make 介紹

--------------------------------------------------------------------------------

make在執(zhí)行時,需要一個命名為Makefile的文件。這個文件告訴make以何種方式編譯源代碼和鏈接程序。典型地,可執(zhí)行文件可由一些.o文件按 照一定的順序生成或者更新。如果在你的工程中已經(jīng)存在一個或者多個正確的Makefile。當(dāng)對工程中的若干源文件修改以后,需要根據(jù)修改來更新可執(zhí)行文 件或者庫文件,正如前面提到的你只需要在shell下執(zhí)行“make”。make會自動根據(jù)修改情況完成源文件的對應(yīng).o文件的更新、庫文件的更新、最終 的可執(zhí)行程序的更新。

make通過比較對應(yīng)文件(規(guī)則的目標和依賴,)的最后修改時間,來決定哪些文件需要更新、那些文件不需要更新。對需要更新的文件make就執(zhí)行數(shù)據(jù)庫中 所記錄的相應(yīng)命令(在make讀取Makefile以后會建立一個編譯過程的描述數(shù)據(jù)庫。此數(shù)據(jù)庫中記錄了所有各個文件之間的相互關(guān)系,以及它們的關(guān)系描 述)來重建它,對于不需要重建的文件make什么也不做。

而且可以通過make的命令行選項來指定需要重新編譯的文件。


--------------------------------------------------------------------------------

Problems and Bugs

=================

If you have problems with GNU `make‘ or think you‘ve found a bug, please report it to the developers; we cannot promise to do anything but we might well want to fix it.

Before reporting a bug, make sure you‘ve actually found a real bug.Carefully reread the documentation and see if it really says you can do what you‘re trying to do. If it‘s not clear whether you should be able to do something or not, report that too; it‘s a bug in the documentation!

Before reporting a bug or trying to fix it yourself, try to isolate it to the smallest possible makefile that reproduces the problem. Then send us the makefile and the exact results `make‘ gave you, including any error or warning messages. Please don‘t paraphrase these messages: it‘s best to cut and paste them into your report. When generating this small makefile, be sure to not use any non-free or unusual tools in your commands: you can almost always emulate what such a tool would do with simple shell commands. Finally, be sure to explain what you expected to occur; this will help us decide whether the problem was really in the documentation.

Once you have a precise problem you can report it in one of two ways.Either send electronic mail to:



bug-make@



or use our Web-based project management tool, at:



http://savannah./projects/make/



In addition to the information above, please be careful to include the version number of `make‘ you are using. You can get this information with the command `make --version‘. Be sure also to include the type of machine and operating system you are using. One way to obtain this information is by looking at the final lines of output from the command

`make --help‘.


--------------------------------------------------------------------------------

以上時GNU make的bug反饋方式。如果在你使用GNU make過程中。發(fā)現(xiàn)bug或者問題。可以通過以上的方式和渠道反饋。

好了。開始我們的神奇之旅吧!



2.1 Makefile簡介
在執(zhí)行make之前,需要一個命名為Makefile的特殊文件(本文的后續(xù)將使用Makefile作為這個特殊文件的文件名)來告訴make需要做什么(完成什么任務(wù)),該怎么做。通常,make工具主要被用來進行工程編譯和程序鏈接。

本節(jié)將分析一個簡單的Makefile,它對一個包含8個C的源代碼和三個頭文件的工程進行編譯和鏈接。這個Makefile提供給了make必要的信 息,make程序根據(jù)Makefile中的規(guī)則描述執(zhí)行相關(guān)的命令來完成指定的任務(wù)(如:編譯、鏈接和清除編譯過程文件等)。復(fù)雜的Makefile我們 將會在本文后續(xù)進行討論。

當(dāng)使用make工具進行編譯時,工程中以下幾種文件在執(zhí)行make時將會被編譯(重新編譯):

1. 所有的源文件沒有被編譯過,則對各個C源文件進行編譯并進行鏈接,生成最后的可執(zhí)行程序;

2. 每一個在上次執(zhí)行make之后修改過的C源代碼文件在本次執(zhí)行make時將會被重新編譯;

3. 頭文件在上一次執(zhí)行make之后被修改。則所有包含此頭文件的C源文件在本次執(zhí)行make時將會被重新編譯。

后兩種情況是make只將修改過的C源文件重新編譯生成.o文件,對于沒有修改的文件不進行任何工作。重新編譯過程中,任何一個源文件的修改將產(chǎn)生新的對應(yīng)的.o文件,新的.o文件將和以前的已經(jīng)存在、此次沒有重新編譯的.o文件重新連接生成最后的可執(zhí)行程序。

首先讓我們先來看一些Makefile相關(guān)的基本知識。



2.2 Makefile規(guī)則介紹
一個簡單的Makefile描述規(guī)則組成:

TARGET... : PREREQUISITES...

COMMAND

...

...

target:規(guī)則的目標。通常是程序中間或者最后需要生成的文件名??梢允?o文件、也可以是最后的可執(zhí)行程序的文件名。另外,目標也可以是一個make執(zhí)行的動作的名稱,如目標“clean”,成這樣的目標是“偽目標”。

prerequisites:規(guī)則的依賴。生成規(guī)則目標所需要的文件名列表。通常一個目標依賴于一個或者多個文件。

command:規(guī)則的命令行。是make程序所有執(zhí)行的動作(任意的shell命令或者可在shell下執(zhí)行的程序)。

一個規(guī)則可以有多個命令行,每一條命令占一行。注意:每一個命令行必須以[Tab]字符開始,[Tab]字符告訴make此行是一個命令行。make按照命令完成相應(yīng)的動作。這也是書寫Makefile中容易產(chǎn)生,而且比較隱蔽的錯誤。

命令就是在任何一個目標的依賴文件發(fā)生變化后重建目標的動作描述。一個目標可以沒有依賴而只有動作(指定的命令)。比如Makefile中的目標“clean”,此目標沒有依賴,只有命令。它所指定的命令用來刪除make過程產(chǎn)生的中間文件(清理工作)。

在Makefile中“規(guī)則”就是描述在什么情況下、如何重建規(guī)則的目標文件,通常規(guī)則中包括了目標的依賴關(guān)系(目標的依賴文件)和重建目標的命令。 make執(zhí)行重建目標的命令,來創(chuàng)建或者重建規(guī)則的目標(此目標文件也可以是觸發(fā)這個規(guī)則的上一個規(guī)則中的依賴文件)。規(guī)則包含了目標和依賴的關(guān)系以及更 新目標所要求的命令。

Makefile中可以包含除規(guī)則以外的部分。一個最簡單的Makefile可能只包含規(guī)則描述。規(guī)則在有些Makefile中可能看起來非常復(fù)雜,但是無論規(guī)則的書寫是多么的復(fù)雜,它都符合規(guī)則的基本格式。

2.3 簡單的示例
本小節(jié)開始我們在第一小節(jié)中提到的例子。此例子由3個頭文件和8個C文件組成。我們講述寫一個簡單的Makefile,來描述如何創(chuàng)建最終的可執(zhí)行文件“edit”,此可執(zhí)行文件依賴于8個C源文件和3個頭文件。Makefile文件的內(nèi)容如下:

#sample Makefile

edit : main.o kbd.o command.o display.o \

insert.o search.o files.o utils.o

cc -o edit main.o kbd.o command.o display.o \

insert.o search.o files.o utils.o

main.o : main.c defs.h

cc -c main.c



kbd.o : kbd.c defs.h command.h

cc -c kbd.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.h

cc -c files.c

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清晰、容易閱讀。注意:反斜線之后不能有空格(這也是大家最容易犯的 錯誤,而且錯誤比較隱蔽)。大家在書寫Makefile時,推薦者中將較長行分解為使用反斜線連接得多個行的方式。當(dāng)我們完成了這個Maekfile以 后;創(chuàng)建可執(zhí)行程序“edit”,你所要做的就是在包含此Makefile的目錄(當(dāng)然也在代碼所在的目錄)下輸入命令“make”。刪除已經(jīng)本目錄下生 成的文件和所有的.o文件,只需要輸入命令“make clean”就可以了。

在這個Makefile中,目標(target)包含:可執(zhí)行文件“edit”和.o文件(main.o,kbd.o….),依賴 (prerequisites)就是冒號后面的那些 .c 文件和 .h文件。所有的.o文件既是依賴(相對于可執(zhí)行程序edit)又是目標(相對于.c和.h文件)。命令包括 “cc –c maic.c”、“cc –c kbd.c”……

目標是一個文件時,當(dāng)它的任何一個依賴文件被修改以后,這個目標文件將會被重新編譯或者重新連接。當(dāng)然,此目標的任何一個依賴文件如果有必要則首先會被重 新編譯。在這個例子中,“edit”的依賴為8個.o文件;而“main.o”的依賴文件為“main.c”和“defs.h”。當(dāng)“main.c”或者 “defs.h”被修改以后,再次執(zhí)行“make”時“main.o”就會被更新(其它的.o文件不會被更新),同時“main.o” 的更新將會導(dǎo)致“edit”被更新。

在描述目標和依賴之下的shell命令行,它描述了如何更新目標文件。命令行必需以[Tab]鍵開始,以和Makefile其他行區(qū)別。就是說所有的命令 行必需以[Tab] 字符開始,但并不是所有的以[Tab]鍵出現(xiàn)行都是命令行。但make程序會把出現(xiàn)在第一條規(guī)則之后的所有的以[Tab]字符開始的行都作為命令行來處 理。(要記?。簃ake程序不關(guān)心命令是如何工作的,對目標文件的更新需要你在規(guī)則的描述中提供正確的命令。“make”程序所做的就是當(dāng)目標程序需要更 新時執(zhí)行規(guī)則所定義的命令)。

目標“clean”不是一個文件,它僅僅代表了執(zhí)行一個動作的標識。通常情況下,不需要執(zhí)行這個規(guī)則所定義的動作,因此目標“clean”沒有出現(xiàn)在其它 規(guī)則的依賴列表中。在執(zhí)行make時,它所指定的動作不會被執(zhí)行。除非執(zhí)行make時明確地指定它作為重建目標。而且目標“clean”沒有任何依賴文 件,它只有一個目的,就是通過這個目標名來執(zhí)行它所定義的命令。Makefile中把那些沒有任何依賴只有執(zhí)行動作的目標稱為“偽目標”(phony targets)。執(zhí)行“clean”目標所定義的命令,可在shell下輸入:make clean。



2.4 make如何工作
默認的情況下,make執(zhí)行Makefile中的第一個規(guī)則,此規(guī)則的第一個目標稱之為“最終目的”或者“終極目標”(就是一個Makefile最終需要更新或者創(chuàng)建的目標)。

上例的Makefile,目標“edit”在Makefile中是第一個目標,因此它就是make的“終極目標”。當(dāng)修改了任何C源文件或者頭文件后,執(zhí)行make將會重建終極目標“edit”。

當(dāng)在shell提示符下輸入“make”命令以后。make讀取當(dāng)前目錄下的Makefile文件,并將Makefile文件中的第一個目標作為其“終極 目標”,開始處理第一個規(guī)則(終極目標所在的規(guī)則)。在我們的例子中,第一個規(guī)則就是目標“edit”所在的規(guī)則。規(guī)則描述了“edit”的依賴關(guān)系,并 定義了鏈接.o文件生成目標“edit”的命令; make在處理這個規(guī)則之前,首先將處理目標“edit”的所有的依賴文件(例子中的那些.o文件)的更新規(guī)則;對包含這些.o文件的規(guī)則進行處理。對. o文件所在的規(guī)則的處理有下列三種情況:

1. 目標.o文件不存在,使用其描述規(guī)則創(chuàng)建它;

2. 目標.o文件存在,目標.o文件所依賴的.c源文件、.h文件中的任何一個比目標.o文件“更新”(在上一次make之后被修改)。則根據(jù)規(guī)則重新編譯生成它;

3. 目標.o文件存在,目標.o文件比它的任何一個依賴文件(的.c源文件、.h文件)“更新”(它的依賴文件在上一次make之后沒有被修改),則什么也不做。

這些.o文件所在的規(guī)則之所以會被執(zhí)行,是因為這些.o文件出現(xiàn)在“終極目標”的依賴列表中。如果在Makefile中一個規(guī)則所描述的目標不是“終極目 標”所依賴的(或者“終極目標”的依賴文件所依賴的),那么這個規(guī)則將不會被執(zhí)行。除非明確指定這個規(guī)則(可以通過make的命令行指定重建目標,那么這 個目標所在的規(guī)則就會被執(zhí)行,例如 “make clean”)。在編譯或者重新編譯生成一個.o文件時,make同樣會去尋找它的依賴文件的重建規(guī)則(是這樣一個規(guī)則:這個依賴文件在規(guī)則中作為目標出 現(xiàn)),就是.c和.h文件的重建規(guī)則。在上例的Makefile中沒有哪個規(guī)則的目標是.c或者.h文件,所以沒有重建.c和.h文件的規(guī)則。不過C言語 的源程序文件可以使用工具Bison或者Yacc來生成(具體用法可參考相應(yīng)的手冊)。

完成了對.o文件的創(chuàng)建(第一次編譯)或者更新之后,make程序?qū)⑻幚斫K極目標“edit”所在的規(guī)則,分為以下三種情況:

1. 目標文件“edit”不存在,則執(zhí)行規(guī)則創(chuàng)建目標“edit”。

2. 目標文件“edit”存在,其依賴文件中有一個或者多個文件比它“更新”,則根據(jù)規(guī)則重新鏈接生成“edit”。

3. 目標文件“edit”存在,它比它的任何一個依賴文件都“更新”,則什么也不做。

上例中,如果更改了源文件“insert.c”后執(zhí)行make,“insert.o”將被更新,之后終極目標“edit”將會被重生成;如果我們修改了頭 文件“command.h”之后運行“make”,那么“kbd.o”、“command.o”和“files.o”將會被重新編譯,之后同樣終極目標 “edit”也將被重新生成。

以上我們通過一個簡單的例子,介紹了Makefile中目標和依賴的關(guān)系。對于Makefile中的目標。在執(zhí)行“make”時首先執(zhí)行終極目標所在的規(guī) 則,接下來一層層地去尋找終極目標的依賴文件所在的規(guī)則并執(zhí)行。當(dāng)終極目標的規(guī)則被完全的展開以后,make將從最后一個被展開的規(guī)則處開始執(zhí)行,之后處 理倒數(shù)第二個規(guī)則,……依次回退。最后一步執(zhí)行的就是終極目標所在的規(guī)則。整個過程就類似于C語言中的遞歸實現(xiàn)一樣。在更新(或者創(chuàng)建)終極目標的過程 中,如果出現(xiàn)錯誤make就立即報錯并退出。整個過程make只是負責(zé)執(zhí)行規(guī)則,而對具體規(guī)則所描述的依賴關(guān)系的正確性、規(guī)則所定義的命令的正確性不做任 何判斷。就是說,一個規(guī)則的依賴關(guān)系是否正確、描述重建目標的規(guī)則命令行是否正確,make不做任何錯誤檢查。

因此,需要正確的編譯一個工程。需要在提供給make程序的Makefile中來保證其依賴關(guān)系的正確性、和執(zhí)行命令的正確性。



2.5 指定變量
同樣是上邊的例子,我們來看一下終極目標“edit”所在的規(guī)則:



edit : main.o kbd.o command.o display.o \

insert.o search.o files.o utils.o

cc -o edit main.o kbd.o command.o display.o \

insert.o search.o files.o utils.o



在這個規(guī)則中.o文件列表出現(xiàn)了兩次;第一次:作為目標“edit”的依賴文件列表出現(xiàn),第二次:規(guī)則命令行中作為“cc”的參數(shù)列表。這樣做所帶來的問 題是:如果我們需要為目標“edit”增加一個的依賴文件,我們就需要在兩個地方添加(依賴文件列表和規(guī)則的命令中)。添加時可能在“edit”的依賴列 表中加入了、但卻忘記了給命令行中添加,或者相反。這樣給后期的維護和修改帶來了很多不方便,而且容易出現(xiàn)修改遺漏。

為了避免這個問題,在實際工作中大家都比較認同的方法是,使用一個變量“objects”、“OBJECTS”、“objs”、“OBJS”、“obj” 或者“OBJ”來作為所有的.o文件的列表的替代。在使用到這些文件列表的地方,使用此變量來代替。在上例的Makefile中可是添加這樣一行:



objects = main.o kbd.o command.o display.o \

insert.o search.o files.o utils.o



“objects”作為一個變量,它代表所有的.o文件的列表。在定義了此變量后,我們就可以在需要使用這些.o文件列表的地方使用“$(objects)”來表示它,而不需要羅列所有的.o文件列表。因此上例的規(guī)則就可以這樣寫:



objects = main.o kbd.o command.o display.o \

insert.o search.o files.o utils.o

edit : $(objects)

cc -o edit $(objects)

…….

…….

clean :

rm edit $(objects)



需要增加或者去掉一個.o文件時。我們只需要改變“objects”的定義(加入或者去掉若干個.o文件)。這樣做不但減少維護的工作量,而且可以避免由于遺漏而產(chǎn)生錯誤的可能。



2.6 自動推導(dǎo)規(guī)則
在使用make編譯.c源文件時,可以省略編譯一個.c文件所使用的命令。這是因為make存在一個默認的規(guī)則,能夠自動完成對.c文件的編譯并生成對應(yīng) 的.o文件。它執(zhí)行命令“cc -c”來編譯.c源文件。對于上邊的例子,此默認規(guī)則就使用命令“cc -c main.c -o main.o”來創(chuàng)建文件“main.o”。因此對一個目標文件是“N.o”,倚賴文件是“N.c”的規(guī)則??梢允÷云湟?guī)則的命令行,使用make的默認 命令。此默認規(guī)則稱為make的隱含規(guī)則。

我們書寫Makefile時,對于一個.c文件如果使用make的隱含規(guī)則,那么它會被自動作為對應(yīng).o文件的一個依賴文件(對應(yīng)是指:文件名除后綴外,其余都相同的兩個文件)。因此我們也可以在規(guī)則中省略目標的倚賴.c文件。

我們上邊的例子就可以以更加簡單的方式書寫,使用了變量“objects”。簡化版本的Makefile如下:



# sample Makefile

objects = main.o kbd.o command.o display.o \

insert.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.h command.h

utils.o : defs.h



.PHONY : clean

clean :

rm edit $(objects)



這種格式的Makefile更接近于我們實際的應(yīng)用。(關(guān)于目標“clean”的詳細說明我們在后邊。

make的隱含規(guī)則在實際工程的make中會經(jīng)常使用,它使得編譯過程變得方便。幾乎在所有的Makefile中都用到了make的隱含規(guī)則,make的隱含規(guī)則是非常重要的一個概念。后續(xù)我們會在第九章會專門討論make的隱含規(guī)則。



2.7 另類風(fēng)格的makefile
Makefile中,目標使用隱含規(guī)則生成,我們就可以也可以書寫另外一種風(fēng)格Makefile。在這個Makefile中,根據(jù)依賴而不是目標對規(guī)則進行分組。上例的Makefile就可以這樣來實現(xiàn):



#sample Makefile

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



例子中頭文件“defs.h”作為所有.o文件的依賴文件。其它兩個頭文件作為其對應(yīng)規(guī)則的目標中所列舉的所有.o文件的依賴文件。

但是這種風(fēng)格的Makefile并不值得我們借鑒。問題在于:同時把多個目標文件的依賴放在同一個規(guī)則中進行描述(一個規(guī)則中含有多個目標文件),這樣導(dǎo) 致規(guī)則定義不明了,比較混亂。建議大家不要在Makefile中采用這種方式了書寫。否則后期維護將會是一件非常痛苦的事情。

書寫規(guī)則建議的方式是:單目標,多依賴。就是說盡量要做到一個規(guī)則中只存在一個目標文件,可有多個依賴文件。盡量避免多目標,單依賴的方式。這樣后期維護也會非常方便,而且Makefile會更清晰、明了。



2.8 清除工作目錄過程文件
在Makefile中的規(guī)則也可以完成除編譯以外的任務(wù)。例如:前邊提到的實現(xiàn)清除當(dāng)前目錄中在編譯過程中生成的文件(edit和哪些.o文件)的規(guī)則:



clean :

rm edit $(objects)



在實際應(yīng)用時,我們會把這個規(guī)則寫成如下稍微復(fù)雜一些的樣子。以防止出現(xiàn)始料未及的情況。

.PHONY : clean

clean :

-rm edit $(objects)



這兩個實現(xiàn)有兩點不同: 1. 通過“.PHONY”特殊目標將“clean”目標聲明為偽目標。防止當(dāng)磁盤上存在一個名為“clean”文件時,“clean”所在規(guī)則的命令無法執(zhí)行。2. 在命令行之前使用“-”,意思是忽略命令“rm”的執(zhí)行錯誤。

這樣的一個目標在Makefile中,不能將其作為終極目標(Makefile的第一個目標)。因為我們的初衷并不是當(dāng)你在命令行上輸入make以后執(zhí)行 刪除動作。而是要創(chuàng)建或者更新程序。在我們上邊的例子中。就是在輸入make以后要需要對目標“edit”進行創(chuàng)建或者重建。

上例中因為目標“clean”沒有出現(xiàn)在終極目標“edit”依賴關(guān)系中,所以我們執(zhí)行“make”時,目標“clean”所在的規(guī)則將不會被處理。如果需要執(zhí)行此規(guī)則,需要在make的命令行選項中明確指定這個目標(執(zhí)行“make clean”)。

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多