バージョン 23.x のニュース発表
以下の発表はバージョン 23.x に固有のものです。時系列順の情報については、ニュースを参照してください。
Ruby ジェネレータの変更
この GitHub PR (23.x リリースに収録予定) は、Ruby コードジェネレータが DSL の代わりにシリアライズされた proto を出力するように変更します。
これは、DSL を別パッケージに分割することを想定して、コードジェネレータから DSL を削除します。
次のような .proto ファイルを考えると
syntax = "proto3";
package pkg;
message TestMessage {
optional int32 i32 = 1;
optional TestMessage msg = 2;
}
変更前の生成コード
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: protoc_explorer/main.proto
require 'google/protobuf'
Google::Protobuf::DescriptorPool.generated_pool.build do
add_file("test.proto", :syntax => :proto3) do
add_message "pkg.TestMessage" do
proto3_optional :i32, :int32, 1
proto3_optional :msg, :message, 2, "pkg.TestMessage"
end
end
end
module Pkg
TestMessage = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("pkg.TestMessage").msgclass
end
変更後の生成コード
# frozen_string_literal: true
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: test.proto
require 'google/protobuf'
descriptor_data = "\n\ntest.proto\x12\x03pkg\"S\n\x0bTestMessage\x12\x10\n\x03i32\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12\"\n\x03msg\x18\x02 \x01(\x0b\x32\x10.pkg.TestMessageH\x01\x88\x01\x01\x42\x06\n\x04_i32B\x06\n\x04_msgb\x06proto3"
begin
Google::Protobuf::DescriptorPool.generated_pool.add_serialized_file(descriptor_data)
rescue TypeError => e
# <compatibility code, see below>
end
module Pkg
TestMessage = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("pkg.TestMessage").msgclass
end
この変更により、以前に存在していた残りの適合性問題のほぼすべてが修正されます。これは、DSL (損失が多い) からシリアライズされた記述子 (すべての情報を保持する) に移行することの副作用です。
後方互換性
この変更は、2021年9月にリリースされた Ruby Protobuf >= 3.18.0 と 100% 互換性があるはずです。さらに、既存のすべてのユーザーとデプロイメントとも互換性があるはずです。
このレベルの後方互換性を実現するために挿入された特別な互換性コードがあり、注意が必要です。互換性コードがないと、後方互換性を損なう可能性のあるエッジケースがあります。以前のコードは緩い部分がありましたが、新しいコードはより厳密になります。
完全なシリアライズされた記述子を使用する場合、このファイルによってインポートされたすべての .proto
ファイルのリストが含まれます (一方、DSL は依存関係を適切に追加しませんでした)。descriptor.proto
のコードを参照してください。
add_serialized_file
は、記述子にリストされているすべての依存関係が、以前に add_serialized_file
で追加されたことを検証します。一般的に、これは問題ないはずです。なぜなら、生成されたコードにはすべての依存関係に対する Ruby require
ステートメントが含まれており、依存している型が DescriptorPool
で以前に定義されていない場合、記述子はとにかくロードに失敗するためです。
ただし、ファイルパスの曖昧さがある場合、問題が発生する可能性があります。たとえば、次のシナリオを考えてみましょう。
// foo/bar.proto
syntax = "proto2";
message Bar {}
// foo/baz.proto
syntax = "proto2";
import "bar.proto";
message Baz {
optional Bar bar = 1;
}
次のように protoc
を呼び出すと、正しく動作します。
$ protoc --ruby_out=. -Ifoo foo/bar.proto foo/baz.proto
$ RUBYLIB=. ruby baz_pb.rb
ただし、次のように protoc
を呼び出し、互換性コードがない場合、ロードに失敗します。
$ protoc --ruby_out=. -I. -Ifoo foo/baz.proto
$ protoc --ruby_out=. -I. -Ifoo foo/bar.proto
$ RUBYLIB=foo ruby foo/baz_pb.rb
foo/baz_pb.rb:10:in `add_serialized_file': Unable to build file to DescriptorPool: Depends on file 'bar.proto', but it has not been loaded (Google::Protobuf::TypeError)
from foo/baz_pb.rb:10:in `<main>'
問題は、bar.proto
が bar.proto
と foo/bar.proto
という 2 つの異なる正規名で参照されていることです。これはユーザーエラーです。各インポートは常に一貫したフルパスで参照される必要があります。このようなユーザーエラーはまれであることを願っていますが、試してみないとわかりません。
この変更のコードは、このエッジケースが発生したことを検出した場合、warn
を使用して警告を出力します。
$ RUBYLIB=foo ruby foo/baz_pb.rb
Warning: Protobuf detected an import path issue while loading generated file foo/baz_pb.rb
- foo/baz.proto imports bar.proto, but that import was loaded as foo/bar.proto
Each proto file must use a consistent fully-qualified name.
This will become an error in the next major version.
この場合、2 つの可能な修正方法があります。1 つは、インポートに bar.proto
という名前を一貫して使用することです (-I.
を削除)。もう 1 つは、インポートに foo/bar.proto
という名前を一貫して使用することです (インポート行を import "foo/bar.proto"
に変更し、-Ifoo
を削除)。
この互換性コードは、次のメジャーバージョンで削除する予定です。
Bazel 5.3 未満のサポート終了
v23 では Bazel 4 のサポートを終了します。Protobuf は、Bazel 5.3 を最小必須バージョンとして Bazel 5 LTS を引き続きサポートします。これは、Foundational C++ Support Policy に記載されているビルドサポートポリシー、および Foundational C++ Support のバージョンに反映されているとおりです。
構文リフレクションの非推奨
v23 では、リフレクションを使用して構文バージョンを確認する機能を非推奨にします。非推奨は、ビルド時の警告として含まれます。この機能は将来のリリースで削除されます。