RFC-0232:適用於多個 API 級別的 FIDL 繫結 | |
---|---|
狀態 | 已接受 |
領域 |
|
說明 | 啟用建構 FIDL 繫結,與多個 API 級別相容 |
問題 | |
毛皮變化 | |
作者 | |
審查人員 | |
提交日期 (年-月-日) | 2023-09-27 |
審查日期 (年-月-日) | 2023 年 10 月 24 日 |
摘要
今天產生 FIDL 繫結時,我們會在樹狀結構中指定 LEGACY
,
編號的 API 級別本文件旨在說明
已過時的 LEGACY
方法,可讓您一次指定多個 API 級別。這個
我們一開始只能用在樹狀結構中,但可能會遇到
這在樹狀結構中很實用
背景
從原始設計 FIDL 的版本管理中,您將無法移除
元素,同時保留對其 ABI 的支援。舉例來說,如果 CL 標示了方法
與 removed=5
一樣,還必須刪除該方法的實作。
這是因為我們已在 HEAD
上建構 Fuchsia 平台,以及此方法的伺服器
繫結不再存在於 HEAD
中,因為其超過 5 個。
為解決這個問題,我們修訂 RFC-0083 並
LEGACY
版本和 legacy
引數。LEGACY
版本就像 HEAD
。
否則會重新加入標示為 legacy=true
的元素。
提振精神
LEGACY
有幾個問題:
也就是本身沒有任何資訊的虛擬版本。繫結 凍結的 API 級別
N
包含屬於N
的所有 API,但LEGACY
包含任何看起來標示為removed
且帶有legacy=true
的項目 時 (除了HEAD
中的所有內容)。舊版支援須依個別 API 而定,且會隨時間改變。這個 也很難保證平台版本實際上可以支援 指定的舊版 API 級別
您無法指定特定 API 級別 (也就是
HEAD
以外的目標) 並包含舊版支援只解決一小部分相容性難題,也就是 Fuchsia 面臨的挑戰 平台是溝通的一面會說出各種通訊協定 但若是並非如此
這等同於 Fuchsia 單聲道存放區的權限,因此更難分割 以及發布流程之外的元件
相關人員
講師:abarth@google.com
審查人員:hjfreyer@google.com、wilkinsonclay@google.com、ddorwin@google.com
諮詢:Wez@google.com、sethladd@google.com
社交:我與 FIDL 團隊和平台討論了這個想法 在寫入 RFC 之前的版本管理工作群組。
設計
建議您在產生 FIDL 時一次指定多個 API 級別
繫結。舉例來說,使用 --available fuchsia:10,15
叫用 fidlc
目標 API 級別 10 和 15,導致繫結結合
兩個層級如果特定名稱元素的定義低於 10
而 15,我們使用第 15 級的定義,因為這是較新的版本。
這會遮蓋 LEGACY
版本。建構 Fuchsia 平台時
指定 LEGACY
繫結為目標,我們會指定支援的 API 級別組合。
也無需使用 legacy=true
標示個別 API。
詳細資料
移除
LEGACY
版本和@available
屬性的legacy
。將 fidlc 的
--available
指令列引數語法從<platform>:<target_version>
到<platform>:<target_versions>
,其中<target_versions>
是以逗號分隔的版本清單。例如:--available fuchsia:10
--available fuchsia:10,11
--available fuchsia:10,20,HEAD
<target_versions>
清單必須排序,且不得包含重複項目。 這是我們要強調的是,版本會產生線性歷史,之後 系統會優先處理各個版本<target_version>
清單決定了一組候選元素:如果符合以下情況,標示為
@available(added=A)
的元素就是候選元素<target_versions>
與{v | v >= A}
相交。標示為
@available(added=A, removed=R)
的元素是候選元素 如果<target_versions>
與{v | A <= v < R}
相交。請注意,這個 RFC 需視 RFC-0231: FIDL 版本管理取代模式運作 語法為確定候選元素 系統會將
replaced
視為與removed
相同。
如果 (1) 是候選元素,就會包含在繫結中。 名稱相同的所有候選字詞之間,
added
版本的成效最高。如果標示為
@available(..., deprecated=D, ...)
的元素包含在以下位置: 如果參照<target_versions>
與{v | v >= D}
相交。這不會影響 但日後可能會發生 (https://fxbug.dev/42156877)。和先前一樣,
--available
標記可以多次用於多個 平台。這兩項功能之間沒有顯著的互動 (多個平台和多個目標版本)。和先前一樣,編譯成功或失敗,必須在 主要程式庫平台的
--available
旗標。視實際情況而定, 其他平台依附元件的--available
旗標上。)例如: 如果使用--available fuchsia:15,16
編譯成功,則保證能 也成功運用--available fuchsia:10,100,HEAD
達成目標同樣地, 失敗則保證會失敗,並顯示相同的錯誤組合。建構 Fuchsia 平台時,將
--available fuchsia:LEGACY
替換為--available fuchsia:<target_versions>
(其中<target_versions>
包含所有項目) 執行階段支援的 API 級別、開發中 API 級別,以及HEAD
。
影響
這項設計可讓您針對指定
任意組合,無論程式庫如何隨著時間進化。
這項限制是重大的,因為 FIDL 版本管理可以代表任何
語法有效變更。具體來說,Fidlc 可包含多個
只要版本範圍不會重疊,即可使用相同名稱來共存。時間
<target_versions>
會包含多個此類元素,我們只加入
是最新的元素這支援三種一般的演化模式:
生命週期。元素為
added
,可能為removed
。我們會將它納入 繫結至任何版本。範例:@available(added=1, removed=5) flexible Method() -> ();
替換。元素為
added
,後置的replaced
和 不同的定義概念上來說,這代表單一元素 而不是兩個不同元素我們假設更換裝置的設計為 可與原始元素相容,並且只加入替換品 元素。範例:@available(added=1, replaced=5) flexible Method() -> (); @available(added=5) flexible Method() -> () error uint32;
名稱重複使用。元素設為
removed
後,其名稱即可重複用於新的added
元素。這與 replacement 類似,但這兩個元素 而且生命週期之間也有所差異我們會假設 偏好新的元素,且只將它納入繫結中。範例:@available(added=1, removed=5) flexible Method(); @available(added=10) flexible Method() -> ();
請注意,以這種方式重複使用元素名稱時,參照該元素無法 藉此跨越兩項定義舉例來說,這樣無法編譯:
@available(added=1, removed=5) type Args = struct {}; @available(added=10) type Args = table {}; @available(added=2) protocol Foo { Method(Args); // ERROR: 'Method' exists at versions 5 to 10, but 'Args' does not };
範例
請考慮使用以下 FIDL 程式庫:
@available(added=1)
library foo;
@available(replaced=2)
type E = strict enum { V = 1; }; // E1
@available(added=2)
type E = flexible enum { V = 1; }; // E2
@available(added=3, removed=6)
open protocol P {
@available(removed=4)
flexible M() -> (); // M1
@available(added=5)
flexible M(table {}) -> (); // M2
};
選取單一版本時,繫結中包含下列項目:
--available |
E1 | E2 | P | M1 | M2 |
---|---|---|---|---|---|
foo:1 |
✔︎ | ||||
foo:2 |
✔︎ | ||||
foo:3 |
✔︎ | ✔︎ | ✔︎ | ||
foo:4 |
✔︎ | ✔︎ | |||
foo:5 |
✔︎ | ✔︎ | ✔︎ | ||
foo:6 |
✔︎ | ||||
foo:HEAD |
✔︎ |
以下是選取多個版本時的內容:
--available |
E1 | E2 | P | M1 | M2 |
---|---|---|---|---|---|
foo:1,2 |
✔︎ | ||||
foo:1,HEAD |
✔︎ | ||||
foo:1,3 |
✔︎ | ✔︎ | ✔︎ | ||
foo:1,2,3 |
✔︎ | ✔︎ | ✔︎ | ||
foo:3,6 |
✔︎ | ✔︎ | ✔︎ | ||
foo:3,HEAD |
✔︎ | ✔︎ | ✔︎ | ||
foo:2,4,6 |
✔︎ | ✔︎ | ✔︎ | ||
foo:1,3,5 |
✔︎ | ✔︎ | ✔︎ | ||
foo:1,2,3,4,5,6,HEAD |
✔︎ | ✔︎ | ✔︎ |
實作
在 fidlc 中實作新的
--available
功能。一併變更 「可用」屬性,以便為版本使用字串陣列。變更所有現有的
legacy
引數,使其與新系統保持一致 (即 如在支援的最低 API 級別之前移除,則為false
;如果在系統支援的最低 API 級別之前移除,則設為true
「安全」標誌如果出現大幅差異 替代方法:覆寫機制。變更樹狀結構內平台版本,以產生指定全部的繫結 支援的 API 級別、開發中 API 級別和
HEAD
。移除 FIDL 檔案中的所有
legacy
引數。從 fidlc 移除
LEGACY
支援。
成效
此提案不會影響成效。
人體工學
本提案使 FIDL 版本管理變得更容易使用,因為沒有
不需要再擔心 legacy
引數
回溯相容性
本提案有助於達成 ABI 回溯相容性,因為 ABI 移除
個別 FIDL 程式庫作者提供 legacy=true
的負擔。此外,
能讓您更加瞭解我們先前「支援的 API 級別」組合,因為這些 API 的 API 級別
層級直接用於為平台產生繫結,(當然,到
請務必確保他們能接受測試)。
安全性考量
此提案不會影響安全性。
隱私權注意事項
此提案對隱私權沒有任何影響。
測試
必須先更新下列檔案,才能測試新行為:
- tools/fidl/fidlc/tests/availability_interleaving_tests.cc
- tools/fidl/fidlc/tests/decomposition_tests.cc
- tools/fidl/fidlc/tests/versioning_tests.cc
- tools/fidl/fidlc/tests/versioning_types_tests.cc
說明文件
下列說明文件頁面必須更新:
缺點、替代方案和未知
非問題:減少遷移的動機
這項提案可以視為減少 RFC-0002 中所述的獎勵計畫:
平台版本管理:遷移已淘汰的 API,因為
您可以指定多個層級,以存取新舊 API。不過,
「LEGACY
」已成為今日可使用的工具。就像花瓣一樣
今天LEGACY
,他們不能濫用這項新功能。
另外,花瓣粉透過 SDK 使用 fidlc,而不是直接叫用 只要使用 SDK 建構規則中的限制,即可緩解這種情況。舉例來說 可能會聲明目標版本字串不含半形逗號。
替代版本:版本範圍
與其允許使用任意版本組合,我們可能需 由兩個端點指定我拒絕這個替代方案的原因有幾個:
一旦決定提高 API 級別的執行頻率, 仍要能長期支援其中一部分的做法如此一來 代表差異,而非範圍
我們可能想要支援目標 API 級別的個別舊元件
N
,不需重新編譯。如果其他設定均已從 API 停用 第N
級至M
級別,我們可能出現{N+1, ..., M}
的落差。截至目前,尚未針對平台版本管理建構的任何項目都假設 從支援的 API 級別到 100 倍例如,version_history.json 包含 列出 API 級別,而非範圍
使用範圍而非組合不會讓 fidlc 實作更加容易。 可能會讓效率稍微提升,但不太在意 練習。還有許多可促進最佳化的測試成果應該是問題 成效自然成為一大問題
替代方法:覆寫機制
此提案的一個缺點,是難以更新所有程式碼 停止對 API 級別的支援時,就會以 fuchsia.git 建立。為了拆分 或是完成多個步驟,我們可能需要用更精細的方式 也會包含在繫結中您有以下幾個選擇:
覆寫個別
fidl
GN 目標中的<target_versions>
。新增排除元素的
@available
引數unsupported=true
即使該代碼通常會包含它這與legacy
類似,但 僅用於暫時 (最好)變更
--available
引數,以接受 JSON 檔案。除了<target_versions>
,可以提供完整的元素名稱清單, 納入或排除。
我拒絕這個替代版本,因為我們不清楚自己需要這項機制。 相反地,我們應該先嘗試透過單一 CL 進行變更。如果沒有 應該嘗試使用條件式編譯來階段變更 僅在停止對 API 級別的支援之前包含實作。如果 如果測試失敗,我們可以重新造訪上述覆寫機制。
此外,我們也可以提高 API 級別的步調來緩解這個現象, 可降低每個 API 級別移除的次數不過,此方法 ,且不在此提案中。
替代方法:將 legacy
預設為 true
這個替代方法可改善現狀。使用 false
做為預設值
忘記新增 legacy=true
可能會導致 ABI 中斷。以 true
做為
預設,忘記新增 legacy=false
只能導致 fidlc 編譯
錯誤或未使用的 API,較為嚴重的問題。
不過,這只是小幅變更,無法解決所有問題
相關單位。系統仍會根據 API 控制 legacy
狀態。
導致特定 API 級別的執行階段支援不一致,因而造成
難以判斷特定版本是否完整支援 API 級別。
既有藝術品和參考資料
Android SDK 可讓您指定 compileSdkVersion
和 minSdkVersion
。詳情請見
Android API 級別和 <uses-sdk>
說明文件。