GNU make手冊翻譯系列(5)

4.6 沒有配方或依賴的規則

        如果一條規則沒有配方或依賴,並且規則的目標不是一個存在的文件名,則執行此規則時,make就認爲它的目標已經被更新過.這樣的目標在作爲一個規則的依賴時,因爲依賴總被認爲被更新過,因此作爲依賴所在的規則中定義的命令總會被執行.看一個例子:

clean: FORCE

        rm$(objects)

FORCE:
這個例子中,目標"FORCE"就符合了上邊的條件,所以當make執行目標"clean"所在規則時:,它的配方總會被執行.這種沒有配方或依賴的特殊目標並沒有一個固定的名字,只是習慣上通常命名爲"FORCE".

        正如你所看到的,使用"FORCE"目標的效果和將"clean"聲明爲僞目標的效果相同.

        使用".PHONY"方式顯然更加直觀高效,只不過因爲其他版本的make程序不一定支持".PHONY"方式,所以許多Makefile中還是使用了"FORCE"目標.


4.7 記錄事件用的空目標文件

        空目標是僞目標的一種變體,它也是一個用來標識一系列配方的集合,並且通常是在make命令行指定該目標時執行.和僞目標不同的是,這個目標可以是一個存在的文件,但文件的具體內容我們並不關心,通常就是一個空文件.

       空目標文件只是用來記錄上一次執行此規則命令的時間戳.實現的方式是在配方中執行touch命令來更新目標文件.

        空目標文件需要有對應的依賴(否則就沒有存在的意義).每次make空目標時,只要有任何一個依賴對象比空目標新,所在規則的配方就會被執行;換句話說,就是如果有一個空目標的依賴在最近一次make該空目標後發生變化,那麼空目標的重建配方就會被執行.下面就是一個例子:

print: foo.c bar.c

        lpr-p $?

        touchprint
按照上面的規則,當目標"print"的任何一個依賴文件被修改之後,輸入"makeprint"就會執行配方中的lpr命令.其中的自動變量"$?"表示只打印變化了的依賴文件.


4.8 特殊的內建目標

Makefile,有一些名字,當它們作爲規則的目標時,具有特殊含義.

.PHONY

                目標".PHONY"的依賴被認爲是僞目標.如果一個目標是僞目標,make該目標時, 論該目標的同名文件是否存在,該目標所 在規則的配方會被無條件執行.

.SUFFIXES

                目標".SUFFIXES"的依賴是一張在後綴規則中需要檢查的後綴名列表.

.DEFAULT

                目標".DEFAULT"的配方被用於重建那些沒有找到相應規則(明確規則或隱含規則) 目標.就是說,目標".DEFAULT"指定了配方的前提下,如果存在一個目標,在某個規 則中作爲依賴卻又不存在構建它的規則,則該目標會套用".DEFAULT"的配方並執行.

.PRECIOUS

             目標".PRECIOUS"的依賴文件在make過程中會被特殊處理:這些依賴文件在作爲目 標被構建期間,如果make程序被kill或中斷,已經生成的這些依賴文件不會被刪除. 使這些依賴文件是中間文件也不會被刪除,在這一點上目標".PRECIOUS"和目標 ".SECONDAY"實現的功能相同.另外,你也可以列出包含隱含規則(比如"%.o")的目標 模式作爲".PRECIOUS"的依賴文件,這樣那些跟該模式匹配的中間文件都會被保留.

.INTERMEDIATE

                 目標".INTERMEDIATE"的依賴文件被作爲中間文件對待.沒有任何依賴文件的目 ".INTERMEDIATE"是沒有意義的.

.SECONDARY

             目標".SECONDARY"的依賴文件被作爲中間文件對待,但這些文件不會被自動刪除. 有任何依賴文件的目標".SECONDARY"表示將所有目標作爲中間過程文件(意味着不 會刪除任何目標文件).

.SECONDEXPANSION

         如果在Makefile中的任何位置設置了".SECONDEXPANSION"目標,make程序在讀 入了所有的Makefile,會對".SECONDEXPANSION"的依賴對象進行二次展開.

.DELETE_ON_ERROR

                如果在Makefile中的任何位置設置了".DELETE_ON_ERROR"目標,make在執行 過程中,如果規則的命令執行錯誤,將刪除已經被修改的目標文件.

.IGNORE

            如果給目標".IGNORE"指定依賴文件,則忽略創建這個文件所執行命令的錯誤.目標 ".IGNORE"的配方會被忽略.當目標".IGNORE"不設置依賴文件時,將忽略所有命令執 行的錯誤.使用".IGNORE"只是爲了實現舊版本兼容.".IGNORE"會影響Makefile中的 每個配方,所以它不是很有用;在後續章節中有更多的選擇方式去忽略指定配方的錯 .

.LOW_RESOLUTION_TIME

              如果給目標".LOW_RESOLUTION_TIME"指定了依賴文件,make程序會將這些依 賴文件當作低分辨率時間戳文件.目標".LOW_RESOLUTION_TIME"的配方會被忽略.

                在判斷文件是否是最新的問題上,很多現代文件系統使用高分辨率文件時間戳來減少 出錯機率.不幸的是,一部分系統並未提供設置高分辨率文件時間戳的方法,這導致 "cp-p"這些命令在執行時必須丟棄文件時間戳中秒級之後的部分.如果一個文件是 由這些命令創建的,該文件就需要設置爲目標".LOW_RESOLUTION_TIME"的依賴, 這樣make程序纔不會錯誤地認爲該文件已經過期了.例如:

.LOW_RESOLUTION_TIME: dst

dst: src

        cp-p src dst
由於"cp-p"命令會丟棄src文件時間戳中秒級之後的部分,所以dst文件總是會稍微舊 src文件.dst文件作爲目標".LOW_RESOLUTION_TIME"的依賴後,只要dst文件 秒級之前部分的時間戳跟src文件秒級之前部分的時間戳相等,make程序就認爲dst 文件是最新的.

            由於檔案文件格式上存在限制,檔案文件中成員文件的時間戳總是低分辨率的.但你 需要將成員文件添加到".LOW_RESOLUTION_TIME"的依賴列表中,因爲make程序 會自動完成這些動作.

.SILENT

              如果你將一個目標添加爲".SILENT"的依賴,則當make程序重建該目標時,將不會在執 行配方之前打印這些配方.目標".SILENT"的配方會被忽略.

                當目標".SILENT"不設置依賴時,表示make程序將不會在執行任何配方前打印這些配 .使用".SILENT"只是爲了實現舊版本兼容,有更多的選擇方式可以使指定配方保持 靜默.如果你想要在某次make過程中讓所有配方保持靜默,可以使用命令行選項"-s""--silent".

.EXPORT_ALL_VARIABLES

                目標".EXPORT_ALL_VARIABLES"作爲一個簡單的不帶依賴的目標時,其目的就是告 make程序將所有變量導出給子make進程.

.NOTPARALLEL

                如果設置了目標".NOTPARALLEL",即使命令行傳入了"-j"選項,make程序都將會串行 執行.但在遞歸調用的子make進程中,除非它的Makefile也包含了這個特殊目標,否則 make進程將會並行執行(make命令行設置了"-j"選項前提下).

.ONESHELL

                如果設置了目標".ONESHELL",則每個規則中即便包含了多行獨立配方,這些配方也 將在一個shell進程中被執行.

.POSIX

                如果設置了目標".POSIX",make程序會運行在符合POSIX標準的模式.這並不意味 着只有符合POSIX標準的Makefile會被接受,而是所有GNUmake的高級特性仍就是 可用的.更確切地說,這個特殊目標的作用是使make程序在遇到make缺省行爲和 POSIX標準存在差別的內容時選擇POSIX標準.

                特別是,如果設置了目標".POSIX",shell在執行配方時就像是設置了"-e"標誌一樣: 方中一旦出現某條命令執行失敗就會立刻退出.


        所有定義的隱含規則後綴作爲目標出現時,都被視爲一個特殊目標,兩個後綴串聯起來也是如此,比如".c.o".這樣的目標被稱爲後綴規則的目標,這種定義方式是已經過時的定義隱含規則的方法(儘管仍舊在廣泛使用).原則上,如果將其分爲兩個部分,並將它們加到後綴列表中,任何目標都可採用這種方式來表示.實際中,後綴通常以"."開始,所以以上的這些特別目標同樣是以"."開始.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章