![]() |
特性是指建置組態中標準化(與工具集無關)的方面,例如是否啟用內嵌。特性名稱不能包含「>
」字元。
建置組態中的每個特性都有一個或多個相關聯的值。非自由特性的特性值不能包含「<
」、「:
」或「=
」字元。自由特性的特性值不能包含「<
」字元。
屬性是一個 (特性, 值) 對,表示為 <特性>值。
子特性是指僅在其父特性存在時才存在的特性,並且其識別碼可以(在其父特性的上下文中)從其值推導出來。子特性的父特性永遠不能是另一個子特性。因此,特性及其子特性形成一個兩級階層。
特性 **F** 的值字串是格式為 值-子值1-子值2
...-子值N
的字串,其中 值
是 **F** 的合法值,而 子值1
...子值N
是 **F** 的某些子特性的合法值。例如,屬性 <toolset>gcc <toolset-version>3.0.1
可以使用值字串更簡潔地表示為 <toolset>gcc-3.0.1
。
屬性集是一組屬性(即不包含重複項的集合),例如:<toolset>gcc <runtime-link>static
。
屬性路徑是將其元素以斜線分隔並連接成單個字串的屬性集。前述範例的屬性路徑表示法為 <toolset>gcc/<runtime-link>static
。
建置規格是一個屬性集,它完整描述了用於建置目標的一組特性。
對於自由特性,所有值均有效。對於所有其他特性,有效值是明確指定的,建置系統將會針對使用無效的特性值回報錯誤。子屬性有效性可能會受到限制,以便某些值僅在存在某些其他子屬性時才有效。例如,可以指定 <gcc-target>mingw
屬性僅在存在 <gcc-version>2.95.2
時才有效。
每個特性都有一組零個或多個以下屬性。特性屬性是關於建置系統在建置請求中出現特性值時應如何解讀這些值的低階描述。我們也參考屬性的屬性,例如,附帶屬性是指其特性具有附帶屬性的屬性。
附帶
附帶特性 (Incidental features) 被假設完全不影響建置產物。因此,建置系統可以將同一個檔案用於建置規格僅在附帶特性上有所不同的目標。控制編譯器警告級別的特性就是一個可能的附帶特性的例子。
非附帶特性 (Non-incidental features) 被假設會影響建置產物,因此建置規格在非附帶特性上有所不同的目標的檔案會被放置在不同的目錄中,如「目標路徑」一節所述。
這類特性會傳播到依賴項。也就是說,如果使用傳播式特性建置主要目標,建置系統會嘗試在建置其任何依賴項時使用相同的特性,作為該主要目標的一部分。例如,當請求最佳化的可執行檔時,通常希望它與最佳化的程式庫連結。因此,<optimization>
特性是傳播式的。
大多數特性都有一組有限的允許值,並且在給定的建置規格中只能採用該集合中的一個值。另一方面,自由式特性可以同時具有多個值,並且每個值都可以是任意字串。例如,可以同時定義多個前置處理器符號。
<define>NDEBUG=1 <define>HAS_CONFIG_H=1
選用式 (optional)
選用式特性是指建置規格中不需要出現的特性。每個非選用式非自由式特性都有一個預設值,當在目標的需求或使用者的建置請求中未指定特性的值時,將使用該預設值。[特性的預設值由特性宣告中列出的第一個值給出。 -- 將此移至其他位置 - dwa]
對稱式 (symmetric)
通常,只有當特性的值与其預設值不同時,特性才會產生子變體目錄,從而導致特性的某些值具有不對稱的子變體目錄結構。對稱式特性始終會產生相應的子變體目錄。
路徑式 (path)
路徑式特性的值指定一個路徑。該路徑被視為相對於使用路徑式特性的 Jamfile 所在的目錄,並且當從不同目錄調用建置時,建置系統會適當地轉換該路徑。
隱含式 (implicit)
隱含式特性的值本身即可識別該特性。例如,使用者不需要寫 "<toolset>gcc",只需寫 "gcc" 即可。隱含式特性名稱也不會出現在變體路徑中,儘管值會出現。因此:bin/gcc/… 與 bin/toolset-gcc/… 相對。通常應該只有少數此類特性,以避免可能的名稱衝突。
複合式 (composite)
複合式特性實際上對應於屬性組。例如,建置變體就是一個複合式特性。從一組建置屬性產生目標時,複合式特性會被遞迴展開並新增到建置屬性集中,以便規則可以在需要時找到它們。非複合式非自由式特性會覆蓋建置屬性集中複合式特性的組成部分。
依賴式 (dependency)
依賴式特性的值是一個目標參考。當用於建置主要目標時,依賴式特性的值將被視為額外的依賴項。
例如,依存性功能允許聲明程式庫 A 依存於程式庫 B。因此,每當應用程式連結到 A 時,它也會連結到 B。將 B 指定為 A 的依存性與將 B 新增到 A 的來源不同。
既不免費也不附帶的功能稱為基本功能。
當請求具有特定屬性的目標,並且該目標需要某些屬性集時,需要找到用於建構的屬性集。這個過程稱為屬性精煉,並由以下規則執行:
有時,希望僅針對其他屬性的特定組合應用某些需求。例如,您使用的其中一個編譯器發出一個無意義的警告,您希望透過傳遞命令列選項給它來抑制該警告。您不希望將該選項傳遞給其他編譯器。條件屬性允許您執行此操作。它們的語法是:
property ( "," property ) * ":" property
例如,上述問題可以透過以下方式解決:
exe hello : hello.cpp : <toolset>yfc:<cxxflags>-disable-pointless-warning ;
該語法也允許條件中有多個屬性,例如:
exe hello : hello.cpp : <os>NT,<toolset>gcc:<link>static ;
目標識別碼用於表示目標。語法如下:
target-id -> (project-id | target-name | file-name ) | (project-id | directory-name) "//" target-name project-id -> path target-name -> path file-name -> path directory-name -> path
此語法允許某些元素被識別為:
為了確定真實含義,會檢查是否存在指定名稱的專案 ID,然後檢查是否存在該名稱的主要目標。例如,有效的目標 ID 可能是:
a -- target in current project lib/b.cpp -- regular file /boost/thread -- project "/boost/thread" /home/ghost/build/lr_library//parser -- target in specific project
原理:目標與專案之間以特殊分隔符號(不僅僅是斜線)分隔,因為:
目標參考用於指定來源目標,並且可以額外指定該目標的所需屬性。它的語法如下:
target-reference -> target-id [ "/" requested-properties ] requested-properties -> property-path
例如:
exe compiler : compiler.cpp libs/cmdline/<optimization>space ;
即使 compiler
可執行檔是使用速度最佳化建構的,也會導致連結已針對空間最佳化的 cmdline
程式庫版本。