| RFC-0093:元件資訊清單的設計原則 | |
|---|---|
| 狀態 | 已接受 |
| 區域 |
|
| 說明 | 元件資訊清單使用的 `.cml` 和 `.cm` 格式設計附註。 |
| 問題 | |
| Gerrit 變更 | |
| 作者 | |
| 審查人員 | |
| 提交日期 (年-月-日) | 2021-04-26 |
| 審查日期 (年-月-日) | 2021-05-05 |
摘要
本文件記錄了有關元件資訊清單所用 .cml 和 .cm 格式的設計考量、原則和決策。
以下所述的大多數決策,都是在 2018 年至 2019 年間做出。
詞彙解釋
.cml是元件資訊清單來源檔案的常見副檔名。CML 檔案是 JSON5 DSL,用於宣告元件。- ComponentDecl 是 FIDL 表格,也是元件資訊清單的標準線路和儲存格式。
.cm是常見的檔案副檔名,用於以 FIDL 信封二進位格式,儲存含有 ComponentDecl 的檔案。cmc是指令列主機工具,可從.cml檔案產生.cm檔案。這項工具建構於 Fuchsia 來源樹狀結構中,並透過 Fuchsia SDK 發布為預先建構的可執行檔。
#1:元件資訊清單有前端和後端
人類和機器的需求與偏好不同,在設計元件資訊清單語法和格式時,主要設計原則是為元件架構建立單一後端格式,供開發人員讀取,並建立獨立的前端 (一開始是單一前端),供開發人員撰寫。這項設計決策有以下優點:
- 您可以分別最佳化後端和前端,以滿足不同的設計目標。
- 您可以在不修改後端的情況下演進前端,反之亦然。
- 雖然目前只有一個前端,但可以導入其他前端,例如滿足不同目標對象的不同設計目標,或迎合便利性、熟悉度或風格的偏好。
為達成這些目標,SDK 提供 [cmc] (「元件資訊清單編譯器」),這是將元件資訊清單來源檔案 (.cml) 轉換為資訊清單二進位檔案 (.cm) 的標準工具。cmc 通常會與建構系統透明整合,這表示開發人員通常會與來源檔案互動,除非他們要對資訊清單進行偵錯或分析。
ComponentDecl:元件資訊清單後端
ComponentDecl 是元件資訊清單的標準儲存和連線格式。這項格式的設計目的是供程式碼 (例如元件管理工具、元件解析器和資訊清單分析工具 (例如 fx scrutiny)) 撰寫及解讀。這類格式必須符合下列目標:
- 且必須明確且能自我說明。應可直接從資訊清單內容衍生出其意義。
- 且必須能隨著時間演進,支援向前和向後相容性。
- 必須易於剖析,並避免不必要的格式轉換。 否則,處理元件資訊清單的程式碼 (包括元件管理工具) 中,就會不必要地增加錯誤或攻擊的風險。
- 必須能輕鬆整合至與元件資訊清單介接的執行階段、元件和工具。
基於這些設計目標,我們自然而然選擇了 FIDL 格式。FIDL 是 Fuchsia 中 IPC 的標準線路格式。FIDL 值類型 (即沒有控制代碼的型別) 可以保存,並做為儲存格式使用。具體來說,我們使用 FIDL 信封,因為這類信封具有略過不明欄位的額外優點,有助於回溯和前向相容性。由於在 Fuchsia 上執行的任何執行階段都已提供 FIDL 繫結,因此可輕鬆與程式碼整合,且不需要額外支援剖析或轉換。
ComponentDecl 的結構不會有預設值,也就是說,只有在欄位不適用,或是來自沒有該欄位的資訊清單版本時,欄位才會未填入值。此外,為了支援向前和向後相容性,ComponentDecl 和其中巢狀結構都是 FIDL 表格或 FIDL 彈性聯集。
CML:元件資訊清單前端
CML (元件資訊清單語言) 是元件資訊清單的來源格式。這項格式的設計目的是供人類讀取和寫入,但格式器和語言伺服器等開發工具也可能讀取和寫入。
- 瞭解基本元件架構概念的初學者應能看懂。
- 應能方便地表示常見模式,且不會有過多的樣板。
- 如果變更會影響資訊清單的語法,但不會影響語意,則應該不需要變更資訊清單的二進位表示法。舉例來說,從單一陣列變更為單一值,不應影響輸出內容。
- 應有助於維護。特別是應允許留言。
- 應具備足夠的機器可讀性,支援自動轉換,例如支援大規模重構。
為達成這些目標,我們發明瞭 CML。CML 是以 JSON5 為基礎的設定語言,可做為簡單的 DSL,用來產生 ComponentDecl。CML 使用 JSON5,許多開發人員已熟悉這種語言,且 Fuchsia 的其他地方也廣泛使用。與 ComponentDecl 不同,CML 提供一些功能,可讓您更簡潔地編寫資訊清單:
- 這可讓系統省略部分欄位的預設值。
- 只要多項功能共用相同選項,就能將這些功能分組為單一宣告。
- 資訊清單可納入資訊清單碎片,將內容提供給資訊清單。舉例來說,您可以依附程式庫並納入程式庫的 Shard,取得該程式庫所需的所有功能。
最後,從 CML 到 ComponentDecl 的轉換雖然不是一對一,但使用者應該能輕鬆理解,不必學習相關規則。
#2:元件由資訊清單定義
資訊清單會說明元件。系統會在啟動時透過元件的網址解析資訊清單。舉例來說,透過 fuchsia-pkg:// 網址啟動的元件會包含具有 .cm 擴充功能的資訊清單,其中包含從套件解析的序列化 ComponentDecl。除了資訊清單,元件也可能納入來自相同套件的資源。舉例來說,使用 ELF 執行器的元件會指定該套件中 ELF 二進位檔的位置。另一方面,具有 https:// 網址的元件可能具有由 https 解析器產生的 ComponentDecl,但該元件並非由可透過網址取得的資源支援。
元件的資訊清單會完整說明其輸入、輸出和內部組成。目前,元件資訊清單不得有任何參數或「懸空」值,這些值會在執行階段填入。1
不過,這並非表示資訊清單會完整說明元件的行為。首先,元件可用的功能是由父項決定,元件無法控制誰提供這些功能。此外,每個元件都屬於環境的一部分,可為元件提供特定類型的設定,例如用於解析元件網址的解析器。
追蹤資訊清單之間的網址會產生元件執行個體樹狀結構。元件執行個體樹狀結構會完整說明構成 Fuchsia 映像檔的軟體。因此,您可以放心地對特定系統映像檔執行安全性稽核,例如使用 [fx
scrutiny](https://fuchsia.dev/reference/tools/fx/cmd/scrutiny)。
#3:元件資訊清單為宣告式
雖然具有命令式特徵的設定語言功能強大,但會導致可讀性、可預測性和可稽核性降低。先例顯示,命令式風格過於強烈的設定語言十分脆弱,且不夠友善。2以元件架構為例,元件定義必須可供稽核且容易理解,因此命令式風格的設定語言並非理想選擇。
因此,CML 是一種陳述式語言。如果 CML 支援產生部分資訊清單,則僅適用於結果非常可預測的情況。舉例來說,資訊清單支援預設值和納入項目,但不提供範本化或參數化功能。
CML 是一種語言,專為人類讀寫而設計。除了整合開發人員工具 (例如格式化工具或 IDE 範本) 之外,CML 不應由工具產生。產生 CML 檔案會提高遮蓋資訊清單底層內容的風險,因為現在有 CM、CML 和工具這三個層級。如果基於某些原因必須產生資訊清單,您應另外編寫前端來產生 CM。
#4:元件資訊清單可來自各種來源
一般而言,元件資訊清單不會繫結至任何單一發布機制。最終,元件解析器有責任為網址擷取元件資訊清單。解析器完成這項作業的方式取決於特定網址架構。舉例來說,fuchsia-pkg:// 解析器會擷取套件,並從網址的片段 ID 部分指定的套件讀取資訊清單。網頁解析器可能會產生資訊清單,內容會因網域、安全性政策和使用者偏好設定而異。
目前最常見的元件發布方式是透過 Fuchsia 套件。這類元件是以 fuchsia-pkg:// 網址識別。元件資訊清單會以 Blob 形式隨附於這個套件中,通常位於 meta/。
尋求靈感
- Kubernetes 中的聲明式應用程式管理:設計 Kubernetes 設定語言時使用的原則,以及替代方案研究。
- 命令式與宣告式:擴展標題主題。
- Starlark:以 Python 為基礎的 DSL 和命令式設定語言。
- Jsonnet:JSON 的擴充功能,可做為資料範本語言,任何程式都會產生 JSON 文件。
- borgcfg、GCL 和 borgmon:Google 使用的功能設定語言,大致上與 Kubernetes 類似,其歷史有助於我們瞭解命令式和宣告式語法之間的取捨。