目的
既存のgrpcプロジェクトで使用されているprotoファイルを、bazelをつかったC++プロジェクトにインクルードしたい。ただし、protoファイルは別リポジトリ(つまりbazel WORKSPACEの外)で管理されているので、そこにBUILDやWORKSPACEファイルを設置したくないという制約がある。
解決方法
WORKSPACEにnew_local_repositoryを追加する。
手順
1. WORKSPACEにnew_local_repositoryを追加する
WORKSPACEに以下を追記する
new_local_repository(
name = "proto",
path = "path/to/proto/dir",
build_file = "path/to/proto.BUILD",
)
nameはproto
としたが何でもよい。この名前のディレクトリにC++のヘッダーファイルが生成される。
path/to/proto/dir
がprotoファイルの場所であり、マニュアルによると絶対パスでなければならないと書いてあるが、bazel 4.0.0ではWORKSPACEからの相対パスでも動作した。
2. new_local_repository用のBUILDファイルを作成する
WORKSPACE配下の任意の場所(上記の例では path/to/proto.BUILD)BUILDファイルをつくる。
内容は通常のproto/grpcビルド用の内容でよい。
以下の内容はgrpc公式のgreeterサンプルを使う場合のもの。
package(default_visibility = ["//visibility:public"])
load("@rules_proto//proto:defs.bzl", "proto_library")
load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_proto_library")
load("@com_github_grpc_grpc//bazel:cc_grpc_library.bzl", "cc_grpc_library")
proto_library(
name = "helloworld_proto",
srcs = ["helloworld.proto"],
)
cc_proto_library(
name = "helloworld_cc_proto",
deps = [":helloworld_proto"],
)
cc_grpc_library(
name = "helloworld_cc_grpc",
srcs = [":helloworld_proto"],
grpc_only = True,
deps = [":helloworld_cc_proto"],
)
3. protoをインクルードしたい側のBUILDファイルの依存に追加
cc_binary(
name = "greeter_client",
srcs = ["greeter_client.cc"],
defines = ["BAZEL_BUILD"],
deps = [
"@proto//:helloworld_cc_grpc",
"@com_github_grpc_grpc//:grpc++",
],
)
new_local_repositoryのname
で指定した名前で @proto
のように参照できる。
4. C++ソースコードでインクルードする
#include "external/proto/helloworld.grpc.pb.h"
前述のように、name
のディレクトリにprotoの生成物ができる。externalディレクトリの配下になることに注意。
トラブルシューティング
ビルドが失敗するようなら、各ビルドステップ毎にビルドしてみるとよい
$ bazel build @proto//:helloworld_proto
INFO: Analyzed target @proto//:helloworld_proto (0 packages loaded, 0 targets configured).
INFO: Found 1 target...
Target @proto//:helloworld_proto up-to-date:
bazel-bin/external/proto/helloworld_proto-descriptor-set.proto.bin
INFO: Elapsed time: 0.138s, Critical Path: 0.01s
INFO: 2 processes: 1 internal, 1 processwrapper-sandbox.
INFO: Build completed successfully, 2 total actions
$ bazel build @proto//:helloworld_cc_proto
INFO: Analyzed target @proto//:helloworld_cc_proto (0 packages loaded, 0 targets configured).
INFO: Found 1 target...
Target @proto//:helloworld_cc_proto up-to-date:
bazel-bin/external/proto/helloworld.pb.h
bazel-bin/external/proto/helloworld.pb.cc
bazel-bin/external/proto/libhelloworld_proto.a
bazel-bin/external/proto/libhelloworld_proto.so
INFO: Elapsed time: 1.148s, Critical Path: 0.02s
INFO: 5 processes: 3 internal, 2 processwrapper-sandbox.
INFO: Build completed successfully, 5 total actions
$ bazel build @proto//:helloworld_cc_grpc
INFO: Analyzed target @proto//:helloworld_cc_grpc (0 packages loaded, 0 targets configured).
INFO: Found 1 target...
Target @proto//:helloworld_cc_grpc up-to-date:
bazel-bin/external/proto/libhelloworld_cc_grpc.a
bazel-bin/external/proto/libhelloworld_cc_grpc.so
INFO: Elapsed time: 0.652s, Critical Path: 0.03s
INFO: 5 processes: 3 internal, 2 processwrapper-sandbox.
INFO: Build completed successfully, 5 total actions
備考
- protoをおいてある場所にBUILDやWORKSPACEをおいてよいなら、
new_local_repository
ではなくlocal_repository
をつかうとよい - protobufで提供されている定義google/protobuf/any.proto 等を使いたい場合は、depsに
"@com_google_protobuf//:any_proto"
などを追加すればよい。https://github.com/cgrushko/proto_library/blob/beae7b78b85b3af51d3ea54663c421ebde97dc10/src/BUILD#L42
refs
- https://docs.bazel.build/versions/master/be/workspace.html#new_local_repository.path
- https://docs.bazel.build/versions/master/be/protocol-buffer.html#proto_library
- https://blog.bazel.build/2017/02/27/protocol-buffers.html
- https://pencilflip.medium.com/getting-started-with-grpc-and-bazel-24725fd9e5c2