RFC-0093 - 元件資訊清單的設計原則

RFC-0093:元件資訊清單的設計原則
狀態已接受
區域
  • 元件架構
說明

關於用於元件資訊清單的 `.cml` 和 `.cm` 格式的設計備註。

問題
Gerrit 變更
作者
審查人員
提交日期 (年-月-日)2021-04-26
審查日期 (年-月-日)2021-05-05

摘要

本文件記錄了設計討論、原則和決定,這些內容與元件資訊清單中使用的 .cml.cm 格式相關。

下方所述的大多數決策是在 2018 年至 2019 年間做出。

  1. 元件資訊清單包含前端和後端
  2. 元件是由資訊清單定義
  3. 元件資訊清單為宣告式
  4. 元件資訊清單可來自多種來源

詞彙解釋

  • .cml元件資訊清單來源檔案的常見副檔名。CML 檔案是用於宣告元件的 JSON5 DSL
  • ComponentDecl 是 FIDL 表格,是元件資訊清單的標準線路和儲存格式。
  • .cm 是含有 FIDL 信封二進位格式 ComponentDecl 的檔案常見副檔名。
  • cmc 是指令列主機工具,可從 .cml 檔案產生 .cm 檔案。這個程式碼會在 Fuchsia 來源樹狀結構中建構,並透過 Fuchsia SDK 以預先建構的可執行檔形式發布。

#1:元件資訊清單包含前端和後端

人類和機器的需求和偏好不盡相同。在設計元件資訊清單語法和格式時,主要的設計原則是建立一個後端格式供元件架構讀取,以及一個前端 (一開始是單數) 供開發人員寫入。這項設計決策具備下列優點:

  1. 您可以分別最佳化後端和前端,以滿足不同的設計目標。
  2. 您可以不修改後端,直接改進前端,反之亦然。
  3. 雖然目前只有一個前端,但您可以導入其他前端,例如為了滿足不同目標對象的不同設計目標,或是為了滿足便利性、熟悉度或風格的偏好設定。

為支援這些目標,SDK 提供 [cmc] (「元件資訊清單編譯器」),這是用來將元件資訊清單來源檔案 (.cml) 轉換為資訊清單二進位檔 (.cm) 的標準工具。cmc 通常會與建構系統整合,這表示開發人員通常會與來源檔案互動,除非他們要對資訊清單進行偵錯或分析。

ComponentDecl:元件資訊清單後端

ComponentDecl 是元件資訊清單的標準儲存和傳輸格式。這類元件是設計給程式碼編寫和解讀的,例如元件管理工具、元件解析工具,以及資訊清單分析工具,例如 fx scrutiny。這類格式必須符合下列目標:

  1. 名稱必須明確且能自我說明。應可直接從資訊清單內容推斷資訊清單的意義。
  2. 必須能夠隨著時間演進,支援前向和回溯相容性。
  3. 必須簡單易懂,並避免不必要的格式轉換。否則,處理元件資訊清單 (包括元件管理工具) 的程式碼中,就會不必要地增加發生錯誤或遭到攻擊的風險。
  4. 必須能輕鬆整合至與元件資訊清單介面的執行階段、元件和工具。

這些設計目標自然會導致格式選擇:FIDL。FIDL 是 Fuchsia 中 IPC 的標準線路格式。FIDL 值類型 (即沒有句柄的類型) 可持續存在,並用作儲存格式。具體來說,我們使用 FIDL 信封,是因為它們有額外的好處,可略過不明欄位,這對於回溯和前向相容性來說相當實用。由於任何在 Fuchsia 上執行的執行階段都已提供 FIDL 繫結,因此您可以輕鬆整合程式碼,且不需要額外支援剖析或轉換作業。

ComponentDecl 的結構沒有預設值,換句話說,只有在欄位不適用或來自不含該欄位的資訊清單版本時,才會未填入欄位。此外,為了支援向前和向後相容性,ComponentDecl 和其中巢狀結構體為 FIDL 資料表FIDL 彈性聯集

CML:元件資訊清單前端

CML (「元件資訊清單語言」) 是元件資訊清單的原始格式。這類檔案的設計目的是供人類閱讀及編寫,但也可能由格式化工具和語言伺服器等開發工具閱讀及編寫。

  1. 初學者只要瞭解基本元件架構概念,就能閱讀這份文件。
  2. 應可輕鬆呈現常見的模式,而不會產生過多的模板。
  3. 變更會影響語法,但不會影響資訊清單的語義意義,且不必變更資訊清單的二進位表示法。舉例來說,從單例陣列變更為單一值,不應影響輸出結果。
  4. 應可提升可維護性。特別是允許留言。
  5. 應足以支援自動轉換,例如支援大規模的重構。

CML 的設計目標就是為了達成這些目標。CML 是一種以 JSON5 為基礎的設定語言,可做為產生 ComponentDecl 的簡易 DSL。透過使用 JSON5,CML 可運用許多開發人員熟悉的語言,並廣泛用於 Fuchsia 的其他部分。與 ComponentDecl 不同,CML 提供一些可讓您更簡潔地編寫資訊清單的功能:

  • 可讓系統略過部分欄位的預設值。
  • 只要多個功能共用相同的選項,就能將這些功能群組成單一宣告。
  • 這可讓資訊清單包含資訊清單碎片,為資訊清單提供內容。舉例來說,您可以依附程式庫並納入程式庫的分片,取得該程式庫所需的所有功能。

最後,從 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 文件。
  • borgcfgGCLborgmon:Google 使用的功能性設定語言,大致類似於 Kubernetes,其歷史記錄有助於我們瞭解命令式和宣告式語法的取捨。

附註


  1. 日後,資訊清單很可能需要支援某種參數化功能,以便支援變數和產品設定功能。在這種情況下,我們應採取避免參數化設定常見陷阱的方法。 

  2. 如需進一步瞭解這項功能,Kubernetes 有詳細的說明文件,說明非宣告式設定的許多缺點。