phony-target makefile語法 - .PHONY在makefile中的用途是什麼?




@用法 makefile教學 (7)

還有一個重要的棘手對待“鳳凰” - 當一個物理目標取決於假目標取決於另一個物理目標:

TARGET1 - > PHONY_FORWARDER1 - > PHONY_FORWARDER2 - > TARGET2

如果你更新了TARGET2,那麼你應該認為TARGET1應該被認為是針對TARGET1的,因此TARGET1應該被重建。 它真的是這樣

棘手的部分是,當TARGET2對TARGET1 沒有陳舊時 - 在這種情況下,你應該期望TARGET1不應該被重建。

這令人驚訝地不起作用,因為: 虛假目標無論如何都是運行的(就像虛假目標通常那樣) ,這意味著虛假目標被認為是更新的 。 並且因為TARGET1被認為是針對虛假目標的陳舊觀點

考慮:

all: fileall

fileall: file2 filefwd
    echo file2 file1 >fileall


file2: file2.src
    echo file2.src >file2

file1: file1.src
    echo file1.src >file1
    echo file1.src >>file1

.PHONY: filefwd
.PHONY: filefwd2

filefwd: filefwd2

filefwd2: file1
    @echo "Produced target file1"


prepare:
    echo "Some text 1" >> file1.src
    echo "Some text 2" >> file2.src

你可以玩這個:

  • 首先做“準備”來準備“源文件”
  • 通過觸摸特定文件來查看它們的更新情況

你可以看到fileall通過偽目標間接依賴於file1 - 但由於這種依賴關係,它總是被重建。 如果您將fileall的依賴關係從filefwdfile ,那麼現在fileall都不會重建fileall ,但只有當任何依賴目標對文件作為文件陳舊時才會重新生成。

.PHONY在Makefile中意味著什麼? 我已經經歷了this ,但它太複雜了。

有人可以用簡單的語言向我解釋嗎?


它是一個不是文件名的構建目標。


假設你已經install目標,這在makefile中很常見。 如果您使用.PHONY ,並且名為install的文件與Makefile位於同一目錄中,則make install將不會執行任何操作 。 這是因為Make將規則解釋為“執行這樣的配方來創建名為install的文件”。 由於該文件已經存在,並且其依賴關係沒有改變,所以不會做任何事情。

但是,如果您將install目標設為PHONY,它會告訴make工具該目標是虛構的,並且該make不應該期望它創建實際的文件。 因此它不會檢查install文件是否存在,這意味著:a)如果文件存在並且b)不會調用額外的stat()則其行為不會被改變。

通常,Makefile中不生成與目標名稱同名的輸出文件的所有目標應該是PHONY。 這通常包括allinstallcleandistclean等。


默認情況下,Makefile目標是“文件目標” - 它們用於從其他文件構建文件。 假定它的目標是一個文件,這使得編寫Makefiles變得相對容易:

foo: bar
  create_one_from_the_other foo bar

但是,有時您希望Makefile運行不代表文件系統中物理文件的命令。 很好的例子是“乾淨”和“全部”的共同目標。 有可能情況並非如此,但是您的主目錄中可能會有一個名為clean的文件。 在這種情況下,Make會被混淆,因為默認情況下, clean目標將與該文件相關聯,並且Make只會在文件看起來與它的依賴關係不是最新的時候才運行。

這些特殊的目標被稱為 ,你可以明確地告訴他們沒有與文件關聯,例如:

.PHONY: clean
clean:
  rm -rf *.o

現在,即使您有一個名為clean的文件, make clean也會按預期運行。

就Make而言,假目標只是一個總是過時的目標,所以無論何時你問make <phony_target> ,目標都會運行,與文件系統的狀態無關。 一些常見偽造目標通常是假的: allinstallcleandistcleanTAGSinfocheck

欲了解更多信息,這裡有一個很好的教程解釋它。


注意 :make工具讀取makefile並檢查規則中':'符號兩側文件的修改時間戳。

在“測試”目錄中存在以下文件:

[email protected]:~/test$ ls
hello  hello.c  makefile

在makefile中,規則定義如下:

hello:hello.c
    cc hello.c -o hello

現在假定文件'hello'是一個包含一些數據的文本文件,它是在'hello.c'文件之後創建的。 所以'hello'的修改(或創建)時間戳將比'hello.c'更新。 所以當我們從命令行調用'make hello'時,它會打印為:

make: `hello' is up to date.

現在訪問'hello.c'文件並在其中放入一些空格,這不會影響代碼語法或邏輯,然後保存並退出。 現在hello.c的修改時間戳比'hello'更新。 現在,如果您調用'make hello',它將執行以下命令:

cc hello.c -o hello

並且文件'hello'(文本文件)將被新的二進製文件'hello'覆蓋(上面編譯命令的結果)。

如果我們在makefile中使用.PHONY,如下所示:

.PHONY:hello

hello:hello.c
    cc hello.c -o hello

然後調用'make hello',它會忽略pwd中存在的任何名為'hello'的文件並每次執行該命令。

現在假設makefile中沒有目標依賴關係:

hello:
    cc hello.c -o hello

並且'hello'文件已經存在於pwd'test'中,那麼'make hello'將始終顯示為:

make: `hello' is up to date.

最好的解釋是GNU make手冊本身: 4.6 Phony Targets部分

.PHONY是make的特殊內置目標名稱之一 。 還有其他你可能感興趣的目標,所以值得瀏覽這些參考資料。

當需要考慮一個.PHONY目標時,make會無條件地運行它的配方,不管這個名稱的文件是否存在,或者它的最後修改時間是什麼。

你也可能對make的標準目標感興趣,比如allclean


這是patch生成的錯誤。 如果你打開.patch文件,你會看到它被組織成一堆段,即所謂的“帥哥”。 每個塊都標識舊版本和新版本中相應的代碼片段(按行號),這些代碼片段之間的差異以及它們之間的相似性(“上下文”)。

如果大塊的相似性與原始文件中的相似性,則大塊可能會失敗。 當您看到此錯誤時,幾乎總是因為您正在使用補丁來修補您正在修補的錯誤版本的代碼。 有幾種方法可以解決這個問題:

  • 獲取已包含補丁(最佳選項)的libdvdnav的更新版本。
  • 獲取正在修補的libdvdnav版本的.patch文件。
  • 手動修補。 對於補丁中的每個塊,嘗試在libdvdnav找到相應的文件和行,並根據補丁中的說明進行更正。
  • 採用更接近.patch文件所針對的任何版本的libdvdnav版本(可能是一個壞主意)。




makefile phony-target