![]() |
我們經常需要控制傳遞給所呼叫工具的選項。這是通過功能來完成的。請看一個例子
# Declare a new free feature import feature : feature ; feature verbatim-options : : free ; # Cause the value of the 'verbatim-options' feature to be # available as 'OPTIONS' variable inside verbatim.inline-file import toolset : flags ; flags verbatim.inline-file OPTIONS <verbatim-options> ; # Use the "OPTIONS" variable actions inline-file { "./inline-file.py" $(OPTIONS) $(<) $(>) }
我們首先定義一個新功能。然後,`flags` 呼叫表示,每當執行 verbatin.inline-file 動作時,`verbatim-options` 功能的值就會被添加到 `OPTIONS` 變數中,並可在動作主體內使用。您需要查閱線上說明(--help)才能找到 `toolset.flags` 規則的所有功能。
雖然您可以定義任何功能集並以任何方式解讀它們的值,但 Boost.Build 建議遵循以下程式碼標準來設計功能。
大多數功能都應該具有一組固定的值,這些值在其設計用於處理的工具類別中是可移植的(與工具無關)。使用者無需針對特定工具調整值。例如,`
除了這些可移植的功能之外,還有一些特殊的「原始」功能,允許使用者根據需要將任何值傳遞給特定工具的命令列參數。例如,`
使用可移植功能是一個好主意,因為
當一個可移植功能被賦予一組固定的值時,您可以使用該功能的兩種不同設定來建置您的專案,Boost.Build 會自動使用兩個不同的目錄來存放產生的檔案。Boost.Build 不會嘗試區分使用不同原始選項建置的目標。
與「原始」功能不同,您不需要在 Jamfile 中使用特定的命令列標誌,而且它更有可能與其他工具相容。
新增功能需要三個步驟
宣告功能。為此,使用了 "feature.feature" 規則。您必須決定功能屬性的集合
如果您希望一個目標的功能值設定自動傳播到其相依目標,則將其設為「propagated(傳播)」。
如果某個功能沒有固定的值列表,則它必須是「free(自由)」。例如,`include` 功能就是一個自由功能。
如果某個功能用於參照相對於 Jamfile 的路徑,則它必須是「path(路徑)」功能。此類功能的值也會自動轉換為 Boost.Build 的內部路徑表示法。例如,`include` 是一個路徑功能。
如果某個功能用於參照某些目標,則它必須是「dependency(相依性)」功能。
在目標特定變數中表示功能值。建置動作是由 Boost.Jam 變數展開修改的命令範本。`toolset.flags` 規則將目標特定變數設定為功能的值。
使用變數。在步驟 2 中設定的變數可用於建置動作中,以形成命令參數或檔案。
這裡有個例子。讓我們看看如何製作一個引用目標的功能。例如,在 Windows 上連結動態函式庫時,有時需要指定一個「DEF 檔」,說明應該匯出哪些函式。如果能像這樣使用這個檔案就好了:
lib a : a.cpp : <def-file>a.def ;
實際上,這個功能已經支援了,但無論如何……
由於該功能引用了目標,它必須是「dependency(依存關係)」。
feature def-file : : free dependency ;
其中一個關心 DEF 檔的工具集是 msvc。應該在其中加入以下一行:
flags msvc.link DEF_FILE <def-file> ;
由於 `msvc.link` 動作並未使用 `DEF_FILE` 變數,我們需要將其修改為:
actions link bind DEF_FILE { $(.LD) .... /DEF:$(DEF_FILE) .... }
請注意 `bind DEF_FILE
` 部分。它告訴 Boost.Build 將 `DEF_FILE
` 中的內部目標名稱轉換為 `link
` 動作中對應的檔案名稱。如果沒有它,`$(DEF_FILE)
` 的展開將會是一個奇怪的符號,連結器可能無法理解。
我們幾乎完成了,除了將以下程式碼新增到 `msvc.jam
`:
rule link { DEPENDS $(<) : [ on $(<) return $(DEF_FILE) ] ; }
這是 Boost.Build 引擎中一個錯誤的解決方法,希望有一天能修復它。
有時您想要為某些功能集建立捷徑。例如,`release
` 是 `<variant>
` 的一個值,並且是一組功能的捷徑。
可以定義您自己的建置變體。例如:
variant crazy : <optimization>speed <inlining>off <debug-symbols>on <profiling>on ;
將使用指定的屬性集定義一個新的變體。您也可以擴充現有的變體:
variant super_release : release : <define>USE_ASM ;
在這種情況下,`super_release
` 將展開為 `release
` 指定的所有屬性,以及您指定的額外屬性。
您不限於僅使用 `variant
` 功能。以下範例定義了一個全新的功能:
feature parallelism : mpi fake none : composite link-incompatible ; feature.compose <parallelism>mpi : <library>/mpi//mpi/<parallelism>none ; feature.compose <parallelism>fake : <library>/mpi//fake/<parallelism>none ;
這將允許您指定 `parallelism
` 功能的值,該功能將展開以連結到必要的函式庫。