簡體   English   中英

如何強制生成文件重建目標?

[英]How do you force a makefile to rebuild a target?

我有一個生成文件,然后調用另一個生成文件。 由於這個 makefile 調用了更多的 makefile 來完成工作,所以它並沒有真正改變。 因此,它一直認為該項目已構建並且是最新的。

dnetdev11 ~ # make
make: `release' is up to date.

如何強制生成文件重建目標?

clean = $(MAKE) -f ~/xxx/xxx_compile.workspace.mak clean


build = svn up ~/xxx                                                       \
        $(clean)                                                                \
        ~/cbp2mak/cbp2mak -C ~/xxx ~/xxx/xxx_compile.workspace        \
        $(MAKE) -f ~/xxx/xxx_compile.workspace.mak $(1)                    \


release:
        $(build )

debug:
        $(build DEBUG=1)

clean:
        $(clean)

install:
        cp ~/xxx/source/xxx_utility/release/xxx_util /usr/local/bin
        cp ~/xxx/source/xxx_utility/release/xxxcore.so /usr/local/lib

注:刪除姓名以保護無辜者

最終固定版本:

clean = $(MAKE) -f xxx_compile.workspace.mak clean;


build = svn up;                                         \
        $(clean)                                        \
        ./cbp2mak/cbp2mak -C . xxx_compile.workspace;   \
        $(MAKE) -f xxx_compile.workspace.mak    $(1);   \


.PHONY: release debug clean install

release:
        $(call build,)

debug:
        $(call build,DEBUG=1)

clean:
        $(clean)

install:
        cp ./source/xxx_utillity/release/xxx_util /usr/bin
        cp ./dlls/Release/xxxcore.so /usr/lib

用於 make 的-B開關,其長格式為--always-make ,告訴make忽略時間戳並制作指定的目標。 這可能會違背使用 make 的目的,但它可能正是您所需要的。

您可以將一個或多個目標聲明為phony

虛假目標不是真正的文件名; 相反,它只是在您提出明確請求時要執行的配方的名稱。 使用虛假目標有兩個原因:避免與同名文件發生沖突,以及提高性能。

...

虛假目標不應成為真實目標文件的先決條件; 如果是,則每次 make 更新該文件時都會運行它的配方。 只要虛假目標永遠不是真實目標的先決條件,虛假目標配方將僅在虛假目標是指定目標時執行

其他人建議使用 .PHONY,這絕對是正確的。 .PHONY 應用於輸入和輸出之間的日期比較無效的任何規則。 由於您沒有表單output: input任何目標,您應該對所有這些目標使用 .PHONY!

綜上所述,您可能應該在 makefile 的頂部為各種文件名定義一些變量,並定義具有輸入和輸出部分的真正 make 規則,以便您可以利用 make 的好處,即您只會實際編譯需要 copmile 的東西!

編輯:添加示例。 未經測試,但這就是你的方式 .PHONY

.PHONY: clean    
clean:
    $(clean)

所用的太陽手冊加以記錄一招make是使用(不存在)目標“.FORCE”。 您可以通過創建一個文件 force.mk 來做到這一點,其中包含:

.FORCE:
$(FORCE_DEPS): .FORCE

然后,假設您現有的 makefile 被稱為makefile ,您可以運行:

make FORCE_DEPS=release -f force.mk -f makefile release

由於.FORCE不存在,任何依賴於它的東西都將過時並重建。

所有這些都適用於任何版本的make 在 Linux 上,您擁有 GNU Make,因此可以使用所討論的 .PHONY 目標。

同樣值得考慮的是為什么make認為 release 是最新的。 這可能是因為您在執行的命令中有一個touch release命令; 這可能是因為有一個名為“release”的文件或目錄存在並且沒有依賴關系,因此是最新的。 那么真正的原因就...

如果我沒記錯的話,'make' 使用時間戳(文件修改時間)來確定目標是否是最新的。 強制重新構建的常用方法是使用“touch”命令更新該時間戳。 您可以嘗試在 makefile 中調用 'touch' 來更新目標之一(可能是這些子 makefile 之一)的時間戳,這可能會強制 Make 執行該命令。

這種簡單的技術將允許 makefile 在不需要強制時正常運行。 makefile的末尾創建一個名為force的新目標。 force目標將觸及您的默認目標所依賴的文件。 在下面的示例中,我添加了touch myprogram.cpp 我還添加了一個遞歸調用make 這將導致每次鍵入make force時都會生成默認目標。

yourProgram: yourProgram.cpp
       g++ -o yourProgram yourProgram.cpp 

force:
       touch yourProgram.cpp
       make

我試過了,它對我有用

將這些行添加到 Makefile

clean:
    rm *.o output

new: clean
    $(MAKE)     #use variable $(MAKE) instead of make to get recursive make calls

保存並立即調用

make new 

它將再次重新編譯所有內容

發生了什么?

1) 'new' 調用干凈。 'clean' do 'rm' 刪除所有擴展名為 '.o' 的目標文件。

2) 'new' 調用 'make'。 'make' 看到沒有 '.o' 文件,所以它再次創建所有的 '.o' 文件。 然后鏈接器將所有 .o 文件鏈接到一個可執行輸出

祝你好運

make clean刪除所有已編譯的目標文件。

如果您不需要保留已成功編譯的任何輸出

nmake /A 

重建所有

根據米勒的遞歸生成被認為有害,您應該避免調用$(MAKE) 在你展示的情況下,它是無害的,因為這不是一個真正的 makefile,只是一個包裝腳本,它也可能是用 Shell 編寫的。 但是你說你在更深的遞歸層次上繼續這樣,所以你可能遇到了那篇令人大開眼界的文章中顯示的問題。

當然,使用 GNU 使其避免起來很麻煩。 盡管他們意識到了這個問題,但這是他們記錄在案的做事方式。

OTOH, makepp就是為了解決這個問題而創建的。 您可以在每個目錄級別上編寫您的 makefile,但它們都被整合到您的項目的完整視圖中。

但是遺留的 makefile 是遞歸編寫的。 因此,有一種解決方法,其中$(MAKE)只會將子請求引導回主 makepp 進程。 只有當你在你的子制作之間做多余的或者更糟糕的事情時,你必須請求--traditional-recursive-make (這當然打破了 makepp 的這個優勢)。 我不知道你的其他 makefile,但如果它們寫得很干凈,makepp 必要的重建應該會自動發生,而不需要其他人在這里建議的任何黑客。

已經提到過,但我想我可以添加到使用touch

如果touch所有要編譯的源文件,則touch命令會將文件的時間戳更改為執行touch命令的系統時間。

源文件 timstamp 是make用來“知道”文件已更改,需要重新編譯的文件

例如:如果項目是一個c++項目,那么做touch *.cpp ,然后再次運行make ,並且 make 應該重新編譯整個項目。

正如 abernier 所指出的,GNU make 手冊中有一個推薦的解決方案,它使用“假”目標來強制重建目標:

clean: FORCE
        rm $(objects)
FORCE: ; 

無論任何其他依賴項如何,這都會干凈地運行。

我在手冊中的解決方案中添加了分號,否則需要一個空行。

這實際上取決於目標是什么。 如果它是一個虛假目標(即目標與文件無關),您應該將其聲明為 .PHONY。

但是,如果目標不是虛假目標,而您只是出於某種原因想重建它(例如,當您使用 __TIME__ 預處理宏時),則應使用此處的答案中描述的 FORCE 方案。

在我的 Linux 系統 (Centos 6.2) 上,聲明目標 .PHONY 和創建對 FORCE 的假依賴之間存在顯着差異,而規則實際上確實創建了與目標匹配的文件。 當每次都必須重新生成文件時,它需要文件的假依賴 FORCE 和假依賴的 .PHONY。

錯誤的:

date > $@

對:

FORCE
    date > $@
FORCE:
    .PHONY: FORCE

暫無
暫無

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

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