Linux中Makefile的編寫

   通常,在一個大型項目中,會有很多個 .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工程

wKiom1ewHnqgU0IaAABK1eW-ISQ817.png

wKioL1ewHnqgtqGCAAA_3gMOh8E402.png

此時,我們輸入命令:make  會顯示 gcc -o test test.c test.h

則說明我們的 test.c 文件已完成編譯。此時我們就可以直接使用 ./test 命令運行程序了

wKiom1ewHnrRyWjgAAA_9uKQ-OQ323.png

最後再make clean 完成清理工作

wKioL1ewHnug0sgMAAA3VqVBY2s400.png




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文件更加簡潔,但凡事都有兩面性,這會破壞文件本身的依賴關係如果文件過多的話,可能會造成混淆。





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