🖼 背景
Protocol Buffers のコード生成だけなら Homebrew でインストール可能な protoc コマンドさえあればいいが、
$ brew install protobuf $ protoc --version libprotoc 3.6.0
gRPC コードを生成するなら grpc_cpp_plugin が必要となる。
$ which grpc_cpp_plugin /usr/local/bin/grpc_cpp_plugin
残念なことに Homebrew や go get ではインストールできず、Mac で make build, make install しなければならない。
WARNING: After installing with make install there is no easy way to uninstall, which can cause issues if you later want to remove the grpc and/or protobuf installation or upgrade to a newer version.
make を使う方式だと公式ドキュメントにも「一度インストールしてしまえば削除するのは難しいからアップグレードのときとか困るよ」と書いてある…。
🌿 環境を汚さずに Docker でコード生成を行う
上のやり方を試したところ確かに C++ コードの生成はできたが、イケてないので Docker を使ってコード生成することにする。
前提として下記のようなディレクトリ構成にした。protobuf ディレクトリにいろんな .proto ファイルが配置されていて、codegen ディレクトリに生成コードを出力。Dockerfile とスクリプトは tools ディレクトリに置いた。
project
├── protobuf
│ └── rpc
│ ├── auth
│ │ └── auth.proto
│ ├── rpc.proto
│ ├── setting
│ │ └── language.proto
│ └── user
│ └── user.proto
├── codegen
│ └── .gitkeep
└── tools
└── Dockerfile
│
└── gen_grpc_cpp.sh
🐳 Dockerfile
gRPC 公式が C++ 用の Docker イメージを公開しているのでそれを使う。
docker run すると bash が起動するので protoc と grpc_cpp_plugin が使えることがわかる。
$ docker run -it --rm grpc/cxx root@55d8450a784e:/# protoc --version libprotoc 3.5.0 root@55d8450a784e:/# which grpc_cpp_plugin /usr/local/bin/grpc_cpp_plugin
この Docker イメージを利用した Docker ファイルが下記。
ホストの ./protobuf ディレクトリをコンテナの /workspace/protobuf ディレクトリへすべてコピーし、コンパイルを実行している。gRPC コードを生成する場合は --grpc_out オプションを使う必要がある。
末尾で対象ファイルを指定しているが **/*.proto で再帰的に配下のディレクトリすべてを対象に加えてほしいところだけど、そうは動作してくれないので、階層数に応じて複数ディレクトリを愚直に指定している。
🐚 tools/gen_grpc_cpp.sh
上記の Docker イメージを使うシェルスクリプトを書いた。流れとしては、
- Docker ビルド
- Docker 実行
- コンテナのファイルをホストにコピー
- 後始末
3番のコンテナ内のファイルをホスト(Mac)にコピーするには docker cp を使うしかないため、このシェルスクリプトが必要となる。もしこのコピーが Dockerfile に記述できるようになれば Docker 実行だけでコード生成&コピーできるようになるが、今の所できないようだ。