2009-11-09 41 views
2

如果foo_user.cpp依賴於foo.h,那麼會創建foo_user.cpp,然後將foo.h的修改時間設置爲過去的更長時間,make將不會重新生成foo_user.cpp(因爲foo.cpp是'newer' )。如果make記錄了依賴關係的修改時間,並且它們完全改變(更新或更舊),那麼我更願意使用它來考慮依賴項的目標是過時的。 GNU可以做到這一點嗎?如果不是,有沒有簡單的選擇?可以'檢查'依賴項的mtime是否不同*運行之間,而不僅僅是比目標更新?

如果您好奇這種情況是如何發生的:foo.h位於符號鏈接的文件夾中。符號鏈接可能指向foolib-1.0文件夾,foolib-2.0文件夾等。當符號鏈接指向不同版本的庫時,即使是較早版本的foo_user.cpp也應該重建。如果我只是將symlinkfolder/foo.h指定爲foo_user.cpp的依賴項,那麼make只關注foo.h的時間戳,而不是通過其訪問foo.h的symlink'd目錄的時間戳。由於make規則是由編譯器生成的,因此我無法將符號鏈接本身作爲依賴項添加(GCC有一個特殊的標誌,當給定的標誌會導致它爲源文件所依賴的所有標題輸出make規則)。

+0

我覺得DigitalRoss是正確的:添加 「foo_user.cpp:symlinkfolder」 到你的makefile(從foo_user.cpp規則獨立)。我測試了這個,它似乎工作(GNUMake 3.81)。 – Beta 2009-11-10 01:34:34

+0

不幸的是,沒有好的自動方法來添加該規則。假設foo.cpp只在symlinkfolder1中使用一個頭,而bar.cpp只在symlinkfolder2中使用一個頭。我不希望每個.cpp文件都依賴於所有可能的符號鏈接文件夾,以避免虛假重建。而且我不想在自己的makefile中維護依賴項,所以我使用編譯器選項讓它生成它們。但是它生成的規則僅指定實際文件,而不指定其包含的文件夾。我可以在生成的規則中搜索包含路徑中文件夾的依賴關係,然後添加文件夾,但速度很慢。 – 2010-01-03 19:53:02

回答

2

不,Make不支持這個。您不妨考慮使用另一種構建系統,如SCons,它不僅僅依賴時間戳,而且實際上計算源文件的MD5哈希值,並將其決定基於哈希值。

從「什麼使SCONS變得更好?」在其網站上:

  • 使用MD5簽名可靠檢測構建變化;可選,可配置的傳統時間戳支持。
+1

我只是想,如果我做了我自己的構建系統,我會這樣做,這真是太棒了。好奇它如何擴展到大型代碼庫。使用boost可以將所需的1,000多個頭文件提供給md5。 – 2009-11-09 21:52:00

+0

如果時間戳*完全相同(默認情況下,您可以根據需要更改此行爲),則SCons不會重新包括散列的文件。 – 2009-11-09 22:00:23

+0

@Greg:嗯......聽起來這種默認行爲可能是爲了防止Joseph感興趣的性能問題。但同時,這種默認行爲不否認使用MD5哈希的主要優點(即不依賴時間戳,從技術上講,不保證內容沒有改變)?打電話給我老式的,但有時候你只能單獨留下足夠的。 – 2009-11-10 02:09:11

3

我試圖理解爲什麼你不能只是添加符號鏈接的相關性。我想象你的自動依賴關係是在一行上,但你可以擁有儘可能多的。

x.o: a.h b.h  
x.o: c.h  
x.o: d.h 

不過話說回來,這很可能是make將統計符號鏈接的目標,而不是符號鏈接本身,因此,不會DTRT。我想你可以在任何時候觸摸一個文件,只要你做的符號鏈接,但我也想你已經想到了...

你可以有一個規則運行ls -id link/. > test,這將把inode號碼的鏈接目標目錄test。您可以然後cmp test save,其中save是從最後一次運行。如果它們不同,你就可以制定規則make clean && make target

targetwrapper: 
    ls -id link/. > test 
    cmp test save || make clean 
    make realtarget 
    cp test save 

clean: 
    echo cleaned 

realtarget: 
    echo made 
+0

「我不能將符號鏈接本身添加爲依賴項,因爲make規則是由編譯器生成的(GCC有一個特殊的標誌,當給定的標誌會導致它爲源文件所依賴的所有標題輸出make規則)。 「 < - 不清楚,或者你只是想念它? ;) – 2009-11-09 21:48:19

+0

我仍然不明白爲什麼你不能*添加*依賴項,即使這個規則是自動生成的,但我會接受你的話。 – DigitalRoss 2009-11-09 21:50:15

+2

依賴和規則不需要在同一行上... – DigitalRoss 2009-11-09 21:50:46

1

雖然make不支持開箱即用,但您可以對其進行編程。

include more_deps 

ifneq ($(MAKE_RESTARTS),) 

more_deps: 
    if (foolink.old differs from what foolink points to) ; then \ 
    readlink foolink > foolink.old ; \ 
    echo "foo_user: foolink_trigger" > more_deps ; \ 
    touch foolink_trigger ; \ 
    else \ 
    echo "" > more_deps ;\ 
    fi 

endif 

foo_user: foo_user.cpp 
    g++ $^ -o [email protected] 

在這裏,你的makefile包括其more_deps有時包括符號鏈接的觸發器的依賴。觸發是一個特殊的中間過程,所有有意義的信息都是其時間戳。當符號鏈接更改時,觸發器的時間戳更新爲當前時間(請參見touch),從而使foo_user過期並重建。

includeMAKE_RESTARTS在計算上述依賴關係之後需要重新啓動make。如果包含的makefile是目標本身,則目標被認爲是重建,重建,然後重新啓動並重新讀取makefile。但是當它第二次讀取makefile時,它看不到more_deps作爲目標,因爲MAKE_RESTARTS變量擴展爲非空字符串。

事實上,如果能聽起來像這樣的行:

more_deps: 
    if (any condition you want with $(VARIABLES) possible!) ; then \ 
    update a file that holds the previous state ;\ 
    ... 
+0

這似乎是一個強大的技術,但我認爲它需要拋光。它會永遠做更多_deps?是否需要「其他」聲明? – Beta 2009-11-10 15:58:03

+0

它確實需要拋光,測試版,但似乎只有你和我關心:-( – 2009-11-10 16:51:15

+0

記住瘋狂科學家的馬克西姆:*「愚人!有一天我會摧毀他們!」*如果如果(condition)
target:update
endif where update is PHONY?Small if statement,and no inclusion needed。 – Beta 2009-11-10 18:09:09

0

通過這過程你改變符號鏈接?您可以將make clean類型的操作添加到更改符號鏈接的腳本中。

你也可以設置與你讓讓複製你的頭文件,其中複製的頭文件依賴於原來的和符號鏈接一個「頭工作文件夾」。 GCC生成的依賴關係只考慮工作標題,不會與您的Makefile的copy headers into the working folder部分發生衝突。

相關問題