RFC-0246:API 級別為 32 位元 | |
---|---|
狀態 | 已接受 |
區域 |
|
說明 | 將 API 級別重新定義為 32 位元數字,而非 64 位元 |
Gerrit 變更 | |
作者 | |
審查人員 | |
提交日期 (年-月-日) | 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,因為 Clang 中的 API 級別僅限於 32 位元。
這並非完全正確。
Clang 會透過 availability
屬性判斷相容性,該屬性會將版本表示為 VersionTuple
。VersionTuple
會將四個整數 major[.minor[.subminor[.build]]]
的元組 (代表版本) 打包至 128 位元結構體。在這個結構中,Fuchsia 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 級別可以透過字串以多種方式表示:
- 任何代表 10 進制數的 UTF-8 字串 (範圍為 [0, 232]) 都是 API 級別的字串表示法 (例如
"7"
)。 - 特殊 API 級別可用其名稱表示,且必須以大寫字母表示 (例如
"HEAD"
)。 - 工具不應接受
"0016"
或"0x20"
等較難解讀的值,因為這可能會造成模糊不清的情況。例如,"0016"
是八進位還是十進位?"2A"
可能是十六進位,但如果系統接受這個值,"29"
是十六進位還是十進位?不過,字串剖析邏輯通常由個別工具作者無法控制的程式庫處理,因此工具「可能」會接受這類值。
每個 API 級別都有一個標準字串表示法:
- 對於「一般」API 級別,十進制 UTF-8 字串表示法是標準的 (例如
"13"
)。 - 對於「特殊」API 級別,大寫的名稱是標準名稱 (例如
"NEXT"
)。
如果工具需要取得保留 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
。NEXT
已在 RFC-0239 中說明,但未指派數值。
這組格式字串可能會視需求隨著時間增加或減少。
這些值一開始會以硬式編碼方式寫入支援指定 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
,因此變更也應該不會被察覺。LSC 預提交作業會確認這一點。
我們選擇 PLATFORM
(先前為 LEGACY
)、HEAD
和 NEXT
做為新的值,以便在這些值之間保留明顯的差距。這樣一來,我們就能在不重新定義現有 API 級別的情況下,建立其他特殊 API 級別。我們建立的任何這類新 API 級別,都應在兩個相鄰 API 級別之間新增。在最糟的情況下,我們可以將每個間隔細分 20 次。
安全性考量
這項變更不會影響安全性。
隱私權注意事項
這項變更不會影響隱私權。
測試
這份 RFC 主要與 Fuchsia 的建構系統和 SDK 中的程式碼相關。無論好壞,對該程式碼的專屬自動化測試都很少。不過,在實際情況中,如果建構系統發生問題,系統會在測試失敗、建構作業中斷,以及本機開發流程出現異常時,很快就會察覺。
說明文件
NEXT
、HEAD
和 PLATFORM
的含義和值將納入 RFC-0239 中介紹的概念的即將推出的說明文件。
缺點、替代方案和未知事項
缺點:32 位元是否足夠?
如果依序分配,即使我們每小時發布一個新的 API 級別,也需要約 245,000 年才能用完此 RFC 中保留的 231 個 API 級別。這似乎就夠了。
不過,API 級別不一定需要密集分配。這份 RFC 定義了 3 個特殊 API 級別,每個級別之間有 1048576 個未使用的 API 級別。可以嗎?
使用 64 位元 API 級別時,即使我們分配的 API 級別非常稀疏 (例如,在連續版本之間保留數千、數百萬或數十億的間隔,就像 Clang 對 VersionTuple
所做的那樣),也難以想像會用完。
在 32 位元 API 級別中,我們必須更謹慎地分配資源。
我知道這樣會讓自己成為歷史笑柄,但還是要說:232 API 級別應該足以滿足所有人的需求。
替代做法:改用 Major.Minor 配置
VersionTuple.h
的編寫方式明確表明,功能可在類似 12.5
或 30.1.2.3
的版本中新增或移除。以這種方式建構版本的平台最多可代表 2125 個1 個獨立版本。或許 Fuchsia 只能使用這些值的 232,這表示 Fuchsia 的版本命名方案不適合?
多個成功的平台都會使用單一整數來為 API 途徑命名 (例如 Chromium 和 Android)。我們沒有足夠的理由相信,我們無法透過相同的策略取得成功。
-
Clang 會使用
minor
、subminor
和build
的最高位元做為標記。 ↩