直接仕事に関係はないけど、急に情報を集める必要が出てきた為 雑なメモとして。実際に手元で動かしているわけではないので、少なからず誤った記述をしていそう。
Androidでは標準ビルドツールとしてGradleを使うので、protobuf-gradle-plugin
を導入する。
これはローカルにあるprotocバイナリとのブリッジが主な仕事で、有効にするとGradleプロジェクト内のsourceSetに配置した .proto
をJavaクラスとしてコンパイル可能になる。
protocのバイナリをローカルに入れてない場合も考慮して、protobuf.protoc.artifact = 'com.google.protobuf:protoc:3.0.0'
などとしてMaven上のprotocを指定すると良い。
Androidはご存知のとおり一般的なJVMとは異なるRuntimeになっており、これをGoogleのProtobufチームは「制約のある実行環境」と呼んでいるらしい。このような環境を考慮して設計された "Lite" と呼ばれるモードがある。
Liteではprotocによる単なるコンパイルでのJavaクラス吐き出しではなく、
などが行われたものになる。現在この機能は protoc
自体に搭載されているため、Gradleプロジェクトの設定レベルでフラグを立てることで有効化できる。ただし上記のとおり外部のライブラリへ共通ロジックが切り出されている為、その記述は別途必要になる。
// https://github.com/google/protobuf-gradle-plugin#default-outputs def protobufVersion = '3.8.0' dependencies { implementation "com.google.protobuf:protobuf-javalite:${protobufVersion}" } protobuf { protoc { artifact = "com.google.protobuf:protoc:${protobufVersion}" } generateProtoTasks { all().each { task -> task.builtins { java { option "lite" } } } } }
ポイントは「現在この機能は protoc
自体に搭載されている」「外部のライブラリへ共通ロジックが切り出されている」の2点。protobuf-javalite
はあくまでも protoc
のLite機能用の内部APIが切り出されたライブラリという位置付けである為、protocの機能アップデート等によって決められたバージョニング規則がそのまま protobuf-javalite
にも設定される。両者は一体となって利用される前提である為、常に同じものが設定されなければいけない。
もしこれが異なるバージョンになった場合、protocのLiteモードで出力されたJavaクラスと、それが参照する protobuf-javalite
のAPIに齟齬が起きClassNotFound等の例外が発生する可能性がある。
なお、この protobuf-javalite
というライブラリは以前 protobuf-lite
というartifactだった。
<artifactId>protobuf-lite</artifactId>
これが2016年頃のリリース以来長いことアップデートされていなかったのだが、2019年6月頃にリリースされた 3.8.x
の時に protobuf-javalite
へと変更されている。
<artifactId>protobuf-javalite</artifactId>
即ち両者は単なるアップグレードであり、protobuf-lite
-> protobuf-javalite
という流れで移行されることが理想である。
またこの旧バージョンではprotoc内にliteのモードが同梱されていなかったため、codegenとして com.google.protobuf:protoc-gen-javalite:xxx
を指定していた。