通常,在一個大型項目中,會有很多個 .c 文件和 .h 文件,這些文件互相依賴互相關聯,開發過程中需要多次修改代碼,每當修改其中一個文件的代碼時,通常需要將這些文件重新編譯一次,這個過程非常麻煩。(不停的輸入 gcc -xx xxx 命令),因此 就產生了Make的自動化編譯工具,極大的提高了軟件開發的效率。而會不會寫makefile,也從一個側面說明了一個人是否具備完成大型工程的能力。
簡單來說:Make有兩個重要的規則:1、依賴關係。2、依賴方法。
下面簡單簡述一下make文件的規則:
Makefile的編寫規則:
target ... : prerequisites ...
command
...
...
(注意:command命令前必須有一個Tab)
target 也就是一個目標文件,可以是Object File,也可以是執行文件。還可以是一個標籤(Label),對於標籤這種特性,後面再說。
prerequisites 就是,要生成那個target所需要的文件或是目標。
command 也就是make需要執行的命令。(任意的Shell命令)
這是一個文件的依賴關係,也就是說,target這一個或多個的目標文件依賴於prerequisites中的文件,其生成規則定義在command中。說白一點就是說,prerequisites中如果有一個以上的文件比target文件要新的話,command所定義的命令就會被執行。這就是Makefile的規則。也就是Makefile中最核心的內容。
舉個例子:以下是一個簡單的C工程
此時,我們輸入命令:make 會顯示 gcc -o test test.c test.h
則說明我們的 test.c 文件已完成編譯。此時我們就可以直接使用 ./test 命令運行程序了
最後再make clean 完成清理工作
make是如何工作的
在默認的方式下,也就是我們只輸入make命令。那麼,
1 make會在當前目錄下找名字叫“Makefile”或“makefile”的文件。
2 如果找到,它會找文件中的第一個目標文件(target),在上面的
例子中,他會找到“edit”這個文件,並把這個文件作爲最終的目標文
件。
3 如果edit文件不存在,或是edit所依賴的後面的 .o 文件的文件修改
時間要比edit這個文件新,那麼,他就會執行後面所定義的命令來生
成edit這個文件。
4 如果edit所依賴的.o文件也存在,那麼make會在當前文件中找目標
爲.o文件的依賴性,如果找到則再根據那一個規則生成.o文件。(這
有點像一個堆棧的過程)
5 當然,你的C文件和H文件是存在的啦,於是make會生成 .o 文件,
然後再用 .o 文件聲明make的終極任務,也就是執行文件edit了。
這就是整個make的依賴性,make會一層又一層地去找文件的依賴關係,
直到最終編譯出第一個目標文件。在找尋的過程中,如果出現錯誤,比如
最後被依賴的文件找不到,那麼make就會直接退出,並報錯,而對於所定
義的命令的錯誤,或是編譯不成功,make根本不理。make只管文件的依
賴性,即,如果在我找了依賴關係之後,冒號後面的文件還是不在,那麼
對不起,我就不工作啦。
通過上述分析,我們知道,像clean這種,沒有被第一個目標文件直接
或間接關聯,那麼它後面所定義的命令將不會被自動執行,不過,我們可
以顯示要make執行。即命令——“make clean”,以此來清除所有的目標
文件,以便重編譯。
於是在我們編程中,如果這個工程已被編譯過了,當我們修改了其中
一個源文件,比如file.c,那麼根據我們的依賴性,我們的目標file.o會被重
編譯(也就是在這個依性關係後面所定義的命令),於是file.o的文件也是
最新的啦,於是file.o的文件修改時間要比edit要新,所以edit也會被重新鏈
接了(詳見edit目標文件後定義的命令)。
而如果我們改變了“command.h”,那麼,kdb.o、command.o和files.o都會被
重編譯,並且,edit會被重鏈接。
簡化書寫:讓make自動推導
Makefile文件內容書寫方式有兩種:
方法1:(我們上面例子是方法2)
test:test.o
gcc -o test test.o(關係與方法必須緊挨着)
test.o:test.s
gcc -c test.s -o test.o
test.s:test.i
gcc -S test.i test.s
test.i:test.c
gcc -E test.c -o test.i
清理工程
.PHONY:clean(意思clean是一個僞目標)
clean:
rm -f test.o test.s test.i test
方法2:
test:test.c
@gcc -o test test.c
.PHONY:clean
這種方法雖然看起來是Makefile文件更加簡潔,但凡事都有兩面性,這會破壞文件本身的依賴關係,如果文件過多的話,可能會造成混淆。