linux c/c++ 編程之-----makefile 初探

首先要把源文件編譯成中間代碼文件,在 Windows 下也就是 .obj 文件,UNIX 下是 .o 文件.這個動作叫做編譯(compile)

然後再把大量的 Object File合成執行文件,這個動作叫作鏈接(link)


編譯時

編譯時,編譯器需要的是語法的正確,函數與變量的聲明的正確。

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

鏈接時

鏈接時,主要是鏈接函數和全局變量,所以,我們可以使用這些中間目標文件(O 文件或是 OBJ 文件)來鏈接我們的應用程序。鏈接器並不管函數所在的源文件,只管函數的中間目標文件(Object File),

在大多數時候,由於源文件太多,編譯生成的中間目標文件太多,而在鏈接時需要明顯地指出中間目標文件名,這對於編譯很不方便,所以,我們要給中間目標文件打個包,在 Windows 下這種包叫“庫文件”(LibraryFile),也就是 .lib 文件,在 UNIX 下,是 Archive File,也就是 .a 文件。


總結一下,源文件首先會生成中間目標文件,再由中間目標文件生成執行文件。

在編譯時,編譯器只檢測程序語法,和函數、變量是否被聲明。如果函數未被聲明,編譯器會給出一個警告,但可以生成 Object File。而在鏈接程序時,鏈接器會在所有的 ObjectFile 中找尋函數的實現,如果找不到,那到就會報鏈接錯誤碼(Linker Error),在 VC

下,這種錯誤一般是:Link 2001 錯誤,意思說是說,鏈接器未能找到函數的實現。你需要指定函數的 Object File. (陳浩-CSDN)


make/make clean


makefile 定義了一系列的規則來指定,哪些文件需要先編譯,哪些文件需要後編譯,哪些文件需要重新編譯,甚至於進行更復雜的功能操作,因爲 makefile 就像一個 Shell 腳本一樣,其中也可以執行操作系統的命令。


make 規則

1)如果這個工程沒有編譯過,那麼我們的所有 C 文件都要編譯並被鏈接。

2)如果這個工程的某幾個 C 文件被修改,那麼我們只編譯被修改的 C 文件,並鏈接目標程序。

3)如果這個工程的頭文件被改變了,那麼我們需要編譯引用了這幾個頭文件的 C 文件,並鏈接目標程序。


描述文件依賴關係

target: components

TAB rule

這 是 一 個 文 件 的 依 賴 關 系 , 也 就 是 說 , target 這 一 個 或 多 個 的 目 標 文 件 依 賴 於prerequisites 中的文件,其生成規則定義在 command 中。說白一點就是說,prerequisites中如果有一個以上的文件比 target 文件要新的話,command 所定義的命令就會被執行。



在定義好依賴關係後,後續的那一行定義瞭如何生成目標文件的操作系統命令,一定以一個 Tab 鍵作爲開頭。記住,make 並不管命令是怎麼工作的,他只管執行所定義的命令。make 會比較 targets 文件和 prerequisites 文件的修改日期,如果 prerequisites 文件的日期要比 targets 文件的日期要新,或者 target 不存在的話,那麼,make 就會執行後續定義的命令。


這就是整個 make 的依賴性,make 會一層又一層地去找文件的依賴關係,直到最終編譯出第一個目標文件


在找尋的過程中,如果出現錯誤,比如最後被依賴的文件找不到,那麼 make 就會直接退出,並報錯,

而對於所定義的命令的錯誤,或是編譯不成功,make 根本不理。make 只管文件的依賴性,即,如果在我找了依賴關係之後,冒號後面的文件還是不在,那麼對不起,我就不工作啦。


make 工作步驟

1、make 會在當前目錄下找名字叫“Makefile”或“makefile”的文件。

2、如果找到,它會找文件中的第一個目標文件(target)並把這個文件作爲最終的目標文件。

3、如果 edit 文件不存在,或是 edit 所依賴的後面的 .o 文件的文件修改時間要比 edit 這個文件新,那麼,他就會執行後面所定義的命令來生成 edit 這個文件。

4、如果 edit 所依賴的.o 文件也存在,那麼 make 會在當前文件中找目標爲.o 文件的依賴性,如果找到則再根據那一個規則生成.o 文件。(這有點像一個堆棧的過程)

5、當然,你的 C 文件和 H 文件是存在的啦,於是 make 會生成 .o 文件,然後再用 .o 文件生命 make 的終極任務,也就是執行文件 edit 了。


clean :

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

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

這裏要說明一點的是,clean 不是一個文件,它只不過是一個動作名字,有點像 C 語言

中的 lable 一樣,其冒號後什麼也沒有,那麼,make 就不會自動去找文件的依賴性,

也就不會自動執行其後所定義的命令。要執行其後的命令,就要在 make 命令後明顯得

指出這個 lable 的名字。這樣的方法非常有用,我們可以在一個 makefile 中定義不用的

編譯或是和編譯無關的命令,比如程序的打包,程序的備份,等等。


#開始註釋行


變量

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

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

edit : $(objects)


Makefile 有三個非常有用的變量.分別是$@,$^,$<代表的意義分別是:

$@--目標文件,

$^--所有的依賴文件,

$<--第一個依賴文件.


一個 Makefile 的缺省規則

..c.o:

gcc -c $<

這個規則表示所有的 .o 文件都是依賴與相應的.c 文件的


GNU 的 make 很強大,它可以自動推導文件以及文件依賴關係後面的命令,於是我們就沒必要去在每一個[.o]文件後都寫上類似的命令,因爲,我們的 make 會自動識別,並自己推導命令。



這種方法,也就是 make 的“隱晦規則”。

files.o : defs.h buffer.h command.h

utils.o : defs.h

.PHONY : clean

clean :

rm edit $(objects)

上面文件內容中,“.PHONY”表示,clean 是個僞目標文件。



.PHONY : clean

clean :

-rm edit $(objects)

前面說過,.PHONY 意思表示 clean 是一個“僞目標”,。

而在 rm 命令前面加了一個小減號的意思就是,也許某些文件出現問題,但不要管,繼續做後面的事。當然,clean的規則不要放在文件的開頭,不然,這就會變成 make 的默認目標,相信誰也不願意這樣。


不成文的規矩是——“clean 從來都是放在文件的最後”。


一、Makefile 裏有什麼?

Makefile 裏主要包含了五個東西:顯式規則、隱晦規則、變量定義、文件指示和註釋。

1、顯式規則。

顯式規則說明了,如何生成一個或多的的目標文件。

這是由 Makefile 的書寫者明顯指出,要生成的文件,文件的依賴文件,生成的命令。

2、隱晦規則。

由於我們的 make 有自動推導的功能,所以隱晦的規則可以讓我們比較粗糙地簡略地書寫 Makefile,這是由 make 所支持的。


引用其它的 Makefile

在 Makefile 使 用 include 關 鍵 字 可 以 把 別 的 Makefile 包 含 進 來 , 這 很 像 C 語 言 的#include,被包含的文件會原模原樣的放在當前文件的包含位置。include 的語法是:

include <filename>

filename 可以是當前操作系統 Shell 的文件模式(可以保含路徑和通配符)

在 include 前面可以有一些空字符,但是絕不能是[Tab]鍵開始。include 和<filename>可b.mk、c.mk,還有

以用一個或多個空格隔開。

舉個例子,你有這樣幾個 Makefile:a.mk、一個文件叫 foo.make,以及一個變量$(bar),其包含了 e.mk 和 f.mk,那麼,下面的語句:

include foo.make *.mk $(bar)

等價於:

include foo.make a.mk b.mk c.mk e.mk f.mk

make 命令開始時,會把找尋 include 所指出的其它 Makefile,並把其內容安置在當前的位置,就好像 C/C++的#include 指令一樣。

如果文件都沒有指定絕對路徑或是相對路徑的話,make 會在當前目錄下首先尋找,如果當前目錄下沒有找到,那麼,make 還會在

下面的幾個目錄下找:

1、如果 make 執行時,有“-I”或“--include-dir”參數,那麼 make 就會在這個參數所指定的目錄下去尋找。

2、如果目錄<prefix>/include(一般是:/usr/local/bin 或/usr/include)存在的話,make 也會去找。



























































發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章