簡單實例,makefile自動依賴(二)

參考自:http://blog.chinaunix.net/uid-20316928-id-3395996.html

《跟我一起學makedfile》 《GUN makefile……》


上一篇中發現修改了頭文件,但是執行make後不會自動重新編譯,

研究發現是因爲沒有頭文件的依賴,最傻的加依賴方法就是在編譯的時候頭文件一塊加進去。

那樣子的話總不能每增加一個頭文件都要去改一次makefile,上網一搜發現可以自動生成依賴文件,所以有了這篇文章。


有錯的地方歡迎指出。互相交流,共同進步。



首先上編譯前的源碼樹:



頂層makefile:


主要講一下makefile中使用的幾個函數:

第7行:wildcard

返回的值是include目錄下面的所有的.h文件

第11行:join

$(join aaa bbb , 111 222 333)返回值是“aaa111 bbb222 333”

第12行:patsubst:

$(patsubst %.c,%.o,x.c.c bar.c)
把字串“x.c.c bar.c”符合模式[%.c]的單詞替換成[%.o],返回結果是“x.c.o bar.o”

第22行:foreach,

names := a b c d
files := $(foreach n,$(names),$(n).o)
上面的例子中,$(name)中的單詞會被挨個取出,並存到變量“n”中,“$(n).o”每次
根據“$(n)”計算出一個值,這些值以空格分隔,最後作爲 foreach 函數的返回,所以,
$(files)的值是“a.o b.o c.o d.o”。

shell,

它的參數應該就是操作系統 Shell 的命令,它和反引號“`”是相同的功能。

注意,這個函數會新生成一個 Shell 程序來執行命令,所以你要注意其運行性能,如果你的
Makefile 中有一些比較複雜的規則,並大量使用了這個函數,那麼對於你的系統性能是有
害的。特別是 Makefile 的隱晦的規則可能會讓你的 shell 函數執行的次數比你想像的多得
多。


各個子目錄中的makefile:(關於自動依賴的關鍵點


截取《跟我一起學習makefile》自動生成依賴部分內容:

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

在 Makefile 中, 我們的依賴關係可能會需要包含一系列的頭文件,比如, 如果我們的 main.c中有一句“#include "defs.h"”,那麼我們的依賴關係應該是:

main.o : main.c defs.h


大多數的C/C++編譯器都支持一個“-M”的選項,即自動找尋源文件中包含的頭文件,並生成一個依賴關係。

例如,如果我們執行下面的命令:
cc -M main.c
其輸出是:
main.o : main.c defs.h

於是由編譯器自動生成的依賴關係,這樣一來,你就不必再手動書寫若干文件的依賴關系,而由編譯器自動生成了。

需要提醒一句的是,如果你使用 GNU 的 C/C++編譯器,你得用“-MM”參數,不然,“-M”參數會把一些標準庫

的頭文件也包含進來

gcc -M main.c 的輸出是:

main.o: main.c defs.h /usr/include/stdio.h /usr/include/features.h \
/usr/include/sys/cdefs.h /usr/include/gnu/stubs.h \
/usr/lib/gcc-lib/i486-suse-linux/2.95.3/include/stddef.h \
/usr/include/bits/types.h /usr/include/bits/pthreadtypes.h \
/usr/include/bits/sched.h /usr/include/libio.h \
/usr/include/_G_config.h /usr/include/wchar.h \
/usr/include/bits/wchar.h /usr/include/gconv.h \
/usr/lib/gcc-lib/i486-suse-linux/2.95.3/include/stdarg.h \
/usr/include/bits/stdio_lim.h

gcc -MM main.c 的輸出則是:
main.o: main.c defs.h

我們用的是gcc編譯器所以用參數-MM。

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

取 http://blog.chinaunix.net/uid-20316928-id-3395996.html 部分內容:

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

Makefile如果由其它文件重建(這裏我的Makefile sinclude了所有.d文件,.d也可以看成是一個Makefile),Makefile在讀入所有其他makefile文件(.d)之後,首先將所讀取的每個makefile(.d)作爲一個目標,尋找更新它們的規則.

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

main目錄:



例如:sources = led.c main.c

執行完$(sources:.c=.c)

第7行展開爲:

sinclude led.d main.d

第四行: 由於sources第一個值爲led.c,所以%.o 會自動展開爲led.o,

所以在編譯的時候只會加入led.c所依賴的頭文件。

  將%.o改成main.o,在編譯時候就只會加入main.c中所依賴的頭文件。

將%.o改成led.o main.o ,編譯時候只會加入第一個目標所依賴的頭文件。

 

這就導致瞭如果有多個源文件,且這些源文件包含不同的頭文件,那麼在修改了某些頭文件,也不會生成新的目標文件。



src目錄:


第5行:sinclude,包含source變量中的所有.c文件對應的.d文件.

例如:

test.c則去包含test.d(.d文件也是一個makefile文件,找到.d文件會自動編譯)

當前目錄下找不到.d文件所以在當前makefile中查詢.d文件生成依賴進入7~10行。

第7~10行:(這一段粘貼就好

第8行:將生成的輸出保存在test.d.$$文件中

第9行:生成test.d文件,該文件的內容爲:

src/eat目錄:


第3~4行的內容:如果只是單個文件可以不加,如上圖src目錄下面的makefile,沒有加編譯也可以通過。

插入編譯過程中的截圖:

可以看出每個子目錄都進去了兩次,編譯兩個makefile

第一次執行:當前的makefile

第二次執行:sinclude中的.d文件



最後貼上編譯後的源碼樹:



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