八、自動生成依賴性
在makefile中,我們的依賴關係可能會需要包含一系列的標頭檔案,比如,如果我們的main.c中有一句「#include "defs.h"」,那麼我們的依賴關係應該是:
main.o : main.c defs.h
但是,如果是乙個比較大型的工程,你必需清楚哪些c檔案包含了哪些標頭檔案,並且,你在加入或刪除標頭檔案時,也需要小心地修改makefile,這是乙個很沒有維護性的工作。為了避免這種繁重而又容易出錯的事情,我們可以使用c/c++編譯的乙個功能。大多數的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
那麼,編譯器的這個功能如何與我們的makefile聯絡在一起呢。因為這樣一來,我們的makefile也要根據這些原始檔重新生成,讓makefile自已依賴於原始檔?這個功能並不現實,不過我們可以有其它手段來迂迴地實現這一功能。gnu組織建議把編譯器為每乙個原始檔的自動生成的依賴關係放到乙個檔案中,為每乙個「name.c」的檔案都生成乙個「name.d」的makefile檔案,[.d]檔案中就存放對應[.c]檔案的依賴關係。
於是,我們可以寫出[.c]檔案和[.d]檔案的依賴關係,並讓make自動更新或自成[.d]檔案,並把其包含在我們的主makefile中,這樣,我們就可以自動化地生成每個檔案的依賴關係了。
這裡,我們給出了乙個模式規則來產生[.d]檔案:
%.d: %.c
@set -e; rm -f $@; /
$(cc) -m $(cppflags) $< > $@.
; /sed 's,/($*/)/.o[ :]*,/1.o $@ : ,g' < $@.
> $@; /
rm -f $@.
這個規則的意思是,所有的[.d]檔案依賴於[.c]檔案,「rm -f $@」的意思是刪除所有的目標,也就是[.d]檔案,第二行的意思是,為每個依賴檔案「$<」,也就是[.c]檔案生成依賴檔案,「$@」表示模式「%.d」檔案,如果有乙個c檔案是name.c,那麼「%」就是「name」,「
」意為乙個隨機編號,第二行生成的檔案有可能是「name.d.12345」,第三行使用sed命令做了乙個替換,關於sed命令的用法請參看相關的使用文件。第四行就是刪除臨時檔案。
總而言之,這個模式要做的事就是在編譯器生成的依賴關係中加入[.d]檔案的依賴,即把依賴關係:
main.o : main.c defs.h
轉成:main.o main.d : main.c defs.h
於是,我們的[.d]檔案也會自動更新了,並會自動生成了,當然,你還可以在這個[.d]檔案中加入的不只是依賴關係,包括生成的命令也可一併加入,讓每個[.d]檔案都包含乙個完賴的規則。一旦我們完成這個工作,接下來,我們就要把這些自動生成的規則放進我們的主makefile中。我們可以使用makefile的「include」命令,來引入別的makefile檔案(前面講過),例如:
sources = foo.c bar.c
include $(sources:.c=.d)
上述語句中的「$(sources:.c=.d)」中的「.c=.d」的意思是做乙個替換,把變數$(sources)所有[.c]的字串都替換成[.d],關於這個「替換」的內容,在後面我會有更為詳細的講述。當然,你得注意次序,因為include是按次來載入檔案,最先載入的[.d]檔案中的目標會成為預設目標。
linux makefile檔案分析
cflags wall wstrict prototypes g fomit frame pointer ffreestanding all crt0.s leds.c arm linux gcc cflags c o crt0.o crt0.s arm linux gcc cflags c o l...
Linux Makefile由淺入深剖析
經過長時間學習linux makefile,於是和大家分享一下,看完本文你肯定有不少收穫,希望本文能教會你更多東西。假設我們有乙個程式由5個檔案組成,源 如下 main.c include mytool1.h include mytool2.h int main mytool1.c include ...
Linux Makefile簡單介紹
c exe linux 中 編譯器 gcc和g 預處理 e 彙編 s 編譯 c 鏈結 o hello gcc e hello.c o hello.i hello ls hello.c hello.i 來看一下hello.i的內容 巨集定義在與處理的時候就展開了 hello gcc s hello.i...