GNU make規則的命令 書寫命令

2022-08-18 20:00:18 字數 3578 閱讀 3305

通常, make 在執行命令列之前會把要執行的命令列輸出到標準輸出裝置。我們稱之為「回顯」,就好像我們在 shell 環境下輸入命令執行時一樣。

如果規則的命令列以字元「 @」開始,則 make 在執行這個命令時就不會回顯這個將要被執行的命令。

如果使用make的命令列引數「 -n」或「 --just-print」,那麼make執行時只顯示所要執行的命令,但不會真正的去執行這些命令。其中也包括了使用「 @」字元開始的命令。

make引數「 -s」或「 --slient」則是禁止所有執行命令的顯示,就好像所有的命令列均使用「 @」開始一樣。在makefile中使用沒有依賴的特殊目標「 .silent」也可以禁止命令的回顯,但是它不如使用「 @」來的靈活。因此在書寫makefile時,我們推薦使用「 @」來控制命令的回顯。

規則中,當目標需要被重建時。此規則所定義的命令將會被執行,如果是多行命令,那麼每一行命令將在乙個獨立的子 shell 程序中被執行(就是說,每一行命令的執行是在乙個獨立的 shell 進城中完成)。因此,多行命令之間的執行是相互獨立的,相互之間不存在依賴(多條命令列的執行為多個相互獨立的程序)。

在 makefile 中書寫在同一行中的多個命令屬於乙個完整的 shell 命令列,書寫在獨立行的一條命令是乙個獨立的 shell 命令列。因此:在乙個規則的命令中,命令列「 cd」改變目錄不會對其後的命令的執行產生影響。就是說其後的命令執行的工作目錄不會是之前使用「 cd」進入的那個目錄。如果要實現這個目的, 就不能把「 cd」和其後的命令放在兩行來書寫。而應該把這兩條命令寫在一行上,用分號分隔。這樣它們才是乙個完整的 shell 命令列。如:

foo : bar/lose

cd bar; gobble lose > ../foo

如果希望把乙個完整的 shell 命令列書寫在多行上,需要使用反斜槓( \)來對處於多行的命令進行連線,表示他們是乙個完整的 shell 命令列。

gnu make 支援同時執行多條命令。通常情況下,同一時刻只有乙個命令在執行,下乙個命令只有在當前命令執行完成之後才能夠開始執行。不過可以通過 make 的命令列選項「 -j」或者「 --job」來告訴 make 在同一時刻可以允許多條命令同時被執行(注意,在 ms-dos 中此選項無效,因為它是單任務作業系統)。

一些情況下,規則中乙個命令的執行失敗並不代表規則執行的錯誤。例如我們使用「 mkdir」命令來確保存在乙個目錄。當此目錄不存在使我們就建立這個目錄,當目錄存在時那麼「 mkdir」就會執行失敗。其實我們並不希望 mkdir 在執行失敗後終止規則的執行。為了忽略一些無關命令執行失敗的情況,我們可以在命令之前加乙個減號「 -」(在[tab]字元之後),來告訴 make 忽略此命令的執行失敗。命令中的「 -」號會在 shell解析並執行此命令之前被去掉, shell 所解釋的只是純粹的命令,「 -」字元是由 make來處理的。

make 在執行命令時如果收到乙個致命訊號(終止 make),那麼 make 將會刪除此過程中已經重建的那些規則的目標檔案。其依據是此目標檔案的當前時間戳和 make 開始執行時此檔案的時間戳是否相同。刪除這個目標檔案的目的是為了確保下一次 make 時目標檔案能夠被正確重建。假設正在編譯時鍵入「 ctrl-c」,此時編譯器已經開始寫檔案「 foo.o」,但是「 ctrl-c」產生的訊號關閉了編譯器。這種情況下檔案「 foo.o」可能是不完整的,但這個內容不完整的「 foo.o」檔案的時間戳比源程式『 foo.c』的時間戳新。如果在 make 收到終止訊號後不刪除檔案「 foo.o」而直接退出,那麼下次執行make 時此檔案被認為已是最新的而不會去重建它。最後在鏈結生成終極目標時由於某乙個.o 檔案的不完整,可能出現一堆令人難以理解的錯誤資訊,或者產生了乙個不正確的終極目標。

make 的遞迴過程指的是:在 makefile 中使用「 make」作為乙個命令來執行本身或者其它 makefile 檔案的過程。遞迴呼叫在乙個存在有多級子目錄的專案中非常有用。例如,當前目錄下存在乙個「 subdir」子目錄,在這個子目錄中有描述此目錄編譯規則的 makefile 檔案,在執行 make 時需要從上層目錄(當前目錄)開始並完成它所有子目錄的編譯。那麼在當前目錄下可以使用這樣乙個規則來實現對這個子目錄的編譯:

subsystem:

cd subdir && $(make)

其等價於規則:

subsystem:

$(make) -c subdir

第乙個規則命令的意思是:進入子目錄,然後在子目錄下執行make。第二個規則使用了make的「 -c」選項,同樣是首先進入子目錄而後再執行make。

在 make 的遞迴執行過程中,上層 make 可以明確指定將一些變數的定義通過環境變數的方式傳遞給子 make 過程。沒有明確指定需要傳遞的變數,上層 make 不會將其所執行的 makefile 中定義的變數傳遞給子 make 過程。使用環境變數傳遞上層所定義的變數時,上層所傳遞給子 make 過程的變數定義不會覆蓋子 make 過程所執行makefile 檔案中的同名變數定義。

如果子make過程所執行makefile中存在同名變數定義,則上層傳遞的變數定義不會覆蓋子makefile中定義的值。就是說如果上層make傳遞的變數和子make所執行的makefile中存在重複的變數定義,則以子makefile中的變數定義為準。除非使用make的「 -e」選項。

上層 make 過程要將所執行的 makefile 中的變數傳遞給子 make 過程,需要明確地指出。在 gnu make 中,實現此功能的指示符是「 export」。當乙個變數使用「 export」進行宣告後,變數和它的值將被加入到當前工作的環境變數中,以後在 make 執行的所有規則的命令都可以使用這個變數。而當沒有使用指示符「 export」對任何變數進行宣告的情況下,上層 make 只將那些已經初始化的環境變數(在執行 make 之前已經存在的環境變數)和使用命令列指定的變數(如命令「 makecflags +=-g」或者「 make –e cflags +=-g」)傳遞給子 make 程式,通常這些變數由字元、數字和下劃線組成。需要注意的是:有些 shell 不能處理那些名字中包含除字母、數字、下劃線以外的其他字元的變數。

書寫makefile時,可能有多個規則會使用相同的一組命令。就像c語言程式中需要經常使用到函式「 printf」。這時我們就會想能不能將這樣一組命令進行類似c語言函式一樣的封裝,以後在我們需要用到的地方可以通過它的名字( c語言中的函式名)來對這一組命令進行引用。這樣就可減少重複工作,提高了效率。在gnu make中,可以使用指示符「 define」來完成這個功能(關於指示符「 define」可參考 6.8 多行定義 一節)。通過「 define」來定義這樣一組命令,同時用乙個變數(作為乙個變數,不能和makefile中其它常規的變數命名出現衝突)來代表這一組命令。通常我們把使用「 define」定義的一組命令稱為乙個命令包。定義乙個命令包的語法以「 define」開始,以「 endef」結束,例如:

define run-yacc

yacc $(firstword $^)

mv y.tab.c $@

endef

這裡,「 run-yacc」是這個命令包的名字。在「 define」和「 endef」之間的命令就是命令包的主體。需要說明的是:使用「 define」定義的命令包中,命令體中變數和函式的引用不會展開。命令體中所有的內容包括「 $」、「(」、「)」等都是變數「 run-yacc」的定義。

空命令列可以防止make在執行時試圖為重建這個目標去查詢隱含命令(包括了使用隱含規則中的命令和「 .default」指定的命令。

《完》

uBlock的動態規則過濾規則書寫

ublock具有動態和靜態兩種規則,但是它比之前的abp等規則過濾規則強的地方就在於他的動態規則,靜態規則的語法繼承與abp,有興趣的可以去看abp的過濾規則現在主要介紹它的動態規則,這才是讓它變成神器的主要原因 英文文件 語句書寫非常簡單 分為4塊 主機位址 目前正在瀏覽的 載入廣告的源位址 請求...

問的書寫規則是什麼意思 漢字筆順的書寫規則是什麼

筆順安排的基本規則有 1先橫後豎 十 於 豐 幹 丁 等。含上述字或部件的字,如木 芋 豔 刊 花 羊等,也是如此。2先撇後捺 人 八 入 木 等。含上述字或部件的字,如大 分 樹 艾等,也是如此。由於漢字中沒有捺起筆的字,所以撇與捺不論是相交 相離 相接,書寫時都是先撇后捺。3先上後下 二 丁 立...

1 Shell命令列書寫規則

學習目標 shell命令列書寫規則 正文 對shell命令列基本功能的理解有助於編寫更好的shell程式,在執行shell命令時多個命令可以在乙個命令列上執行,但此時要使用分號 分隔命令,例如 root ubuntu ls a l free df 長shell命令列可以使用反斜線字元 在命令列上擴充...