Makefile自動依賴

Makefile自動依賴

 

Makefile生成自動依賴的方法有兩種:

1.  將所有.o文件的依賴關係寫入單獨文件,然後在Makefile中調用該文件

2.  每個.c文件對應一個.d文件,將依賴關係寫入.d文件中

 

 

一、對於第一種方法,Makefile的寫法如下:

#file start

CC = gcc

SRCS := $(wildcard *.c)

OBJS := $(patsubst %.c,%.o, $(SRCS))

 

all: main

 

main: $(OBJS)

        $(CC) -o main $(OBJS)

 

.depend: $(SRCS)

        @$(CC) -MM $(SRCS) > $@

sinclude .depend

 

clean:

        rm -f  *.o .depend main

#file end

 

說明:

(1)       OBJS := $(patsubst %.c,%.o, $(SRCS))

     將$(SRC)中的.c文件列表替換成對應的.o文件,在這裏不能用“*.c”“*.o”來代替,試想在.o文件還不存在的情況下,規則語句“main: $(OBJS)”就會被解析成“main:*.o”,main依賴於“*.o”,“*.o”對應的規則又去哪找呢

(2)       .depend: $(SRCS)

     爲的是.c文件更改時重新生成.depend文件

(3)       @$(CC) -MM $(SRCS) > $@

     行首的”@”符號表示在執行make時不顯示該符號後的shell命令;

     $@:表示當前目標文件,即”.depend”

     假設main.c文件只引用了main.h頭文件,那麼這條命令的輸出結果爲:

         main.o: main.c main.h

(4)       sinclude .depend

     將生成的依賴關係文件引入到當前Makefile。

     Makefile中include的調用方式:

a)  首先在指定的目錄下搜索被調用文件(該例沒有加路徑,則爲當前目錄)

b)  如果沒有找到,則從-I所指定的include目錄查找,如果還沒找到,則從“/usr/gnu/include”“/usr/local/include”等目錄查找

c)  最終結果還是沒找到,則Makefile會試圖尋找匹配規則來生成對應文件,例如本例中的規則爲:

           .depend: $(SRCS)

          @$(CC) -MM $(SRCS) > $@

則根據該規則生成.depend文件。

程序首次編譯時肯定不存在.depend文件,但這是makefile也不需要該文件,因爲首次編譯肯定連接的都是最新文件。也就是說首次編譯時生成的.depend文件其實沒用上,而是留作以後有了改動,比如更改了.h文件中的宏變量,則此時可根據.depend中的依賴關係只生成對應的.o文件了

d)  如果沒有對應規則或其它原因導致生成文件失敗,就要看你用的是include還是sinclude了,兩者的區別:

 

異常

錯誤

include

輸出異常信息(例如首次編譯時找不到.depend文件)

Makefile終止執行(例如找不到匹配規則而無法生成文件)

cinclude

不輸出異常信息

忽略該錯誤,makefile繼續執行

 

(5)      此方法過時?

     很遺憾,在<< GNU make>>手冊中說該方法過時了,原因描述如下:

 

     InGNU make, the feature of remaking makefiles makes this practice obsolete—you need nevertell make explicitly to regenerate the prerequisites, because it always regenerates any makefile that is out of date.

 

     這段話的關鍵句“because it always regenerates any makefile that is out of date”甚是無法理解,要的不就是這種效果麼,有文件更新的話對其進行重新編譯,對的啊,不懂!

     正是由於這個搞不懂的原因纔有了第二種方法

 

二、爲每個.c文件生成對應的.d文件,Makefile寫法如下:

#file start

SOURCES = $(wildcard *.c)

OBJS := $(patsubst %.c,%.o, $(SOURCES))

 

all: main

 

%.d: %.c

        @set -e; rm -f $@; /

        $(CC) -MM  $< > $@.

; /

        sed 's,/($*/)/.o[ :]*,/1.o $@ : ,g' < $@.

> $@; /

        rm -f $@.

 

sinclude $(SOURCES:.c=.d)

 

main:$(OBJS)

        $(CC) -o main $(OBJS)

 

clean:

        rm -f *.o test *.d

#file end

 

上面提到的原因中“you need nevertell make explicitly to regenerate the prerequisites”,其實在這裏也是手動指定的啊:“$(CC) -MM  $< > $@.

”,另外爲每個.c文件都生成.d文件似乎還麻煩了些,沒明白手冊是什麼意思。

貼上main.d文件中的內容:

main.o main.d : main.c main.h

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