RFC-0106:Fuchsia SDK 中包含的元件資訊清單

RFC-0106:元件資訊清單包含 Fuchsia SDK 中的元件
狀態已接受
領域
  • 元件架構
說明

建立元件資訊清單,包括 SDK 中的資料分割 sysroot,並發布至樹狀結構外整合商。

問題
更小鳥
作者
審查人員
提交日期 (年月分)2021-05-12
審查日期 (年-月-日)2021-06-23

摘要

本文件建議將元件資訊清單資料分割至整合商開發套件 (IDK)。這項操作會建立將元件資訊清單資料分割至樹狀結構外 (OOT) 開發人員的標準用途,並建立一個通用模式,讓資訊清單資料分割可在不同的開發人員環境之間移植。

讀者應熟悉下列項目:

提振精神

讓不同環境的工作流程保持一致

自推出以來,元件資訊清單資料分割和 cmlcmx 中的 include 語法已出現廣泛採用。這些片段可用於各種工作,例如減少樣板封裝實作詳細資料簡化開發人員工作流程,以及核心運作領域

目前,資訊清單的處理機制包括採用 Fuchsia 樹狀結構的來源版面配置。這適用於位於 Fuchsia 樹系中的資訊清單,但無法順利移植到 OOT 的開發作業。以在 C/C++ 元件中記錄為例。系統會開啟本指南,指示開發人員將下列項目新增至元件資訊清單中:

{
  include: [ "sdk/lib/diagnostics/syslog/client.shard.cml" ],
}

不過,本指南指出上述操作僅適用於樹狀結構 (IT)。由於 OOT 開發人員也屬於本指南的目標對象,因此該指南會指示這些開發人員改為將以下內容新增到元件資訊清單中,有效內嵌資料分割的內容:

{
  use: [
    { protocol: "fuchsia.logger.LogSink" },
  ],
}

其他地方也出現了相同問題。例如測試執行器的測試執行器架構目錄 (用於支援 Fuchsia 上各種類型的測試,例如 C/C++ GoogleTest、Rust libtest、Gotest on Go 等) 提供了僅適用於 IT 的操作說明。這導致 OOT 開發人員無法做出良好的測試做法。

由於用戶端暴露在 Fuchsia 記錄的實作詳細資料中,這項入侵在一開始就擊敗了納入資訊清單資料分割的目的。除此之外,未來將更難以自動化調度管理未來的大規模變更,例如規劃未來要採用不同的通訊協定,以發布元件記錄。最後,這也讓 IT 和 OOT 開發人員的工作流程更加順暢。

隱藏實作詳細資料

如果我們重新查看 LogSink 資料分割範例,建議系統記錄程式庫的用戶端加入這個資料分割,因為這個資料分割會導入元件的沙箱,讓用戶端程式庫正常運作。

目前,這組功能並不簡單,只是一個通訊協定,但預計未來會有所改變。舉例來說,如果用戶端將通訊端連線至 Syslog,然後將字元緩衝至該通訊端,而在目前的通訊協定中,我們可能導入系統,將特殊格式的結構化資料寫入 VMO,並在用戶端和伺服器之間旋轉資料,這與現行追蹤的運作方式不同。

如果隱藏資料分割背後的這些詳細資料,可以降低元件作者的認知負載,因為元件作者只是想寫入 Syslog,並不關心這些細節。但這也可讓系統記錄維護人員隨著時間更新這些詳細資料,而不必注意元件擁有者。

這種做法的運作方式相反,也就是向元件公開功能,而不是取用這些功能,且具有不同類型的功能 (例如目錄功能而非通訊協定功能)。不妨參考這份檢查探索與託管指南。本指南會說明開發人員必須將下列項目新增至元件資訊清單中:

{
    capabilities: [
        {
            directory: "diagnostics",
            rights: [ "connect" ],
            path: "/diagnostics",
        },
    ],
    expose: [
        {
            directory: "diagnostics",
            from: "self",
            to: "framework",
        },
    ],
}

或者,開發人員也可以直接加入資料分割。這樣一來,開發人員就不必再處理 14 行樣板,必須處理多種概念,像是向架構公開目錄能力 (大多數元件開發人員不必熟悉的元件) 以及日後需要變更該機制的麻煩。最後,如果資料分割可在 IT 和 OOT 元件資訊清單之間移動,則檢查指南會大幅縮短,因為不需要為 IT 和 OOT 開發人員指定另一組操作說明。

簡化系統功能的用量

另一個較複雜的範例是,使用網路引擎時可能需要的各種功能,也就是以 FIDL 用戶端直接的身分,而非透過先前範例中的用戶端程式庫。網頁執行階段功能強大且強大,現今的網頁應用程式只要具備必要功能,就能執行許多特殊權限的裝置作業。fuchsia.web 定義了 Web 引擎實作所需的不同功能,才能代管特定網頁應用程式。

為了簡化從環境中使用相同功能,並提供給網路引擎的功能,我們使用資料分割來按照常見類別將這些功能細分。例如,這個資料分割定義了網路引擎需要的一組「資料表風險」功能:

{
    "sandbox": {
        "services": [
            "fuchsia.device.NameProvider",
            "fuchsia.fonts.Provider",
            "fuchsia.intl.PropertyProvider",
            "fuchsia.logger.LogSink",
            "fuchsia.memorypressure.Provider",
            "fuchsia.process.Launcher",
            "fuchsia.sysmem.Allocator",
        ]
    }
}

如果網頁應用程式並非本機且/或需要網路,這個資料分割會定義所需的額外功能:

{
    "sandbox": {
        "services": [
            "fuchsia.net.name.Lookup",
            "fuchsia.net.interfaces.State",
            "fuchsia.posix.socket.Provider"
        ]
    }
}

而需要此資料分割,才能在「景色」檢視畫面中算繪網頁應用程式:

{
    "sandbox": {
        "services": [
            "fuchsia.accessibility.semantics.SemanticsManager",
            "fuchsia.ui.input.ImeService",
            "fuchsia.ui.input.ImeVisibilityService",
            "fuchsia.ui.scenic.Scenic"
        ]
    }
}

已有其他資料分割用於解鎖圖形或硬體媒體轉碼器的硬體加速功能。

這些是非常重要的資訊。比起將容器放在專屬的資料分割中,比起將依附元件新增至元件沙箱中的其他服務層,其實更為簡單。此外,同樣的道理再次有助於改良程序。

請注意,此為假設範例。如今這些碎片已存在 IT 部門。此為將資料分割移至 IDK 使其可用 OOT 的可能性的探索,但不保證會如此。此外,上述資料分割的內容仍為流動版本,此處僅為說明用範例,但不做為參考文件。

實作

封裝資訊清單資料分割為 IDK 發布作業

如要開發以 Fuchsia 為目標的 C/C++ 開發作業,您可以將 include 路徑 (透過 --include-directory-I 標記指定至編譯器) 設定為一或多個目錄,這些目錄包含特別巢狀的子目錄和標頭檔案。如此一來,含有 Fuchsia 專用標頭的程式碼可在 IT 和 OOT 建構之間移植。

舉例來說,以下 C 行程式碼同時適用於 IT 和 OOT:

#include <lib/zx/process.h>

這是因為指定 Fuchsia 的 IT 版本和 OOT 版本都會將其加入目錄,路徑底下具有 lib/zx/process.h 檔案。在 Fuchsia 結帳時,對應的 include 目錄為 //zircon/system/ulib/zx/include/,在 OOT 建構中,這個路徑需要為 $FUCHSIA_SDK/pkg/zx/include/。另請參閱:IDK 版面配置

在 include 路徑中設定目錄,讓指令納入可攜碼轉移,也稱為設定「sysroot」。

我們也會以類似的方式,將元件資訊清單資料分割 (位於 $FUCHSIA_SDK/pkg/ 以下的子路徑中) 與資料分割用途有關,然後根據 IT 和 OOT 建構作業,在 cmc 中設定 --includepath 旗標。

例如,上方範例使用的 Syslog 資料分割可能如下:

  • 包含:include: [ "syslog/client.shard.cml" ]
  • 發現 //sdk/lib/syslog/client.shard.cml 下的 IT,因此要使用 --includepath $FUCHSIA_CHECKOUT/sdk/lib/ 設定 cmc IT。
  • $FUCHSIA_SDK/pkg/syslog/client.shard.cml 中找到 OOT,因此我們將使用 --includepath $FUCHSIA_SDK_ROOT/pkg/ 設定 cmc OOT。

可攜式資料分割與本機資料分割

有些資料分割僅供 OOT 開發人員使用,有些則只供 IT 使用。以上我們探討了一些可以使用 OOT 的資料分割僅有利於 IT 的資料分割就是一個範例:「這個資料分割」用於在兩個元件定義之間共用大量複雜的能力轉送,其中一個是系統元件,另一個則是該元件的測試替身。這個特定的資料分割 OOT 未使用。

因此,部分資料分割應設為可攜權並在 IDK 中發布,而其他資料分割則應僅授予特定存放區才能存取。

我們提議針對相對和絕對路徑,使用共同標記法來編寫這項差異。資訊清單 include 指令中使用的路徑應會解析為可攜式資料分割,不應有開頭的 //,例如 syslog/client.shard.cml。將會依據資料分割的 sysroot 進行解析。另一方面,如果是特定存放區只在本機的資料分割路徑,則路徑應以 // 開頭,並依據存放區的來源根 (或檢查根目錄) 進行解析。例如,請透過路徑 //src/sys/test_manager/meta/common.shard.cml這個資料分割納入 IT。

使用 cmc 建構系統整合

建構系統 (例如樹狀 GN 和 Ninja 建構),以及指定 Fuchsia 的樹狀結構外版本已與 cmc 整合。您必須修改這類整合作業,才能因應新的 include 行為。適用於下列 cmc 子指令

  • compile
  • include
  • check-includes

叫用 cmc 時必須指定下列標記:

  • --includeroot:解析前置字串 // 的路徑。
  • --includepath:按照指定順序 (第一個比對) 解析其他路徑的零或多個路徑。

以 SDK Atom 形式的資料分割

建構系統將像其他 IDK 元素的處理方式一樣,將資料分割納入 IDK 中。我們將重複使用現有的 sdk_atom() 範本,根據想要的 IDK 版面配置指定 id 參數。

將資料分割新增至 IDK 的程序

資料分割可指定可能會與平台介面重疊的合約期望。例如,系統記錄檔資料分割參照 Fuchsia 命名空間 (fuchsia.logger.LogSink) 中的通訊協定,這個通訊協定已知是由 Fuchsia 系統元件提供。因此,在 IDK 中發布的資料分割會視為 API 及 SDK Atom,並會透過目前用於新增或修改在 IDK 中發布的 FIDL 檔案一樣進行 API 審查。此外,您也可以使用類別的 sdk_atom() 概念,例如先將資料分割當做「內部」(而非分散式 OOT) 部署,然後透過現有程序將其提升為較高曝光類別。

未來工作

通訊埠 expect_includes()

Fuchsia 的 GN 建構作業提供的範本,可預期依附元件在資訊清單中包含特定資料分割 (請參閱這份指南)。這項做法的其中一個優點是,會引導開發人員將依附元件 (例如特定服務的用戶端程式庫) 納入元件中,並在元件中加入資訊清單資料分割,確保程式庫可以存取在執行階段正常運作所需的功能。

IT 開發人員對此提供非常正面的意見回饋,部分 OOT 開發人員對此抱持著意願。這個範本或概念可透過 GN 中繼資料移植到 GN SDK,以及使用 Bazel/Blaze SDK 使用 Bazel 規格或 Bazel 供應商。

另請參閱:https://fxbug.dev/42156975

效能

由於所有工作是在建構期間完成,因此本提案不會影響執行階段效能。

處理作業包括在建構階段處理,會增加一些額外工作。不過,這應該不會影響乾淨建構牆時間。我們從先前的研究得知,如果建構作業不在關鍵路徑上,通常不會導致建構延遲,而且直接從來源衍生的工作 (例如 cmc 叫用、fidlc 叫用等) 幾乎在關鍵路徑上幾乎沒有出現這種工作,因為這項工作可以順暢執行,而且這個工作彈性非常靈活。

例如,請考慮這項變更。在 cmc 中,一般作業速度約快 300 毫秒。然而,即使建構作業中有數千次 cmc 叫用,我們測量不到建構牆時間也沒有影響。

人體工學

我們致力讓資訊清單保有簡單透明的機制。舉例來說,您可以將包含指令的指令替換為內含檔案的內容,透過簡單的指令產生後處理的元件資訊清單。

fx cmc include manifest --includepath $(fx get-src-dir)

這類似於在 C/C++ 原始碼上執行 C 預先處理器 (請參閱 man cpp)。

此外,cmc 也會產生易於疑難排解的簡單錯誤,包括發生不尋常的錯誤情況 (例如加入週期)。所有支援的錯誤都會進行單元測試。

cmc 工具本身已隨附在 Fuchsia IDK 中。其結構完全隱密,並且在沒有任何外部依附元件的情況下執行。這可透過指令列叫用,不需要整合建構系統。

回溯相容性

在 IDK 中變更資料分割會在取得最新 IDK 版本後對新建的 OOT 元件造成影響,但不會影響舊的預先建構。請務必小心避免破壞性變更,並使用標準做法進行平台變更:在不同版本的軟性轉換、支援期,以及與相關人員溝通交流。

和平台演進的一切一樣,都應充分測試變更,並以容易造成破壞的方式管理破壞性變更 (例如使用某些版本管理機制)。請注意,針對平台版本管理及這個問題的部分問題 (例如 FIDL 版本管理),目前都會保持開啟狀態,且不在此 RFC 的涵蓋範圍內。

安全性考量

元件資訊清單會定義能力轉送和沙箱,它們會對安全性造成直接影響。不過,資訊清單包含的目標並非最終產生不同的資訊清單,而是要以更符合人體工學的方式產生相同的資訊清單。只要納入的最終資訊清單經過處理,就不會對安全性造成任何影響。

為協助開發人員瞭解資訊清單在處理後會是什麼樣子,可以使用上述的 cmc include

測試

cmc 中的現有功能已受到單元和整合測試的涵蓋範圍。cmc 的測試涵蓋範圍大於 90%,其中 include 子指令的涵蓋率已經完成。對於 Fuchsia IDK 或 OOT 整合所需的任何未改善變更,將依照 SDK 團隊的指示及預期進行測試。

在 CTS 測試涵蓋範圍內,IDK 中的元件資訊清單應視為任何其他 IDK 構件。

說明文件

include 語法已記載完畢。

cmc include 指令是透過 cmc help include 自行記錄。

目前指示 OOT 開發人員使用替換資訊清單的現有說明文件,將會更新,使其在不再需要時,不再依賴 IT 和 OOT 開發。

缺點、替代項目和未知

不執行任何動作

我們可以維持現狀,但不必解決上方動機一節中描述的問題。

將 IDK 中的資料分割整理為頂層構件

除了在 IDK 中各種可能位置發布元件資訊清單資料分割之外,例如在 $FUCHSIA_SDK_ROOT/pkg$FUCHSIA_SDK_ROOT/fidl 底下 (根據資料分割的邏輯關聯) 之外,我們也探索了另一種為元件資訊清單資料分割建立單一基本目錄的替代方案。例如:$FUCHSIA_SDK_ROOT/component_manifests/。這類似於所有 .fidl 檔案在 $FUCHSIA_SDK_ROOT/fidl/ 底下的分類方式,也就是是依類型 (屬於 FIDL 檔案) 匯總,而不是由其他邏輯關聯 (例如 pkg/async/pkg/memfs/pkg/zx/) 進行匯總。

我們根據 SDK 客戶的意見回饋,拒絕了這個替代方法,指出他們偏好使用 SDK 內容的邏輯關聯,而非將不同類型的檔案分散到不同的基本目錄中。接受的設計允許執行個體將元件資訊清單資料分割,以便使用 syslog,以便從以 C++ 編寫的元件寫入 syslog。

優先藝術與參考資料

元件資訊清單包含以 C/C++ 提供為靈感。

cmc include 指令是以 cpp 指令為靈感來源,這個指令會對指定檔案執行 C 預先處理工具,並列印後處理結果。請查看:man cpp