6.

protocの使い方|.protoのコンパイルと--proto_path・Go gRPC出力

編集
この記事の要点
  • protoc は Protocol Buffers のコンパイラで、.proto 定義から各言語のソースを生成する
  • 基本構文は protoc [オプション] [.proto ファイル]
  • --proto_path(または -I)で .proto 検索パスを指定する
  • 言語別出力は --cpp_out / --java_out / --python_out / --go_out 等。--go-grpc_out 等は別途プラグインのインストールが必要
  • `protoc` 単体では Go / gRPC コードは出ない。protoc-gen-goprotoc-gen-go-grpcgo install して PATH を通す

protoc とは

protocProtocol Buffers(protobuf)の公式コンパイラで、.proto 形式のスキーマ定義から、各種プログラミング言語のシリアライズ / デシリアライズコードを自動生成するコマンドラインツールです。gRPC のスタブコード生成にも使われます。

インストール

OSコマンド
macOS(Homebrew)brew install protobuf
Ubuntu / Debianapt install -y protobuf-compiler
Fedora / RHELdnf install protobuf-compiler
Windows公式 Releases から zip を取得し PATH を通す
各 OS(手動)github.com/protocolbuffers/protobuf/releases からダウンロード
# バージョン確認
protoc --version
# libprotoc 3.21.12

基本的な使用法

protoc [オプション] [.proto ファイル...]

シンプルな例

// helloworld.proto
syntax = "proto3";

package helloworld;
option go_package = "example.com/hello/pb";

message HelloRequest  { string name = 1; }
message HelloResponse { string message = 1; }

service Greeter {
  rpc SayHello(HelloRequest) returns (HelloResponse);
}
# Go コードを生成
protoc \
  --proto_path=. \
  --go_out=. --go_opt=paths=source_relative \
  helloworld.proto

# gRPC サーバ / クライアントスタブも生成
protoc \
  --proto_path=. \
  --go_out=. --go_opt=paths=source_relative \
  --go-grpc_out=. --go-grpc_opt=paths=source_relative \
  helloworld.proto

主要オプション

--proto_path(-I)

.proto ファイルを検索するディレクトリを指定します。複数指定でき、import 解決にも使われます。区切りは Linux / macOS は :、Windows は ; です。

# 単一
protoc -I=./proto file.proto

# 複数(Linux / macOS)
protoc -I=./proto:./vendor file.proto

# 別ディレクトリの proto を import する場合に必須
protoc -I=./api -I=./third_party/googleapis api/service.proto

--xxx_out(言語ごとの出力)

protoc が標準で対応している言語の出力先を指定します。

オプション対象言語
--cpp_out=DIRC++
--java_out=DIRJava
--python_out=DIRPython
--csharp_out=DIRC#
--ruby_out=DIRRuby
--php_out=DIRPHP
--objc_out=DIRObjective-C
--js_out=DIRJavaScript

--go_out / --go-grpc_out(プラグイン)

Go 向け生成は protoc 本体ではなくプラグインで提供されています。事前に Go ツールチェインで導入し、PATH を通す必要があります。

# Go 向けプラグインのインストール
go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest

# $GOPATH/bin にバイナリが入るので PATH を通す
export PATH="$PATH:$(go env GOPATH)/bin"

protoc はオプション名から protoc-gen-go のようなバイナリ名を逆算して呼び出すため、命名規則が固定です。

--descriptor_set_out

解析した結果をFileDescriptorSet(バイナリ形式の中間表現)として出力します。動的読み込みや gRPC サーバの reflection に使えます。

protoc \
  --include_imports \
  --descriptor_set_out=api.pb \
  api/service.proto

パスの考え方

オプション役割
-I / --proto_path入力 .proto を探す根
--xxx_out=DIR生成物の出力先
--xxx_opt=paths=source_relative生成パスを入力ファイル相対に保つ

buf との関係

近年は bufbuf.build)という protoc のラッパが普及しており、依存解決・lint・breaking change 検出を YAML で管理できます。新規プロジェクトでは buf を推奨する声も多いですが、内部では protoc を呼んでいるためオプションの理解は依然として重要です。

よくあるエラーと対処

エラー原因 / 対処
protoc-gen-go: program not found or is not executableGo プラグイン未インストール / PATH 未設定。go install 後に $(go env GOPATH)/bin を PATH に追加
File not found.-I で指定したパスが間違っている。proto ファイルのパスは -I からの相対で書く
Import "xxx.proto" was not found依存 proto がある場合、その場所も -I で指定する必要がある
Missing input file引数で .proto を渡し忘れ。シェルのワイルドカード(*.proto)が想定通り展開されているか確認
生成された Go コードに package が無い.proto 側で option go_package = "..."; を指定
古い protoc でビルドが通らないprotobuf ランタイムと protoc のバージョンを揃える。brew upgrade protobuf 等で更新

関連

編集
Post Share
子ページ

子ページはありません

同階層のページ
  1. go mod init
  2. go mod tidy
  3. go mod download
  4. go build
  5. go_package
  6. protoc

最近更新/作成されたページ