簡體   English   中英

Makefile 依賴項不適用於假目標

[英]Makefile dependencies don't work for phony target

這是我的 Makefile 的簡化版本:

.PHONY: all 

all: src/server.coffee
  mkdir -p bin
  ./node_modules/.bin/coffee -c -o bin src/server.coffee

我想運行make並且只在src/server.coffee更改時重新編譯它。 但是,每次我運行make時它都會重新編譯:

$ make
mkdir -p bin
./node_modules/.bin/coffee -c -o bin src/server.coffee
$ make
mkdir -p bin
./node_modules/.bin/coffee -c -o bin src/server.coffee

如果我將 Makefile 更改為不使用虛假目標,它會按預期工作。 新的生成文件:

bin/server.js: src/server.coffee
  mkdir -p bin
  ./node_modules/.bin/coffee -c -o bin src/server.coffee

結果:

$ make
mkdir -p bin
./node_modules/.bin/coffee -c -o bin src/server.coffee
$ make
make: `bin/server.js' is up to date.

為什么它不尊重我對虛假目標的依賴? 我問的原因是因為實際上,我不會只是將單個文件編譯成另一個文件,所以我不想跟蹤所有輸出文件的名稱以用作目標。

而不是一個虛假的目標(正如@cmotley 指出的那樣,它正在正常工作)當你想避免額外工作時你可能使用的是一個“空目標”

空目標是假目標的變體; 它用於保存您不時明確請求的操作的配方。 與虛假目標不同,這個目標文件可以真實存在; 但文件的內容無關緊要,通常是空的。

空目標文件的目的是記錄最后一次執行規則配方的時間及其最后修改時間。 這樣做是因為配方中的命令之一是用於更新目標文件的觸摸命令。

然而,在這種情況下,實際上不需要添加額外的空輸出文件——您已經有了 CoffeeScript 編譯的輸出,這符合更典型的 Makefile 模式。 正如您在問題中已經證明的那樣:您可以做的是重構這種方法:

.PHONY: all
all: bin/server.js

bin/server.js: src/server.coffee
  mkdir -p bin
  ./node_modules/.bin/coffee -c -o bin src/server.coffee

現在你擁有了你想要的兩樣東西:一個很好的傳統“全部”目標,它是正確的虛假目標,以及一個不會做額外工作的構建規則。 您也可以更好地使其更通用,以便您可以輕松添加更多文件:

.PHONY: all
all: bin/server.js bin/other1.js bin/other2.js

bin/%.js: src/%.coffee
  mkdir -p bin
  ./node_modules/.bin/coffee -c -o bin $<

根據 Make 文檔:

The prerequisites of the special target .PHONY are considered
to be phony targets. When it is time to consider such a target, 
make will run its recipe unconditionally, regardless of whether 
a file with that name exists or what its last-modification time is.

http://www.gnu.org/software/make/manual/html_node/Special-Targets.html

Make 無條件地運行 PHONY 目標的配方 - 先決條件無關緊要。

需要有一些目標文件來與 server.coffee 文件的修改時間進行比較。 由於您沒有具體的目標, make無法知道輸出是否比依賴項更新,因此它將始終構建all .

正如其他人提到的那樣,make 查看文件的時間戳以確定依賴項是否已更改。

如果你想“模擬”一個具有依賴性的假目標,你將不得不創建一個具有該名稱的真實文件並使用touch命令(在 Unix 系統上)。

我需要一個解決方案來僅在 makefile 被更改時才清理目錄(即編譯器標志被更改,因此需要重新編譯目標文件)。

這是我使用(並在每次編譯之前運行)一個名為makefile_clean的文件:

makefile_clean: makefile
    @rm '*.o'
    @sudo touch makefile_clean

touch命令將最后修改的時間戳更新為當前時間。

謝謝@anonymous-penguin,但在我看來,將那些無用的文件(只是一個標志)放在文件夾/tmp中是一個更好的主意。

這是 makefile,當且僅當文件Dockerfile發生更改時,它才會構建 docker 鏡像。

# Configable variable
BUILD_FLAG_FILE = /tmp/ACMHomepage/Dockerfile_builded

# State variable
REBUILD = false

.PHONY: build
build: $(BUILD_FLAG_FILE)

$(BUILD_FLAG_FILE): Dockerfile
    $(eval REBUILD = true)
    @echo "Build image $(DB_NAME)..."
    @docker build -t $(DB_NAME) .
    @mkdir -p $(dir $(BUILD_FLAG_FILE))
    @touch $(BUILD_FLAG_FILE)

如您所見,它將在/tmp/ACMHomepage/Dockerfile_builded中創建一個空文件作為標志。 如果構建了 docker 鏡像,則變量REBUILD將為true ,這很有用!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM