遷移指南

庫版本中的破壞性更改列表,以及如何更新程式碼以適應這些更改。

v34.0 中的更改

以下是庫版本中破壞性更改的列表,以及如何更新程式碼以適應這些更改。

這涵蓋了在v34.x 新聞公告v34.0 釋出說明中宣佈的破壞性更改。

C++ 的變更

C++ 在 7.34.0 版本中將其主版本號提升至 7。6.33 是 6.x 系列的最後一個次要版本。

刪除未來宏

以下用於破壞性更改分階段推出的宏已被刪除,其行為現在是預設行為

  • PROTOBUF_FUTURE_RENAME_ADD_UNUSED_IMPORT
  • PROTOBUF_FUTURE_REMOVE_ADD_IGNORE_CRITERIA
  • PROTOBUF_FUTURE_STRING_VIEW_DESCRIPTOR_DATABASE
  • PROTOBUF_FUTURE_NO_RECURSIVE_MESSAGE_COPY
  • PROTOBUF_FUTURE_REMOVE_REPEATED_PTR_FIELD_ARENA_CONSTRUCTOR
  • PROTOBUF_FUTURE_REMOVE_MAP_FIELD_ARENA_CONSTRUCTOR
  • PROTOBUF_FUTURE_REMOVE_REPEATED_FIELD_ARENA_CONSTRUCTOR

新的 RepeatedPtrField 佈局

RepeatedPtrField 已轉換為新的內部元素佈局,其中元素儲存在預分配記憶體的連續塊中,類似於 std::deque。這導致一些 API 的複製/移動語義發生了一些變化,並且一些 UnsafeArena API 可能會成為其 arena-safe 對應物的函式等價物並被棄用。

RepeatedField::Get 和 RepeatedPtrField::Get 上的 MSB 硬化檢查

透過為重複欄位訪問新增全面的邊界檢查,Protobufs 針對 OOB 錯誤進行了強化。

從 Repeated/Map 欄位中刪除啟用 Arena 的建構函式

RepeatedField(Arena*)RepeatedPtrField(Arena*)Map(Arena*) 建構函式已被刪除。

移除已棄用的 API

我們刪除了以下公共執行時 API。

AddUnusedImportTrackFile() 和 ClearUnusedImportTrackFiles()

API: AddUnusedImportTrackFile(), ClearUnusedImportTrackFiles()

替代: AddDirectInputFile()ClearDirectInputFiles()

來自訊息差異器的 AddIgnoreCriteria

PROTOBUF_FUTURE_REMOVE_ADD_IGNORE_CRITERIA 是為破壞性更改而新增的。我們刪除了該宏。

API: AddIgnoreCriteria()

替代: 將原始指標包裝在 unique_ptr 中。

FieldDescriptor::has_optional_keyword()

API: FieldDescriptor::has_optional_keyword()

替代: has_presence()

FieldDescriptor::label()

API: FieldDescriptor::label()

替代: is_repeated()is_required()

FieldDescriptor::is_optional()

API: FieldDescriptor::is_optional()

替代: !is_required() && !is_repeated()

UseDeprecatedLegacyJsonFieldConflicts()

API: UseDeprecatedLegacyJsonFieldConflicts()

替代: 無替代。

更嚴格的名稱長度限制

Protobuf 編譯器對欄位名稱等符號名稱的長度實施了更嚴格的限制,以防止潛在問題。如果任何欄位名稱的長度 > 2^16,則會生成錯誤。

在 CMake 中隱藏私有生成器標頭檔案

protoc 生成器標頭檔案不再由 CMake 安裝。這不應影響大多數使用者。

邏輯常量操作上的 [[nodiscard]]

[[nodiscard]] 已新增到多個邏輯常量 protobuf API 中,如果未能使用返回的值,則表明可能存在錯誤。這遵循 C++ 標準庫中常用的模式。

Python 中的變更

Python 在 7.34.0 版本中將其主版本號提升至 7。6.33 是 6.x 系列的最後一個次要版本。

放棄 Python 3.9 支援

支援的最低 Python 版本是 3.10。使用者應升級。

放寬毒丸警告

我們放寬了毒丸。對於 7.34.x 的舊生成檔案,不再發出警告或錯誤。

在不正確的 Timestamp 或 Duration 轉換時引發 TypeError

現在,當將不正確的型別轉換為 TimestampDuration 時,我們不再引發 AttributeError,而是引發 TypeError

拒絕布林值轉換為列舉和 int 欄位

我們現在拒絕將布林值設定為 enumint 欄位。API 會引發錯誤而不是隱式轉換它們。

從 json_format 中刪除 float_precision

我們從 json_format 序列化器中刪除了已棄用的 float_precision 選項。此選項不存在於其他 ProtoJSON 序列化器中,並且具有令人困惑的語義。

從 text_format 中刪除 float_format/double_format

我們從 text_format 中刪除了已棄用的 float_formatdouble_format 選項。這些選項在其他 proto 文字格式序列化器中不可用。

已刪除的已棄用 API

我們刪除了以下公共執行時 API。

FieldDescriptor.label

API: FieldDescriptor.label

替代: is_repeated()is_required()

PHP 中的更改

PHP 在 5.34.0 版本中將其主版本號提升至 5。4.33 是 4.x 系列的最後一個次要版本。

放棄 PHP 8.1 支援

支援的最低 PHP 版本是 8.2。使用者應升級。

已刪除的已棄用 API

我們刪除了以下公共執行時 API。

FieldDescriptor getLabel

API: FieldDescriptor getLabel

替代: isRepeated()isRequired()

Google\Protobuf\Field_Kind

API: Google\Protobuf\Field_Kind

替代: Google\Protobuf\Field\Kind

Google\Protobuf\Field_Cardinality

API: Google\Protobuf\Field_Cardinality

替代: Google\Protobuf\Field\Cardinality

Google\Protobuf\Internal\RepeatedField

API: Google\Protobuf\Internal\RepeatedField

替代: Google\Protobuf\RepeatedField

修復預設值被靜默忽略的問題

PHP 執行時已修復,以在 proto2 和 editions 中的標量欄位上遵循預設值,而不是靜默忽略它們。

型別檢查對齊

純 PHP 和 upb-PHP 實現的型別檢查已對齊。值得注意的是,純 PHP 現在拒絕字串欄位的 null,與 upb-PHP 的行為匹配。

Objective-C 中的變更

Objective-C 在 5.34.0 版本中將其主版本號提升至 5。4.33 是 4.x 系列的最後一個次要版本。

可空性註解

某些 GPB*Dictionary API 的可空性註解已更正,以標記 API 何時可以返回 nil。這導致 Swift 程式碼獲得 Swift Optional。對於 Objective-C 呼叫者,註解更正不太可能對原始碼產生任何影響。

已刪除的已棄用 API

我們刪除了以下公共執行時 API。

GPBFieldDescriptor optional

API: -[GPBFieldDescriptor optional]

替代: !required && fieldType == GPBFieldTypeSingle

其他變更

放棄 Bazel 7 支援

支援的最低 Bazel 版本是 8,這將預設從 WORKSPACE 更改為 Bzlmod。使用者應升級到 Bazel 8 或更高版本並遷移到 Bzlmod。

Bazel:刪除已棄用的 ProtoInfo.transitive_imports

ProtoInfo 中已棄用的 transitive_imports 欄位已刪除。使用者應遷移到 transitive_sources

刪除 protobuf_allow_msvc 標誌並繼續支援 Bazel+MSVC

由於 Bazel 在 Windows 上的最新改進,我們現在繼續支援 Bazel+MSVC。--define=protobuf_allow_msvc 標誌已刪除。

v30.0 中的更改

以下是庫版本中破壞性更改的列表,以及如何更新程式碼以適應這些更改。

這涵蓋了在v30.x 新聞公告v30.0 釋出說明中宣佈的破壞性更改。

C++ 的變更

將 CMake 子模組替換為獲取的依賴項

以前,我們的預設 CMake 行為是使用 Git 子模組來獲取固定的依賴項。指定 -Dprotobuf_ABSL_PROVIDER=package 會將我們的 CMake 配置翻轉為查詢 Abseil 的本地安裝(jsoncpp 和 gtest 也有類似選項)。這些選項不再存在,預設行為是首先查詢所有依賴項的安裝,如果需要,再從 GitHub 獲取固定版本。

要防止任何回退獲取(類似於舊的 package 行為),您可以呼叫 CMake,如下所示

cmake . -Dprotobuf_LOCAL_DEPENDENCIES_ONLY=ON

始終從固定版本獲取依賴項(類似於舊的預設行為),您可以呼叫 CMake,如下所示

cmake . -Dprotobuf_FORCE_FETCH_DEPENDENCIES=ON

string_view 返回型別

以下描述符 API 的返回型別現在是 absl::string_view,這節省了記憶體

  • MessageLite::GetTypeName
  • UnknownField::length_delimited
  • 描述符 API 名稱函式,例如 FieldDescriptor::full_name

我們預計未來的破壞性版本將繼續將其他 API 遷移到 absl::string_view

在大多數情況下,您應該嘗試在安全的情況下更新型別以使用 absl::string_view,或者在需要時顯式複製到原始型別。如果函式返回此值,您可能還需要更新呼叫者。

如果受影響的 API 方法返回的字串用作

型別遷移

std::string

顯式轉換為 std::string 以保留現有行為。

或者,切換到效能更好的 absl::string_view

const std::string&

遷移到 absl::string_view

如果不可行(例如由於大量依賴項),複製到 std::string 可能會更容易。

const std::string*

const char*

如果可空,遷移到 std::optional

否則,遷移到 absl::string_view

呼叫 data() 時要小心,因為 absl::string_view 不保證以 null 結尾。

對於常見的容器和其他 API,您可能可以遷移到與 absl::string_view 相容的變體。以下是一些常見示例。

類別遷移前遷移
插入到 std::vector

push_back()

push_front()

push()

emplace_back()

emplace_front()

emplace()

對映或集的插入

set.insert(key)

map.insert({key, value})

map.insert({key,
{value_params...}})

set.emplace(key)

map.emplace(key, value)

map.try_emplace(key,
value_params...)

對映或集的查詢

find()

count()

contains()

遷移到 Abseil 容器。

或者,定義一個透明比較器。

std::set>>
std::map>>

參見 https://abseil.io/tips/144

字串連線

operator+

operator+=

absl::StrCat()

absl::StrAppend()

無論如何,出於效能原因都推薦這些。參見 https://abseil.io/tips/3

另請參見 https://abseil.io/tips/1,獲取有關使用 absl::string_view 的一般提示。

停用 MSVC + Bazel

Windows 上的 Bazel 使用者應切換到使用 clang-cl,方法是將以下內容新增到其專案中,例如此示例

.bazelrc

common --enable_platform_specific_config build:windows
--extra_toolchains=@local_config_cc//:cc-toolchain-x64_windows-clang-cl
--extra_execution_platforms=//:x64_windows-clang-cl

MODULE.bazel

bazel_dep(name = "platforms", version = "0.0.10")
bazel_dep(name = "rules_cc", version = "0.0.17")

# For clang-cl configuration
cc_configure = use_extension("@rules_cc//cc:extensions.bzl", "cc_configure_extension")
use_repo(cc_configure, "local_config_cc")

WORKSPACE

load("//:protobuf_deps.bzl", "PROTOBUF_MAVEN_ARTIFACTS", "protobuf_deps")

protobuf_deps()

load("@rules_cc//cc:repositories.bzl", "rules_cc_dependencies", "rules_cc_toolchains")

rules_cc_dependencies()

rules_cc_toolchains()

BUILD

僅適用於需要與 Bazel 8 相容的使用者。

platform(
    name = "x64_windows-clang-cl",
    constraint_values = [
        "@platforms//cpu:x86_64",
        "@platforms//os:windows",
        "@bazel_tools//tools/cpp:clang-cl",
    ],
)

適用於需要與 Bazel 7 和 8 相容的使用者。

platform(
    name = "x64_windows-clang-cl",
    constraint_values = [
        "@platforms//cpu:x86_64",
        "@platforms//os:windows",
        # See https://github.com/bazelbuild/rules_cc/issues/330.
        "@rules_cc//cc/private/toolchain:clang-cl",
    ],
)

使用者還可以透過設定選擇退出標誌 --define=protobuf_allow_msvc=true 暫時消除錯誤,直到下一個破壞性版本。

或者,希望繼續使用 MSVC 的使用者可以切換到使用 CMake。這可以透過 Visual Studio 完成,或者透過向 CMake 命令列提供 MSVC 生成器。例如

cmake -G "Visual Studio 17 2022" -A Win64 .

ctype 從 FieldDescriptor 選項中移除

我們不再從 FieldDescriptor 選項中公開 ctype。您可以使用 v28 版本中新增的 FieldDescriptor::cpp_string_type() API 來代替它。

修改除錯 API 以編輯敏感欄位

Protobuf C++ 除錯 API(包括 Protobuf AbslStringify、proto2::ShortFormatproto2::Utf8FormatMessage::DebugStringMessage::ShortDebugStringMessage::Utf8DebugString)已更改為編輯用 debug_redact 註解的敏感欄位;這些 API 的輸出包含每個程序的隨機字首,並且不再可由 Protobuf TextFormat 解析器解析。使用者應採用新的編輯除錯格式以滿足大多數需要人類可讀輸出的情況(例如日誌記錄),或者考慮切換到二進位制格式進行序列化和反序列化。需要舊的可反序列化格式的使用者可以使用 TextFormat.printer().printToString(proto),但這不會編輯敏感欄位,因此應謹慎使用。

2024 年 12 月 4 日釋出的新聞文章中閱讀更多相關資訊。

已刪除的已棄用 API

我們刪除了以下公共執行時 API,這些 API 已被標記為棄用(例如 ABSL_DEPRECATED)至少一個次要或主要版本,並且已過時或已被替換。

API: Arena::CreateMessage

替代方案: Arena::Create

API: Arena::GetArena

替代方案: value->GetArena()

API: RepeatedPtrField::ClearedCount

替代方案: 遷移到 Arenas (遷移指南)。

API: JsonOptions

替代方案: JsonPrintOptions

放棄 C++14 支援

根據 Foundational C++ 支援矩陣,此版本放棄了 C++14 作為最低支援版本,並將其提高到 17。

使用者應升級到 C++17。

在 Arena 上清除 Oneof 訊息後引入 ASAN Poisoning

此更改添加了一個強化檢查,影響使用 Arenas 的 C++ protobuf。在 protobuf arena 上分配的 Oneof 訊息現在在除錯模式下被清除,並在 ASAN 模式下被 poisoning。呼叫 clear 後,將來嘗試使用該記憶體區域將在 ASAN 中導致崩潰,作為 use-after-free 錯誤。

此實現需要 C++17。

放棄我們的 C++ CocoaPods 釋出

我們放棄了自 v4.x.x 以來一直損壞的 C++ CocoaPods 釋出。C++ 使用者應直接使用我們的 GitHub 釋出

Python 中的變更

Python 的主版本從 5.29.x 提升到 6.30.x。

放棄 Python 3.8 支援

支援的最低 Python 版本是 3.9。使用者應升級。

刪除 bazel/system_python.bzl 別名

我們刪除了舊的 bazel/system_python.bzl 別名。

請移除對 system_python.bzl 的直接引用,轉而使用 protobuf_deps.bzl。如果您需要直接引用,請使用它在 v5.27.0 中移動到的 python/dist/system_python.bzl

欄位設定器驗證變更

Python 和 upb 的欄位設定器現在在 edition 2023 下驗證封閉列舉。用無效值更新的封閉列舉欄位會生成錯誤。

刪除已棄用的 py_proto_library 宏

protobuf.bzl 中已棄用的內部 py_proto_library Bazel 宏已刪除。它已被官方 py_proto_library 替換,後者在 v29.x 中已移至 bazel/py_proto_library 中的 protobuf。此實現以前在 v29.x 之前的 rules_python 中可用。

移除已棄用的 API

我們刪除了以下公共執行時 API,這些 API 已被標記為棄用至少一個次要或主要版本。

反射方法

API: reflection.ParseMessage, reflection.MakeClass

替代方案: message_factory.GetMessageClass()

RPC 服務介面

API: service.RpcException, service.Service, service.RpcController, and service.RpcChannel

替代方案: 從 2.3.0 版本開始,RPC 實現不應嘗試在此基礎上構建,而應提供程式碼生成器外掛,以生成特定於特定 RPC 實現的程式碼。

MessageFactory 和 SymbolDatabase 方法

API: MessageFactory.GetPrototype, MessageFactory.CreatePrototype, MessageFactory.GetMessages, SymbolDatabase.GetPrototype, SymbolDatabase.CreatePrototype, 和 SymbolDatabase.GetMessages

替代方案: message_factory.GetMessageClass()message_factory.GetMessageClassesForFiles()

GetDebugString

API: GetDebugString

替代方案

沒有替代方案。它只存在於 Python C++ 中,而該版本已不再發布。純 Python 或 UPB 不支援它。

Python map 欄位的 setdefault 行為變更

setdefault 類似於 ScalarMapdict,只是鍵和值都必須設定。setdefaultMessageMaps 拒絕。

Python 巢狀訊息類的 __qualname__ 包含外部訊息名稱

Python 巢狀訊息類 __qualname__ 現在包含外部訊息名稱。以前,巢狀訊息的 __qualname____name__ 結果相同,即不包含外部訊息名稱。

例如:

message Foo {
  message Bar {
    bool bool_field = 1;
  }
}
nested = test_pb2.Foo.Bar()
self.assertEqual('Bar', nested.__class__.__name__)
self.assertEqual('Foo.Bar', nested.__class__.__qualname__) # It was 'Bar' before

Objective-C 中的變更

這是 Objective-C 的第一個破壞性版本.

Objective-C 的主版本從 3.x.x 提升到 4.30.x。

全面修改未知欄位處理 API,棄用大多數現有 API

我們棄用了 GPBUnknownFieldSet 並將其替換為 GPBUnknownFields。新型別保留了原始輸入或 API 呼叫中未知欄位的順序,以確保在訊息重新寫入時保留排序的任何語義含義。

作為此項的一部分,GPBUnknownField 型別也有 API 更改,幾乎所有現有 API 都已棄用並添加了新 API。

已棄用的屬性 API

  • varintList
  • fixed32List
  • fixed64List
  • lengthDelimitedList
  • groupList

已棄用的修改 API

  • addVarint
  • addFixed32
  • addFixed64
  • addLengthDelimited
  • addGroup

已棄用的初始化器 initWithNumber:

新的屬性 API

  • type
  • varint
  • fixed32
  • fixed64
  • lengthDelimited
  • group

此型別以其值中的單個欄位編號建模,而不是將給定欄位編號的所有值分組。用於建立新欄位的 API 是 GPBUnknownFields 類上的 add* API。

我們還棄用了 -[GPBMessage unknownFields]。取而代之的是,有新的 API 來提取和更新訊息的未知欄位。

已刪除的已棄用 API

我們刪除了以下公共執行時 API,這些 API 已被標記為棄用至少一個次要或主要版本。

GPBFileDescriptor

API: -[GPBFileDescriptor syntax]

替代方案: 已過時。

GPBMessage mergeFrom:extensionRegistry

API: -[GPBMessage mergeFrom:extensionRegistry:]

替代方案: -[GPBMessage mergeFrom:extensionRegistry:error:]

GPBDuration timeIntervalSince1970

API: -[GPBDuration timeIntervalSince1970]

替代方案: -[GPBDuration timeInterval]

GPBTextFormatForUnknownFieldSet

API: GPBTextFormatForUnknownFieldSet()

替代方案: 已過時 - 使用 GPBTextFormatForMessage(),它包含任何未知欄位。

GPBUnknownFieldSet

API: GPBUnknownFieldSet

替代方案: GPBUnknownFields

GPBMessage unknownFields

API: GPBMessage unknownFields 屬性

替代方案: -[GPBUnknownFields initFromMessage:]-[GPBMessage mergeUnknownFields:extensionRegistry:error:]-[GPBMessage clearUnknownFields]

刪除用於舊生成程式碼的已棄用執行時 API

此版本刪除了支援 3.22.x 版本之前 Objective-C 生成程式碼的已棄用執行時方法。當舊的生成程式碼啟動時,庫還會發出執行時日誌訊息。

API: +[GPBFileDescriptor allocDescriptorForClass:file:fields:fieldCount:storageSize:flags:]

替代方案: 使用當前版本的庫重新生成。

API: +[GPBFileDescriptor allocDescriptorForClass:rootClass:file:fields:fieldCount:storageSize:flags:]

替代方案: 使用當前版本的庫重新生成。

API: +[GPBEnumDescriptor allocDescriptorForName:valueNames:values:count:enumVerifier:]

替代方案: 使用當前版本的庫重新生成。

API: +[GPBEnumDescriptor allocDescriptorForName:valueNames:values:count:enumVerifier:extraTextFormatInfo:]

替代方案: 使用當前版本的庫重新生成。

API: -[GPBExtensionDescriptor initWithExtensionDescription:]

替代方案: 使用當前版本的庫重新生成。

其他變更

毒丸警告

我們更新了“毒丸”,以便為在新的滾動升級策略下工作但將在下一個主要版本更新中中斷的舊生成程式碼 + 新執行時組合發出警告。例如,Python 4.x.x 生成程式碼應適用於 5.x.x 執行時,但會警告即將對 6.x.x 執行時造成的破壞。

C# 和 Ruby 中 UTF-8 強制執行的變更

我們添加了一個修復,以使 UTF-8 強制執行在不同語言中保持一致。字串欄位中包含錯誤非 UTF-8 資料的使用者可能會更早看到 UTF-8 強制執行錯誤。

Ruby 和 PHP 在 JSON 解析中的錯誤

我們修復了根據 JSON 規範,JSON 解析數字欄位中的字串時的不一致問題。

此修復未伴隨主要版本更新,但 Ruby 和 PHP 現在會對數字欄位中的非數字字串(例如 """12abc""abc")引發錯誤。v29.x 包含對這些錯誤情況的警告。

v22.0 中的編譯器更改

JSON 欄位名稱衝突

更改來源:PR #11349PR #10750

我們對欄位名稱衝突與 JSON 對映的處理方式進行了一些細微更改。在 proto3 中,我們部分放寬了限制,僅在欄位名稱產生區分大小寫的 JSON 對映(原始名稱的駝峰式)時才報錯。我們現在還檢查 json_name 選項,並對區分大小寫的衝突報錯。在 proto2 中,我們稍微收緊了限制,如果兩個 json_name 規範衝突,將報錯。如果隱式 JSON 對映(駝峰式)存在衝突,我們將在 proto2 中發出警告。

我們提供了一個臨時訊息/列舉選項來恢復舊行為。如果立即重新命名欄位不是您的選擇,請在特定訊息/列舉上設定 deprecated_legacy_json_field_conflicts 選項。此選項將在未來的版本中刪除,但會為您提供更多時間進行遷移。

v22.0 中 C++ API 的更改

4.22.0 對 C++ 執行時和 protoc 進行了破壞性更改,如8 月份宣佈

Autotools 關閉

更改來源:PR #10132

在 v22.0 中,我們從 protobuf 編譯器和 C++ 執行時中刪除了所有 Autotools 支援。如果您正在使用 Autotools 構建其中任何一個,則必須遷移到 CMakeBazel。我們有一些專用說明,用於使用 CMake 設定 protobuf。

Abseil 依賴

更改來源:PR #10416

從 v22.0 開始,我們明確依賴於 Abseil。這使我們能夠刪除大部分 stubs,這些 stubs 是從舊的內部程式碼分支出來的,後來成為 Abseil。存在許多細微的行為變化,但大多數對使用者應該是透明的。一些值得注意的更改包括

  • string_view - absl::string_view 已在我們的許多 API 中取代了 const std::string&。這最常用於輸入引數,使用者應該不會注意到任何變化。在少數情況下(例如虛擬方法引數或返回型別),使用者可能需要進行顯式更改才能使用新的簽名。

  • tables - 我們現在使用 Abseil 的 flat_hash_mapflat_hash_setbtree_mapbtree_set,而不是 STL set/map。這些更高效,並支援異構查詢。這對於使用者來說應該是大部分不可見的,但可能會導致一些與表排序相關的細微行為變化。

  • logging - Abseil 的日誌庫與我們的舊日誌程式碼非常相似,只是拼寫略有不同(例如,ABSL_CHECK 而不是 GOOGLE_CHECK)。最大的區別在於它不支援異常,並且在 FATAL 斷言失敗時將始終崩潰。(以前我們有一個 PROTOBUF_USE_EXCEPTIONS 標誌來切換到異常。)由於這些只在遇到嚴重問題時發生,我們認為無條件崩潰是合適的響應。

    日誌更改來源:PR #11623

  • 構建依賴項 - 新的構建依賴項總是會導致下游使用者的破壞。我們要求 Abseil LTS 20230125 或更高版本才能構建。

    • 對於 Bazel 構建,當從您的 WORKSPACE 執行 protobuf_deps 時,Abseil 將在固定的 LTS 版本上自動下載和構建。這應該是透明的,但如果您依賴於舊版本的 Abseil,則需要升級您的依賴項。

    • 對於 CMake 構建,我們將首先查詢由頂級 CMake 配置引入的現有 Abseil 安裝(參見說明)。否則,如果 protobuf_ABSL_PROVIDER 設定為 module(其預設值),我們將嘗試從我們的 git 子模組構建和連結 Abseil。如果 protobuf_ABSL_PROVIDER 設定為 package,我們將查詢預安裝的 Abseil 系統版本。

GetCurrentTime 方法中的更改

在 Windows 上,GetCurrentTime() 是系統提供的宏名稱。在 v22.x 之前,Protobuf 錯誤地刪除了 GetCurrentTime() 的宏定義。這使得 Windows 開發人員在包含 後無法使用該宏。從 v22.x 開始,Protobuf 保留了宏定義。這可能會破壞依賴於先前行為的客戶程式碼,例如如果他們使用表示式 google::protobuf::util::TimeUtil::GetCurrentTime()

要將您的應用程式遷移到新行為,請更改您的程式碼以執行以下操作之一

  • 如果定義了 GetCurrent 宏,則顯式取消定義 GetCurrentTime
  • 透過使用 (google::protobuf::util::TimeUtil::GetCurrentTime)() 或類似表示式來阻止宏擴充套件

示例:取消定義宏

如果您不使用 Windows 宏,請使用此方法。

之前

#include <google/protobuf/util/time_util.h>

void F() {
  auto time = google::protobuf::util::TimeUtil::GetCurrentTime();
}

之後

#include <google/protobuf/util/time_util.h>
#ifdef GetCurrentTime
#undef GetCurrentTime
#endif

void F() {
  auto time = google::protobuf::util::TimeUtil::GetCurrentTime();
}

示例 2:阻止宏擴充套件

之前

#include <google/protobuf/util/time_util.h>

void F() {
  auto time = google::protobuf::util::TimeUtil::GetCurrentTime();
}

之後

#include <google/protobuf/util/time_util.h>

void F() {
  auto time = (google::protobuf::util::TimeUtil::GetCurrentTime)();
}

C++20 支援

更改來源:PR #10796

為了支援 C++20,我們已在 C++ 生成的 protobuf 程式碼中保留了新的 關鍵字。與其他保留關鍵字一樣,如果您將它們用於任何欄位、列舉或訊息,我們將新增下劃線字尾以使其成為有效的 C++。例如,concept 欄位將生成 concept_() getter。如果您有使用這些關鍵字的現有 proto,則需要更新引用它們的 C++ 程式碼以新增相應的下劃線。

最終類

更改來源:PR #11604

作為強化 Protobuf 庫中假設的更廣泛工作的一部分,我們已將一些從未打算繼承的類標記為 final。目前沒有已知的使用案例來繼承這些類,這樣做可能會導致問題。如果您的程式碼正在繼承這些類,則沒有緩解措施,但如果您認為您有使用繼承的一些有效理由,您可以提出問題

容器靜態斷言

更改來源:PR #11550

作為強化 Protobuf 庫中假設的更廣泛工作的一部分,我們已將靜態斷言新增到 MapRepeatedFieldRepeatedPtrField 容器中。這些確保您僅使用這些容器和預期型別,如我們的文件中所述。如果您遇到這些靜態斷言,則應遷移您的程式碼以使用 Abseil 或 STL 容器。std::vector 是重複欄位容器的良好直接替換,而 std::unordered_mapabsl::flat_hash_mapMap 的良好直接替換(前者提供類似的指標穩定性,而後者更高效)。

已清除元素棄用

更改來源:PR #11588PR #11639

關於“已清除欄位”的 RepeatedPtrField API 已被棄用,並將在以後的破壞性版本中完全刪除。這最初是作為在清除元素後重復使用元素的最佳化而新增的,但最終效果不佳。如果您正在使用此 API,您應該考慮遷移到 arenas 以獲得更好的記憶體重用。

UnsafeArena 棄用

更改來源:PR #10325

作為刪除 arena-unsafe API 的更廣泛工作的一部分,我們隱藏了 RepeatedField::UnsafeArenaSwap。這是我們目前刪除的唯一一個,但在以後的版本中,我們將繼續刪除它們並提供幫助程式來處理 arena 之間高效的借用模式。在單個 arena(或棧/堆)中,SwapUnsafeArenaSwap 一樣高效。好處是如果您不小心在不同的 arena 之間呼叫它,它不會導致無效的記憶體操作。

對映對升級

更改來源:PR #11625

對於 v22.0,我們已開始清理 Map API,使其與 Abseil 和 STL 更加一致。值得注意的是,我們已將 MapPair 類替換為 std::pair 的別名。這對於大多數使用者應該是透明的,但如果您直接使用該類,您可能需要更新程式碼。

新 JSON 解析器

更改來源:PR #10729

我們在此版本中重寫了 C++ JSON 解析器。它應該主要是隱藏的更改,但不可避免地一些未記錄的怪癖可能會發生變化;請相應地進行測試。解析不符合 RFC-8219 JSON 的文件(例如缺少引號或使用非標準布林值的文件)已被棄用,並將在未來版本中刪除。欄位的序列化順序現在保證與欄位編號順序匹配,而之前則不那麼確定。

作為此次遷移的一部分,util/internal 下的所有檔案都已刪除。這些檔案用於舊解析器,從未打算在外部使用。

Arena::Init

更改來源:PR #10623

Arena 中的 Init 方法是沒有任何作用的程式碼,現在已刪除。如果您正在呼叫此方法,您可能打算直接使用一組 ArenaOptions 呼叫 Arena 建構函式。您應該刪除該呼叫或遷移到該建構函式。

ErrorCollector 遷移

更改來源:PR #11555

作為我們 Abseil 遷移的一部分,我們正在從 const std::string& 轉向 absl::string_view。對於我們的三個錯誤收集器類,如果不破壞現有程式碼,這是無法完成的。對於 v22.0,我們決定釋出兩種變體,並將方法從 AddErrorAddWarning 重新命名為 RecordErrorRecordWarning。舊簽名已被標記為棄用,並且效率會略低(由於字串複製),但否則仍然有效。您應該將這些遷移到新版本,因為 Add* 方法將在以後的破壞性版本中刪除。