![]() |
本節說明如何擴充 Boost.Build 以適用於您當地的需求,主要是要為您擁有的非標準工具新增支援。在我們開始之前,請務必閱讀並了解元目標的觀念,名為「觀念」的節對了解其餘的教材至關重要。
Boost.Build 的目前版本有三個層級的目標,如下所列。
從 Jam 檔案中的宣告所建立的物件。可以使用一組屬性來呼叫以產生實體目標。
與檔案或動作相對應的物件。
對應於 Boost.Jam 建置引擎的低層級實體目標。實質上是一個字串,通常是檔案名稱。
大多數情況下,您需要處理的只有實體目標,以及建立實體目標的程序。很少需要擴充元目標的層級。jam 目標通常只會在命令列模式中使用。
所有 Boost.Jam 與目標相關的內建函式,例如 DEPENDS
或 ALWAYS
都會作用於 jam 目標。將它們套用至元目標或實體目標並不會產生任何效果。
元目標是一個會記錄 Jam 檔案中指定資訊的物件,例如元目標類型、名稱、來源與屬性,並可以搭配特定屬性來呼叫以產生實體目標。在程式碼層級,它會表示成從 abstract-target 衍生的類別實例。 [4]
產生 方法會採取建置屬性(作為 property-set 類別實例),並回傳包含以下內容的清單
前置元素—此呼叫的用法需求( property-set 的實例)
後續元素—建立的實體目標(virtual-target
的實例)
可以使用 targets.resolve-reference
函式根據目標識別碼來查詢元目標,而且 targets.generate-from-reference
函式可以查詢並同時產生元目標。
abstract-target 類別有三個直接衍生類別
project-target 對應專案,且不預期會進一步將其子類化。<此類別的 generate 方法會建立專案中所有未標記為 explicit 的目標。
main-target 對應專案中的目標,且包含一個或多個目標替代。此類別也不應當作子類別使用。此類別的 generate 方法會選擇要建立的替代,並呼叫該替代的 generate 方法。
basic-target 對應特定目標替代。這是基本類別,並帶有多個衍生類別。 generate 方法會處理目標需求和要求的建立屬性,以決定目標的最終屬性、建立所有來源,並最後呼叫包含來源虛擬目標清單和最終屬性的抽象 construct 方法。
project-target 和 main-target 類別的執行個體會隱含建立,也就是在載入新的 Jamfiles 或建立具有尚未得知的名稱的新目標替代時建立。源自 basic-target 的類別的執行個體通常會在 Jamfile 呼叫 metatarget 規則(例如 exe
)時建立。
可建立源於 basic-target 的自訂類別,並建立會建立此類目標執行個體的新 metatarget 規則。不過,在大部分情況下,會使用 basic-target(一種 typed-target)的特定子類別。該類別會與 類型 關聯,並轉發至 產生器 建立該類型的具體目標。此流程會在下文中說明。在宣告新類型時,會自動定義新的 metatarget 規則。該規則會建立新類型,並與該類型關聯。
具體目標由衍生自virtual-target
類別的類別實例表示。最常使用的子類別為file-target
。檔案目標與建立它的動作相關聯,這是action
類別的實例。而動作又包含來源目標清單。此外,它還包含屬性集實例,其中包含動作應使用的建置屬性。
以下為從另一個目標(source
)建立目標的範例。
local a = [ new action $(source) : common.copy : $(property-set) ] ; local t = [ new file-target $(name) : CPP : $(project) : $(a) ] ;
第一行建立action
類別的實例。第一個參數為來源清單。第二個參數為 jam 層級動作的名稱。第三個參數為套用於此動作的屬性集。第二行建立一個目標。我們指定名稱、類型和專案。我們也傳遞前面建立的動作物件。如果動作建立多個目標,我們可以重複第二行好幾次。
在某些情況下,用於建立具體目標的程式碼可能會以相同的屬性呼叫多次。如果傳回不同的file-target
實例對應到相同檔案,這顯然會導致問題。因此,每當傳回目標時,您都應該透過virtual-target.register
函數傳遞目標;除了讓 Boost.Build 追蹤為每個中目標建立哪些虛擬目標之外,這也會在必要時以先前建立的相同目標取代目標。[5]以下是一些範例
return [ virtual-target.register $(t) ] ; return [ sequence.transform virtual-target.register : $(targets) ] ;
理論上,Boost.Build 中的各種中目標(例如exe
、lib
或obj
)都可以透過撰寫新的中目標類別來實作;類別會獨立於其他程式碼,找出要產生的檔案以及要使用的命令。但是,這種方式相當不靈活。例如,新增對新編譯器的支援將需要編輯多個中目標。
實際上,大多數檔案都有特定類型,且大多數工具都能使用特定類型的檔案並產出特定類型之檔案。為了利用此事實,Boost.Build 定義了目標類型的概念和 產生器 ,還有一個特殊的 metatarget 類別 typed-target 。目標類型僅為一種識別字元。它會與對應到該類型的檔案附檔名關聯在一起。產生器是工具的一種抽象化。它會標示它所產生之類型,如果被調用時附有目標輸入集合,就會想建構標示類型之輸出目標。最後, typed-target 會與特定目標類型相關聯,並傳遞該類型的產生器(或產生器集合)。
產生器是從 generator
所衍生出來的類別的實例。 generator
類別本身適合用在一般情況。您可以定義衍生類別以套用於自訂場景。