1. 程式人生 > >Makefile偽目標詳解

Makefile偽目標詳解

本節我們討論一個Makefile中的一個重要的特殊目標:偽目標。

偽目標是這樣一個目標:它不代表一個真正的檔名,在執行make時可以指定這個目標來執行其所在規則定義的命令,有時我們也可以將一個偽目標稱為標籤。使用偽目標有兩點原因:1. 避免在我們的Makefile中定義的只執行命令的的目標(此目標的目的為了執行執行一列命令,而不需要建立這個目標)和工作目錄下的實際檔案出現名字衝突。2. 提高執行make時的效率,特別是對於一個大型的工程來說,編譯的效率也許你同樣關心。以下就這兩個問題我們進行分析討論:

1. 如果我們需要書寫這樣一個規則:規則所定義的命令不是去建立目標檔案,而是使用make指定具體的目標來執一些特定的命令。像下邊那樣:

clean: 

rm *.o temp 

規則中rm不是建立檔案clean的命令,只是刪除當前目錄下的所有.o檔案和temp檔案。在工作目錄下不存在clean這個檔案時,我們輸入make clean後,rm *.o temp總會被執行。這是我們的初衷。

但當前工作目錄下存在檔案clean時情況就不一樣了,在我們輸入make clean時。規則沒有依賴檔案,所以目標被認為是最新的而不去執行規則作定義的命令,命令rm將不會被執行。這並不是我們的初衷。為了避免這個問題,我們可以將目標clean明確的宣告為偽目標。將一個目標宣告為偽目標需要將它作為特殊目標.PHONY

的依賴。如下:

.PHONY : clean 

這樣目標clean就是一個偽目標,無論當前目錄下是否存在clean這個檔案。我們輸入make clean之後。rm命令都會被執行。而且,當一個目標被宣告為偽目標後,make在執行此規則時不會試圖去查詢隱含規則來建立這個目標。這樣也提高了make的執行效率,同時我們也不用擔心由於目標和檔名重名而使我們的期望失敗。在書寫偽目標規則時,首先需要宣告目標是一個偽目標,之後才是偽目標的規則定義。目標clean書寫格式應該如下:

.PHONY: clean 

clean: 

rm *.o temp 

2. 偽目標的另外一使用場合在make

的並行和遞迴執行過程中。此情況下一般存在一個變數,其定義為所有需要make的子目錄。對多個目錄進行make的實現方式可以在一個規則中可以使用shell的迴圈來完成。如下:

SUBDIRS = foo bar baz 

subdirs: 

for dir in $(SUBDIRS); do \ 

$(MAKE) -C $$dir; \ 

done 

但這種實現方法存在以下幾個問題。1. 當子目錄執行make出現錯誤時,make不會退出。就是說,在對某一個目錄執行make失敗以後,會繼續對其他的目錄進行make。在最終執行失敗的情況下,我們很難根據錯誤的提示定位出具體是是那個目錄下的Makefile出現錯誤。這給問題定位造成了很大的困難。為了避免這樣的問題,我們可以在命令列部分加入錯誤的監測,在命令執行錯誤後make退出。不幸的是,如果在執行make時使用了-k選項,此方式將失效。2. 外一個問題就是使用這種shell的迴圈方式時,沒有用到make對目錄的並行處理功能,因為規則的命令是一條完整的shell命令,不能被並行的執行。

我們可以通過偽目標方式來克服以上實現方式所存在的兩個問題。

SUBDIRS = foo bar baz 

.PHONY: subdirs $(SUBDIRS) 

subdirs: $(SUBDIRS) 

$(SUBDIRS): 

$(MAKE) -C [email protected] 

foo: baz 

上邊的實現中使用了一個沒有命令列的規則foo: baz,用來限制子目錄的make順序。此規則的含義時在處理foo目錄之前,需要等待baz目錄處理完成。在書寫一個並行執行makeMakefile時,目錄的處理順序是需要特別注意的。

一般情況下,一個偽目標不作為一個另外一個目標檔案的依賴。這是因為當一個目標檔案的依賴包含偽目標時,每一次在執行這個規則時偽目標所定義的命令都會被執行(因為它是規則的依賴,重建規則目標檔案時需要首先重建它的依賴)。當偽目標沒有作為任何目標(此目標是一個可被建立或者已存在的檔案)的依賴時,我們只能通過make的命令列選項明確指定這個偽目標,來執行它所定義的命令。例如我們的make clean

Makefile中,偽目標可以有自己的依賴。在一個目錄下如果需要建立多個可執行程式,我們可以將所有程式的重建規則在一個Makefile中描述。因為Makefile中第一個目標是終極目標,約定的做法是使用一個稱為all的偽目標來作為終極目標,它的依賴檔案就是那些需要建立的程式。下邊就是一個例子:

#sample Makefile 

all : prog1 prog2 prog3 

.PHONY : all 

prog1 : prog1.o utils.o 

cc -o prog1 prog1.o utils.o 

prog2 : prog2.o 

cc -o prog2 prog2.o 

prog3 : prog3.o sort.o utils.o 

cc -o prog3 prog3.o sort.o utils.o 

執行make時,目標all被作為終極目標。為了完成對它的更新,make會建立(不存在)或者重建(已存在)目標all的所有依賴檔案(prog1prog2prog3)。當需要單獨更新某一個程式時,我們可以通過make的命令列選項來明確指定需要重建的程式。(例如: “make prog1)。當一個偽目標作為另外一個偽目標依賴時,make將其作為另外一個偽目標的子例程來處理(可以這樣理解:其作為另外一個偽目標的必須執行的部分,就行C語言中的函式呼叫一樣)。下邊的例子就是這種用法:

.PHONY: cleanall cleanobj cleandiff 

cleanall : cleanobj cleandiff 

rm program 

cleanobj : 

rm *.o 

cleandiff : 

rm *.diff 

cleanobjcleandiff這兩個偽目標有點像子程式的意思(執行目標clearall時會觸發它們所定義的命令被執行)。我們可以輸入make cleanallmake cleanobjmake cleandiff命令來達到清除不同種類檔案的目的。例子首先通過特殊目標.PHONY聲明瞭多個偽目標,它們之間使用空各分割,之後才是各個偽目標的規則定義。

說明:

通常在清除檔案的偽目標所定義的命令中rm使用選項–f--force)來防止在缺少刪除檔案時出錯並退出,使make clean過程失敗。也可以在rm之前加上-來防止rm錯誤退出,這種方式時make會提示錯誤資訊但不會退出。為了不看到這些討厭的資訊,需要使用上述的第一種方式。

另外make存在一個內嵌隱含變數RM,它被定義為:RM = rm –f。因此在書寫clean規則的命令列時可以使用變數$(RM)來代替rm,這樣可以免出現一些不必要的麻煩!這是我們推薦的用法。

Refer: http://www.cnblogs.com/hnrainll/archive/2011/04/12/2014082.html


相關推薦

Makefile目標

本節我們討論一個Makefile中的一個重要的特殊目標:偽目標。 偽目標是這樣一個目標:它不代表一個真正的檔名,在執行make時可以指定這個目標來執行其所在規則定義的命令,有時我們也可以將一個偽目標稱為標籤。使用偽目標有兩點原因:1. 避免在我們的Makefile中定義的

Makefile目標

而是 一次 我們 避免 並行 重名 理解 目標 完整   本節我們討論一個Makefile中的一個重要的特殊目標:偽目標。 偽目標是這樣一個目標:它不代表一個真正的文件名,在執行make時可以指定這個目標來執行其所在規則定義的命令,有時我們也可以將一個偽目標稱為標簽。使用

自動生成Makefile的全過程

change make auto osc .cn 轉換成 otto 創建 準備 一、簡介 Linux下的程序開發人員,一定都遇到過Makefile,用make命令來編譯自己寫的程序確實是很方便。一般情況下,大家都是手工寫一個簡單Makefile,如果要想寫出一個符合自由軟件

css中類/元素

input 其他 中文 tro 網頁 單元 web link 語言 一、偽類和偽元素 偽類和偽元素都是用來修飾不在文檔樹中的部分,區別在於, 偽類用於當已有元素處於的某個狀態時,為其添加對應的樣式,這個狀態是根據用戶行為而動態變化的(如:hover/:active)。

Makefile概述及

Makefile 值得一提的是,在Makefile中的命令,必須要以[Tab]鍵開始。       什麼是makefile?或許很多Winodws的程式設計師都不知道這個東西,因為那些Windows的IDE都為你做了這個工作,但我覺得要作一個好的和pr

CSS元素

CSS選擇器大致可以分成5類:基本選擇器,層次選擇器,屬性選擇器,偽類,偽元素。基本,層次,屬性選擇器比較容易理解,畢竟它們選擇的物件都屬於DOM中看得見摸得著的元素。但偽類和偽元素相對比較抽象,稍微有一點點理解上的難度。本篇就是我對偽類和偽元素的理解。 先介紹一下偽類和偽元素有什麼區別?其

makefile目標理解

makefile偽目標控制子makefile執行 下面的makefile耽誤了我半天時間,我要紀念下 程式碼塊 程式碼塊語法遵循標準markdown程式碼,例如: SUBDIRS =bin

Makefile 目標.PHONY

在接觸Makefile的時候,我們經常會看到.PHONY標記,它就是偽目標,所謂偽目標,就是指沒有真正的檔案和它對應,只是一個標識而已。make程式看到.PHONY後面的目標後就會去執行對應的命令。例如

MAKEFILE目標 靜態模式 十三

六、多目標 Makefile的規則中的目標可以不止一個,其支援多目標,有可能我們的多個目標同時依賴於一個檔案,並且其生成的命令大體類似。於是我們就能把其合併起來。當然,多個目標的生成規則的執行命令是同一個,這可能會可我們帶來麻煩,不過好在我們的可以使用一個自動化變數“[email protected

makefile 多行變數 環境變數 目標變數 模式變數 十九

六、多行變數   還有一種設定變數值的方法是使用define關鍵字。使用define關鍵字設定變數的值可以有換行,這有利於定義一系列的命令(前面我們講過“命令包”的技術就是利用這個關鍵字)。 define指示符後面跟的是變數的名字,而重起一行定義變數的值,定義是以endef關鍵字結束。其工作方式和“=”操作符

makefile學習之路——目標

偽目標 makefile 由於在makefile中,make在默認情況下將目標當作是一個文件來處理,所以這裏就會出現一個情況,如果makefile中的目標是實際已經存在的文件,那麽,我們在使用makefile的時候,就會報錯。為了避免這種情況的出現,就引入了偽目標的概念。 引

makefile

makefile原文鏈接:https://blog.csdn.net/qq_38646470/article/details/79917494專欄鏈接:https://blog.csdn.net/column/details/20028.html    或許很多Wino

Faster R-CNN:目標檢測的實現過程

最大的 中心 width 小數據 等等 eat tar 優先 博文 本文詳細解釋了 Faster R-CNN 的網絡架構和工作流,一步步帶領讀者理解目標檢測的工作原理,作者本人也提供了 Luminoth 實現,供大家參考。 Luminoth 實現:h

Hadoop分佈安裝+MapReduce執行原理+基於MapReduce的KNN演算法實現

本篇部落格將圍繞Hadoop偽分佈安裝+MapReduce執行原理+基於MapReduce的KNN演算法實現這三個方面進行敘述。 (一)Hadoop偽分佈安裝 1、簡述Hadoop的安裝模式中–偽分佈模式與叢集模式的區別與聯絡. Hadoop的安裝方式有三種:本地模式,偽分佈模式

(二十二)訪問者模式動態雙分派)

 作者:zuoxiaolong8810(左瀟龍),轉載請註明出處,特別說明:本博文來自博主原部落格,為保證新部落格中博文的完整性,特複製到此留存,如需轉載請註明新部落格地址即可。               本次LZ

Hadoop單機式分散式安裝

Ubuntu、centos7、6叢集搭建:https://blog.csdn.net/qq_40938267/article/details/83476896 遇到的問題以及解決方法: 1.在./bin/hdfs namenode –format時 載入不出class  檢視配置的

Linux下多資料夾編寫Makefile

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

基於Tensorflow的目標檢測(Detection)的程式碼案例

這篇博文我主要闡述了基於Tensorflow的Faster RCNN在Windows上的一個Demo程式,其中,分為兩個部分,一個是訓練資料匯入部分,一個是網路架構部分開始。源程式git地址我會放在文章最後,下載後可以參考對應看一下。 一、程式執行環境說明 首先,我想闡述一堆巨坑,下面只要有

Sass中的巢狀---結合線上編譯選擇器巢狀、屬性巢狀、類巢狀

推薦部落格:https://blog.hypers.io/2017/08/06/sass%20&%20compass%20%E6%95%99%E7%A8%8B%20--%20%E8%AF%AD%E6%B3%95%E7%AF%87(%E4%B8%80)/?utm_source=tuicool&