RFC-0246:API 級別為 32 位元 | |
---|---|
狀態 | 已接受 |
領域 |
|
說明 | 將 API 級別重新定義為 32 位元數字,而非 64 位元 |
更小鳥 | |
作者 | |
審查人員 | |
提交日期 (年月分) | 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 所定義。
這會帶來兩個問題:
- 其中有「clang API 級別」和「FIDL API 級別」,通常會有不同的值。
- API 級別有時是以字串表示,有時則是整數。
clang 與 FIDL 對比... ?
RFC-0002 將 API 級別定義為 64 位元整數,後續的 RFC 已分配特定的 64 位元整數並為其命名與意義。舉例來說,LEGACY
是由 0xFFFFFFFFFFFFFFFF
識別。但根據上述程式碼,我們會改為將 0xFFFFFFFF
傳遞至 Clang,因為在這種情況下,API 級別在 Clang 中受限於 32 位元。
但不是真的。
Clang 會透過 availability
屬性指出相容性的原因,而該屬性代表版本為 VersionTuple
。VersionTuple
會將一個代表版本的整數 major[.minor[.subminor[.build]]]
封裝成一個 128 位元結構,其中代表一個版本。在這個結構中,Fussia API 級別是「主要版本」的模型,因此限制為 32 位元。
Clang 是 Fuchsia 平台版本管理中至關重要的一環,因此必須解決這種不一致的問題。
string
對int
與... ?
主機工具和建構系統用於代表 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 = 4293918720
。PLATFORM
會扮演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 = 4291821568
。RFC-0239 中描述了NEXT
,但並未指派數值。
此組合可能會視需要隨著時間成長或縮小。
一開始,這些值會以硬式編碼的方式寫入支援指定 HEAD
或 NEXT
的 SDK,但最終應在 //sdk/version_history.json
中定義。
使用整數與字串的時機
指令列工具會接受輸入並產生字串的輸出內容,因此應接受上述 API 級別的任何字串表示法,並最好使用標準字串格式輸出 API 級別。不過,有時這個做法並不可行,或是非常不方便,因此您不需要使用標準字串表單。舉例來說,Clang 不知道特殊 Fuchsia API 級別的名稱,因此 -ffuchsia-api-level
的值必須以整數形式提供。
在建構工具的實作中,建議以整數形式儲存 API 級別。
建構系統可以透過最自然的方式表示 API 級別,對該建構系統而言最自然。
效能
這項異動不會影響成效。
回溯相容性
LEGACY
和 HEAD
數值的變更不具回溯相容性,嚴格來說。不過,先前的 64 位元值實際上只能在 fidlc
內使用,而且基本上在 Fuchsia SDK 中無法向使用者顯示。
在理論上,SDK 使用者可以看到目前在 C++ 程式碼中將 HEAD
定義為 0xFFFFFFFF
的定義,但由於 Fuchsia 來源樹狀結構以外的程式碼目前指定的是 HEAD
或 LEGACY
,因此這項變更也應該不會察覺。如預先提交,就會確認這點。
系統選擇了 PLATFORM
的新值 (先前為 LEGACY
)、HEAD
和 NEXT
值,以在兩者之間提供大量落差。這樣一來,我們就可以建立其他特殊 API 級別,不必重新定義現有的 API 級別。我們建立的任何這類新 API 級別,都應在兩個相鄰的 API 級別之間加入一半。在最糟糕的情況下,我們可以細分每 20 次間隔。
安全性考量
這項變更應該不會影響安全性。
隱私權注意事項
這項異動不會影響隱私權。
測試
這個 RFC 主要與 Fuchsia 的建構系統和 SDK 中的程式碼相關。若是更好或更糟的是,很少有專門的自動測試程式碼。然而,在實務上,如果建構系統故障,在測試失敗、建構中斷和本機開發流程變差時,就會很快發現它。
說明文件
NEXT
、HEAD
和 PLATFORM
的含義和值,都將包含在 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)。沒有充分理由相信我們也無法 成功遵循相同的策略
-
Clang 會使用每個
minor
、subminor
和build
最重要的位元做為標記。↩