編譯模式 (Compilation Modes)
模式是一個具名的編譯期開關,用於控制哪些宣告被包含在建置中。
- #[mode(name1, name2, ...)] 根據啟用的模式名稱篩選宣告。
- #[test_only] ≡ #[mode(test)]。
- 未標註的宣告始終包含。
- 標註的宣告當且僅當列出的任何名稱被啟用時才包含。
- 啟用任何模式(包括 test)表示建置不可發佈。
- 模式只影響編譯期包含;除了可發佈性之外,它們在位元組碼層級被消除。
模式基礎 (Mode Basics)
模式透過以下屬性表達:
#[mode(name1, name2, ...)]
#[test_only] // (#[mode(test)] 的簡寫)
啟用任何模式(包括 test)編譯的程式碼不可發佈。
本節定義了模式的語法、包含規則、範圍和工具互動。(如需介紹性教學和範例,請參閱指南頁面。)
模式標註 (Mode Annotations)
#[mode(...)] 可以放置在模組和模組成員(函式、結構體、常數等)上。
#[mode(name1, name2, ...)]
module <addr_opt>::<ident> { ... }
module <addr_opt>::<ident> {
#[mode(name1, name2, ...)]
<decl>
}
注意:#[test_only] 完全等同於 #[mode(test)]。
模式名稱 (Mode Names)
每個名稱都是一個非空識別符。模式名稱區分大小寫。
包含模型 (Inclusion model)
令 M 為建置的啟用模式集合。令 S(m) 為宣告 m 上列出的模式集合,其中 #[test_only] 貢獻 {test},未標註的宣告具有 S(x) = ∅。宣告 x 被包含在編譯單元中當且僅當以下其中一項為真:
- S(x) = ∅ (未標註)
- S(x) ∩ M ≠ ∅:(標註被包含)
即:未標註的宣告始終被包含;標註的宣告當且僅當其列出的至少一個名稱在建置中啟用時才被包含,否則被排除。
模組範圍 (Module scope)
如果模組被排除,其所有成員隱含地被排除。如果模組被包含,標註的成員仍可能被排除,如果其自身的 S(m) 不與 M 相交。
在一個屬性上的多個模式 (Multiple modes on one attribute)
#[mode(a, b, c)] 中的列表是析取式的(邏輯或):如果任何列出的名稱匹配就包含。
名稱解析與重複 (Name resolution & duplicates)
模式只是編譯期篩選器。它們不引入執行時條件,在位元組碼中沒有表示。所有驗證都在包含的原始碼子集上執行。
當存在重複時,標準名稱解析規則適用。這意味著兩個模式不能在同一建置中啟用具有相同名稱的不同模組或成員。類似地,模式標註定義不能覆蓋具有相同名稱的未標註宣告。
為了提供模式特定的替代方案,將它們放在由模式閘控的分離模組中,或使用不同的名稱並在測試或驅動程式中選擇它們。
使用工具與標誌 (Usage Tooling & flags)
對於建置和測試,move build --mode <name> 將 <name> 添加到 M。可以透過重複傳遞 --mode 來啟用多個模式;M 是所有傳遞名稱的聯集,例如 move build --mode test --mode debug。這將啟用所有用 #[mode(test)] 或 #[mode(debug)] 標註的模組和成員。注意 move test 隱含地供應 --mode test。
可發佈性 (Publishability)
任何啟用至少一個模式(包括 test)的建置都會產生不可發佈的輸出。要建立可發佈的工件,不能啟用任何模式。