2008年10月1日 星期三

轉載--跟我一起寫Makefile

半年多來,因為專案的需要,必須重拾用Linux & C++開發程控系統,由於必須傳授小弟們一些基礎概念,最讓我頭痛之一莫過於make(用於自動化編譯),幸好在內地有位大內高手把makefile的教學寫的超級平易近人,有時不得不佩服對岸的人才濟濟。

----------以下為轉貼部份內容----------

跟我一起寫 Makefile


陳皓

概述
——

什麼是makefile?或許很多Winodws的程序員都不知道這個東西,因為那些 Windows的IDE都為你做了這個工作,但我覺得要作一個好的和professional的程序員,makefile還是要懂。這就好像現在有這麼多 的HTML的編輯器,但如果你想成為一個專業人士,你還是要瞭解HTML的標識的含義。特別在Unix下的軟件編譯,你就不能不自己寫makefile 了,會不會寫makefile,從一個側面說明了一個人是否具備完成大型工程的能力。

因為,makefile關係到了整個工程的編譯規則。一個工程中的源文件不計數,其按類型、功 能、模塊分別放在若干個目錄中,makefile定義了一系列的規則來指定,哪些文件需要先編譯,哪些文件需要後編譯,哪些文件需要重新編譯,甚至於進行 更複雜的功能操作,因為makefile就像一個Shell腳本一樣,其中也可以執行操作系統的命令。

makefile帶來的好處就是——「自動化編譯」,一旦寫好,只需要一個make命令,整個 工程完全自動編譯,極大的提高了軟件開發的效率。make是一個命令工具,是一個解釋makefile中指令的命令工具,一般來說,大多數的IDE都有這 個命令,比如:Delphi的make,Visual C++的nmake,Linux下GNU的make。可見,makefile都成為了一種在工程方面的編譯方法。

現在講述如何寫makefile的文章比較少,這是我想寫這篇文章的原因。當然,不同產商的 make各不相同,也有不同的語法,但其本質都是在「文件依賴性」上做文章,這裡,我僅對GNU的make進行講述,我的環境是RedHat Linux 8.0,make的版本是3.80。必竟,這個make是應用最為廣泛的,也是用得最多的。而且其還是最遵循於IEEE 1003.2-1992 標準的(POSIX.2)。

在這篇文檔中,將以C/C++的源碼作為我們基礎,所以必然涉及一些關於C/C++的編譯的知識,相關於這方面的內容,還請各位查看相關的編譯器的文檔。這裡所默認的編譯器是UNIX下的GCC和CC。

關於程序的編譯和鏈接
——————————

在此,我想多說關於程序編譯的一些規範和方法,一般來說,無論是C、C++、還是pas,首先 要把源文件編譯成中間代碼文件,在Windows下也就是 .obj 文件,UNIX下是 .o 文件,即 Object File,這個動作叫做編譯(compile)。然後再把大量的Object File合成執行文件,這個動作叫作鏈接(link)。

編譯時,編譯器需要的是語法的正確,函數與變量的聲明的正確。對於後者,通常是你需要告訴編譯 器頭文件的所在位置(頭文件中應該只是聲明,而定義應該放在C/C++文件中),只要所有的語法正確,編譯器就可以編譯出中間目標文件。一般來說,每個源 文件都應該對應於一個中間目標文件(O文件或是OBJ文件)。

鏈接時,主要是鏈接函數和全局變量,所以,我們可以使用這些中間目標文件(O文件或是OBJ文 件)來鏈接我們的應用程序。鏈接器並不管函數所在的源文件,只管函數的中間目標文件(Object File),在大多數時候,由於源文件太多,編譯生成的中間目標文件太多,而在鏈接時需要明顯地指出中間目標文件名,這對於編譯很不方便,所以,我們要給 中間目標文件打個包,在Windows下這種包叫「庫文件」(Library File),也就是 .lib 文件,在UNIX下,是Archive File,也就是 .a 文件。

總結一下,源文件首先會生成中間目標文件,再由中間目標文件生成執行文件。在編譯時,編譯器只 檢測程序語法,和函數、變量是否被聲明。如果函數未被聲明,編譯器會給出一個警告,但可以生成Object File。而在鏈接程序時,鏈接器會在所有的Object File中找尋函數的實現,如果找不到,那到就會報鏈接錯誤碼(Linker Error),在VC下,這種錯誤一般是:Link 2001錯誤,意思說是說,鏈接器未能找到函數的實現。你需要指定函數的Object File.

好,言歸正傳,GNU的make有許多的內容,閒言少敘,還是讓我們開始吧。

Makefile 介紹
———————

make命令執行時,需要一個 Makefile 文件,以告訴make命令需要怎麼樣的去編譯和鏈接程序。

首先,我們用一個示例來說明Makefile的書寫規則。以便給大家一個感興認識。這個示例來源於GNU的make使用手冊,在這個示例中,我們的工程有8個C文件,和3個頭文件,我們要寫一個Makefile來告訴make命令如何編譯和鏈接這幾個文件。我們的規則是:
1)如果這個工程沒有編譯過,那麼我們的所有C文件都要編譯並被鏈接。
2)如果這個工程的某幾個C文件被修改,那麼我們只編譯被修改的C文件,並鏈接目標程序。
3)如果這個工程的頭文件被改變了,那麼我們需要編譯引用了這幾個頭文件的C文件,並鏈接目標程序。

只要我們的Makefile寫得夠好,所有的這一切,我們只用一個make命令就可以完成,make命令會自動智能地根據當前的文件修改的情況來確定哪些文件需要重編譯,從而自己編譯所需要的文件和鏈接目標程序。

....

該教學文章共分為十四篇,最重要的是都有簡單的例子,讓你可以馬上實作,值得讚賞!
上列轉貼出部份內容,有興趣的同好們,請前往右列網址參拜:陳皓--跟我一起寫Makefile

沒有留言: