RFC-0246:API 級別為 32 位元

RFC-0246:API 級別為 32 位元
狀態已接受
領域
  • 一般
說明

將 API 級別重新定義為 32 位元數字,而非 64 位元

更小鳥
  • 1009253
作者
審查人員
提交日期 (年月分)2024-04-01
審查日期 (年-月-日)2024-04-29

摘要

本提案將 API 級別的定義變更為未簽署的 32 位元整數。這取代了 RFC-0002,其定義為未簽署的 64 位元整數。

提振精神

目前您可以在 target_api_level.gni 中找到以下程式碼 (已改寫,以便理解):

if (override_target_api_level == -1) {
    clang_fuchsia_api_level = 4294967295
    fidl_fuchsia_api_level = "LEGACY"
}

大致上來說,如果在 fuchsia.git 中建構時未指定 API 級別,clang_fuchsia_api_level 應設為 0xFFFFFFFF,而 fidl_fuchsia_api_level 應設為字串值 "LEGACY"。這個字串之後會由 fidlc 解譯為 0xFFFFFFFFFFFFFFFF 值的別名,如 RFC-0083 所定義。

這會帶來兩個問題:

  1. 其中有「clang API 級別」和「FIDL API 級別」,通常會有不同的值。
  2. API 級別有時是以字串表示,有時則是整數。

clang 與 FIDL 對比... ?

RFC-0002 將 API 級別定義為 64 位元整數,後續的 RFC 已分配特定的 64 位元整數並為其命名與意義。舉例來說,LEGACY 是由 0xFFFFFFFFFFFFFFFF 識別。但根據上述程式碼,我們會改為將 0xFFFFFFFF 傳遞至 Clang,因為在這種情況下,API 級別在 Clang 中受限於 32 位元。

但不是真的。

Clang 會透過 availability 屬性指出相容性的原因,而該屬性代表版本為 VersionTupleVersionTuple 會將一個代表版本的整數 major[.minor[.subminor[.build]]] 封裝成一個 128 位元結構,其中代表一個版本。在這個結構中,Fussia API 級別是「主要版本」的模型,因此限制為 32 位元。

Clang 是 Fuchsia 平台版本管理中至關重要的一環,因此必須解決這種不一致的問題。

stringint與... ?

主機工具和建構系統用於代表 API 級別的類型不一致。即使在 fuchsia.git 的建構系統中,還是如上述的程式碼區塊所示,也會不一致。

這不一定是問題,且此 RFC 無法完全解決問題。 然而,我們會嘗試提供指引,讓您瞭解這個差異。

相關人員

講師:abarth@google.com

審查者:

  • ddorwin@google.com
  • mkember@google.com
  • haowei@google.com

諮詢時間:

  • chaselatta@google.com
  • phosek@google.com
  • ianloic@google.com

社會化:

與平台版本管理工作小組成員和工具鍊團隊成員討論一項 Google 內部錯誤

相關規定

API 級別必須能夠以字串表示,包括兩行指令列,以及檔案和目錄的名稱。

API 級別必須完全排序,因此我們可以說:「Foo 是在 API 級別 N 新增,N <= M,因此 Foo 屬於 API 級別 M 的一部分」。

我們必須能夠為 API 級別指派特殊的名稱和行為。本節中的其他要求也適用於這些「特殊」API 級別。

設計

整數表示法

API 級別將重新定義為無正負號的 32 位元整數。

這個空間的下半部 (也就是 API 級別低於 0x80000000) 即為「一般」API 級別。這個空間的上半部已預留。這個 RFC 和日後的 RFC 將定義大於或等於 0x80000000 的特定值含義。

統一處理所有 API 級別的工具可能會忽略「一般」和保留值之間的差別,並將這些值全部視為未帶正負號的 32 位元整數,按照一般方式排序。

如果工具針對特定 API 級別採用特殊邏輯,則應拒絕輸入內容,指定無法解讀的保留 ABI 級別值。

字串表示法

API 級別可以使用多種不同方式的字串表示:

  • 任何在間隔 [0, 232] 中代表 Base-10 數字的 UTF-8 字串都是 API 級別的字串表示法 (例如 "7")。
  • 您可以使用大寫字母的名稱表示特殊 API 級別,例如 "HEAD"
  • 工具不應接受較容易理解的值 (例如 "0016""0x20"),因為這樣做可能會造成混淆。例如,"0016" 是八進位還是十進位?"2A" 可能是十六進位,但如果可接受,該值是 "29" 十六進位還是十進位?不過,字串剖析邏輯通常是由個別工具作者控制以外的程式庫處理,因此工具「可」接受這類值。

每個 API 級別都有一種標準字串表示法

  • 如為「一般」API 級別,以 Base-10 UTF-8 字串表示為標準格式 (例如 "13")。
  • 如為「特殊」API 級別,大寫字母的名稱就是標準名稱 (例如 "NEXT")。

如果工具需要知道 API 級別的標準字串表示法,且需要針對保留 API 級別 (也就是大於或等於 0x80000000) 取得無特殊名稱的標準表示法,就必須傳回錯誤。

特殊 API 級別

下列 API 級別為特殊名稱:

  • PLATFORM = 0xFFF00000 = 4293918720PLATFORM 會扮演 LEGACY 先前提供的角色,根據預設,平台會在 API 級別 PLATFORM 中建構。先前,LEGACY 在 FIDL 中具有 0xFFFFFFFFFFFFFFFF 值,且無法在 Clang 中表示。

    LEGACY 已由 RFC-0232 淘汰,並正從 FIDL 中移除,但在作業完成後,平台建構、C++ 和 Rust 程式碼也會使用 PLATFORM 偵測一般平台版本。

    PLATFORM 只有在同時用於 OS 版本和 IDK 一部分的程式碼中,才有實用價值。在這類程式庫中,如果目標 API 級別低於 PLATFORM,表示程式碼是建構在 SDK 的一部分,且只能使用版本指定特定 API 級別中可用的 API 元素。如果目標 API 級別等於 PLATFORM,表示程式碼將做為 OS 的一部分建構,且必須為「支援」或「停用」階段中的所有 API 級別提供支援。詳情請參閱 RFC-0239

  • HEAD = 0xFFE00000 = 4292870144。先前,HEAD 在 FIDL 中的值為 0xFFFFFFFFFFFFFFFE,Clang 中的 0xFFFFFFFF 值。

  • NEXT = 0xFFD00000 = 4291821568RFC-0239 中描述了 NEXT,但並未指派數值。

此組合可能會視需要隨著時間成長或縮小。

一開始,這些值會以硬式編碼的方式寫入支援指定 HEADNEXT 的 SDK,但最終應在 //sdk/version_history.json 中定義。

使用整數與字串的時機

指令列工具會接受輸入並產生字串的輸出內容,因此應接受上述 API 級別的任何字串表示法,並最好使用標準字串格式輸出 API 級別。不過,有時這個做法並不可行,或是非常不方便,因此您不需要使用標準字串表單。舉例來說,Clang 不知道特殊 Fuchsia API 級別的名稱,因此 -ffuchsia-api-level 的值必須以整數形式提供。

在建構工具的實作中,建議以整數形式儲存 API 級別。

建構系統可以透過最自然的方式表示 API 級別,對該建構系統而言最自然。

效能

這項異動不會影響成效。

回溯相容性

LEGACYHEAD 數值的變更不具回溯相容性,嚴格來說。不過,先前的 64 位元值實際上只能在 fidlc 內使用,而且基本上在 Fuchsia SDK 中無法向使用者顯示。

在理論上,SDK 使用者可以看到目前在 C++ 程式碼中將 HEAD 定義為 0xFFFFFFFF 的定義,但由於 Fuchsia 來源樹狀結構以外的程式碼目前指定的是 HEADLEGACY,因此這項變更也應該不會察覺。如預先提交,就會確認這點。

系統選擇了 PLATFORM 的新值 (先前為 LEGACY)、HEADNEXT 值,以在兩者之間提供大量落差。這樣一來,我們就可以建立其他特殊 API 級別,不必重新定義現有的 API 級別。我們建立的任何這類新 API 級別,都應在兩個相鄰的 API 級別之間加入一半。在最糟糕的情況下,我們可以細分每 20 次間隔。

安全性考量

這項變更應該不會影響安全性。

隱私權注意事項

這項異動不會影響隱私權。

測試

這個 RFC 主要與 Fuchsia 的建構系統和 SDK 中的程式碼相關。若是更好或更糟的是,很少有專門的自動測試程式碼。然而,在實務上,如果建構系統故障,在測試失敗、建構中斷和本機開發流程變差時,就會很快發現它。

說明文件

NEXTHEADPLATFORM 的含義和值,都將包含在 RFC-0239 中引入的概念說明文件中。

缺點、替代項目和未知

缺點:32 位元是否足夠?

如果採用依序配置的方式,即使每小時核發了新的 API 級別,該 RFC 以外的 231 API 級別大約需要 245,000 年才會用盡。好像已經足夠了。

不過,API 級別不一定需要密集分配。這個非常 RFC 定義了 3 個特別的 API 級別,各級別之間有 1048576 個未使用的 API 級別。不知道你方便嗎?

使用 64 位元 API 級別時,即使我們是在非常稀疏的情況下配置 (例如,因為使用 VersionTuple 時,在連續版本之間留下數千、數百萬或數十億個連續版本),就很難想像執行效能的可能性。

針對 32 位元 API 級別,我們在分配時必須更加謹慎。

我認為自己有可能成為歷史上大笑的庫存,我認為:232 API 級別應該足以滿足所有人的需求。

替代方法:改用 Major.Minor 配置

我們明確假設 VersionTuple.h 功能可在類似 12.5 (甚至是 30.1.2.3) 的版本中導入或移除。以此方式建構版本的平台可代表最多 21251 個不同版本。也許 Fuchsia 只能使用其中 232 個值,表示 Fuchsia 的版本管理機制不適當?

目前有多個平台成功讓 API 介面以單一整數版本 (例如 Chromium 和 Android)。沒有充分理由相信我們也無法 成功遵循相同的策略


  1. Clang 會使用每個 minorsubminorbuild 最重要的位元做為標記。