Skip to content

Commit

Permalink
Break dependency on protobuf.bzl from google/protobuf for C++ (#92)
Browse files Browse the repository at this point in the history
* Break dependency on protobuf.bzl from google/protobuf for C++

This replaces the use of cc_proto_library / proto_gen from the
@com_google_protobuf//:protobuf.bzl. The reason for doing so is that
newer versions of google/protobuf have changed cc_proto_library +
proto_gen so that they no longer work with pgv_cc_proto_library.

pgv_proto_library now takes a proto_library containing the protos
instead of a list of proto files. The approach for generating the protoc
command line arguments was taken from bazelbuild/rules_go

The py_proto_library imported from @com_google_protobuf//:protobuf.bzl
is used by Envoy, so we left it in.

Signed-off-by: Andrew Keesler <[email protected]>
Signed-off-by: Amin Jamali <[email protected]>

* Fix nits

- change mnemonic to ProtoGenValidateCcGenerate
- accept array of proto_library rules as argument

Signed-off-by: Sam Smith <[email protected]>
  • Loading branch information
sesmith177 authored and rodaine committed Aug 8, 2018
1 parent 05ff6bc commit 8f40688
Show file tree
Hide file tree
Showing 7 changed files with 120 additions and 119 deletions.
112 changes: 26 additions & 86 deletions bazel/pgv_proto_library.bzl
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
load("@io_bazel_rules_go//proto:def.bzl", "go_proto_library")
load("@io_bazel_rules_go//proto:compiler.bzl", "go_proto_compiler")
load("@com_google_protobuf//:protobuf.bzl", "proto_gen", "cc_proto_library")
load(":protobuf.bzl", "cc_proto_gen_validate")

def pgv_go_proto_library(name, proto = None, deps = [], **kwargs):
go_proto_compiler(
Expand All @@ -18,94 +18,34 @@ def pgv_go_proto_library(name, proto = None, deps = [], **kwargs):
visibility = ["//visibility:public"],
**kwargs)

def _CcValidateHdrs(srcs):
ret = [s[:-len(".proto")] + ".pb.validate.h" for s in srcs]
return ret

def _CcValidateSrcs(srcs):
ret = [s[:-len(".proto")] + ".pb.validate.cc" for s in srcs]
return ret

def pgv_cc_proto_library(
name,
srcs=[],
deps=[],
external_deps=[],
cc_libs=[],
include=None,
protoc="@com_google_protobuf//:protoc",
protoc_gen_validate = "@com_lyft_protoc_gen_validate//:protoc-gen-validate",
internal_bootstrap_hack=False,
use_grpc_plugin=False,
default_runtime="@com_google_protobuf//:protobuf",
cc_deps=[],
**kargs):
"""Bazel rule to create a C++ protobuf validation library from proto source files
Args:
name: the name of the pgv_cc_proto_library.
srcs: the .proto files of the pgv_cc_proto_library.
deps: a list of PGV dependency labels; must be pgv_cc_proto_library.
external_deps: a list of dependency labels; must be cc_proto_library.
include: a string indicating the include path of the .proto files.
protoc: the label of the protocol compiler to generate the sources.
protoc_gen_validate: override the default version of protoc_gen_validate.
Most users won't need this.
default_runtime: the implicitly default runtime which will be depended on by
the generated cc_library target.
**kargs: other keyword arguments that are passed to cc_library.
"""

# Generate the C++ protos
cc_proto_library(
name=name + "_proto",
srcs=srcs,
deps=[d + "_proto" for d in deps] + [
"@com_lyft_protoc_gen_validate//validate:validate_cc",
] + external_deps,
cc_libs=cc_libs,
incude=include,
protoc=protoc,
internal_bootstrap_hack=internal_bootstrap_hack,
use_grpc_plugin=use_grpc_plugin,
default_runtime=default_runtime,
**kargs)

includes = []
if include != None:
includes = [include]

gen_hdrs = _CcValidateHdrs(srcs)
gen_srcs = _CcValidateSrcs(srcs)

proto_gen(
name=name + "_validate",
srcs=srcs,
# This is a hack to work around the fact that all the deps must have an
# import_flags field, which is only set on the proto_gen rules, so depend
# on the cc rule
deps=[d + "_validate" for d in deps] + [
"@com_lyft_protoc_gen_validate//validate:validate_cc_genproto"
] + [d + "_genproto" for d in external_deps],
includes=includes,
protoc=protoc,
plugin=protoc_gen_validate,
plugin_options=["lang=cc"],
outs=gen_hdrs + gen_srcs,
visibility=["//visibility:public"],
)
"""Bazel rule to create a C++ protobuf validation library from proto source files
Args:
name: the name of the pgv_cc_proto_library.
deps: proto_library rules that contains the necessary .proto files. Note that this
must include @com_lyft_protoc_gen_validate//validate:validate_proto
cc_deps: C++ dependencies of the protos being compiled. Likely cc_proto_library or pgv_cc_proto_library
**kargs: other keyword arguments that are passed to cc_library.
"""

cc_proto_gen_validate(
name=name+"_validate",
deps=deps,
)

if default_runtime and not default_runtime in cc_libs:
cc_libs = cc_libs + [default_runtime]
native.cc_library(
name=name,
hdrs=[":"+name+"_validate"],
srcs=[":"+name+"_validate"],
deps= cc_deps + [
"@com_lyft_protoc_gen_validate//validate:cc_validate",
"@com_lyft_protoc_gen_validate//validate:validate_cc",
"@com_google_protobuf//:protobuf",
],
alwayslink=1,
**kargs)

native.cc_library(
name=name,
hdrs=gen_hdrs,
srcs=gen_srcs,
deps=cc_libs + deps + [
":" + name + "_proto",
"@com_lyft_protoc_gen_validate//validate:cc_validate",
],
includes=includes,
alwayslink=1,
**kargs)
84 changes: 84 additions & 0 deletions bazel/protobuf.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
def _proto_path(proto):
"""
The proto path is not really a file path
It's the path to the proto that was seen when the descriptor file was generated.
"""
path = proto.path
root = proto.root.path
ws = proto.owner.workspace_root
if path.startswith(root):
path = path[len(root):]
if path.startswith("/"):
path = path[1:]
if path.startswith(ws):
path = path[len(ws):]
if path.startswith("/"):
path = path[1:]
return path

def _protoc_gen_validate_impl(ctx):
"""Generate protos using protoc-gen-validate plugin"""
protos = []
for dep in ctx.attr.deps:
protos += [f for f in dep.proto.direct_sources]

cc_hdrs = [p.basename[:-len(".proto")] + ".pb.validate.h" for p in protos]
cc_hdrs += [p.basename[:-len(".proto")] + ".pb.h" for p in protos]

cc_srcs = [p.basename[:-len(".proto")] + ".pb.validate.cc" for p in protos]
cc_srcs += [p.basename[:-len(".proto")] + ".pb.cc" for p in protos]

out_files = [ctx.actions.declare_file(out) for out in cc_hdrs+cc_srcs]

dir_out = ctx.genfiles_dir.path
if ctx.label.workspace_root:
dir_out += ("/"+ctx.label.workspace_root)

args = [
"--cpp_out="+dir_out,
"--plugin=protoc-gen-validate="+ctx.executable._plugin.path,
"--validate_out=lang=cc:"+ dir_out,
]

tds = depset([], transitive = [dep.proto.transitive_descriptor_sets for dep in ctx.attr.deps])
descriptor_args = [ds.path for ds in tds]

if len(descriptor_args) != 0:
args += ["--descriptor_set_in=%s" % ":".join(descriptor_args)]

ctx.action(
inputs=protos + tds.to_list() + [ctx.executable._plugin],
outputs=out_files,
arguments=args + [_proto_path(proto) for proto in protos],
executable=ctx.executable._protoc,
mnemonic="ProtoGenValidateCcGenerate",
use_default_shell_env=True,
)

return struct(
files=depset(out_files)
)

cc_proto_gen_validate = rule(
attrs = {
"deps": attr.label_list(
mandatory = True,
providers = ["proto"],
),

"_protoc": attr.label(
cfg = "host",
default = Label("@com_google_protobuf//:protoc"),
executable = True,
single_file = True,
),
"_plugin": attr.label(
cfg = "host",
default = Label("@com_lyft_protoc_gen_validate//:protoc-gen-validate"),
allow_files = True,
executable = True,
),
},
output_to_genfiles = True,
implementation = _protoc_gen_validate_impl,
)
8 changes: 2 additions & 6 deletions tests/harness/BUILD
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
# gazelle:exclude harness.pb.go

load("@io_bazel_rules_go//proto:def.bzl", "go_proto_library")
load("@com_google_protobuf//:protobuf.bzl", "cc_proto_library")

proto_library(
name = "harness_proto_target",
Expand All @@ -27,11 +26,8 @@ go_proto_library(

cc_proto_library(
name = "harness_proto",
srcs = ["harness.proto"],
default_runtime = "@com_google_protobuf//:protobuf",
protoc = "@com_google_protobuf//:protoc",
visibility = ["//visibility:public"],
deps = [
"@com_google_protobuf//:cc_wkt_protos",
":harness_proto_target",
],
visibility = ["//visibility:public"],
)
22 changes: 4 additions & 18 deletions tests/harness/cases/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ load(
)

proto_library(
name = "go_proto",
name = "cases_proto",
srcs = [
"bool.proto",
"bytes.proto",
Expand Down Expand Up @@ -36,7 +36,7 @@ proto_library(

pgv_go_proto_library(
name = "go",
proto = ":go_proto",
proto = ":cases_proto",
importpath = "github.com/lyft/protoc-gen-validate/tests/harness/cases/go",
deps = [
"//tests/harness/cases/other_package:go",
Expand Down Expand Up @@ -64,22 +64,8 @@ go_library(

pgv_cc_proto_library(
name = "cc",
srcs = [
"bool.proto",
"bytes.proto",
"enums.proto",
"maps.proto",
"messages.proto",
"numbers.proto",
"oneofs.proto",
"repeated.proto",
"strings.proto",
"wkt_any.proto",
"wkt_duration.proto",
"wkt_timestamp.proto",
"wkt_wrappers.proto",
],
deps = [
deps = [":cases_proto"],
cc_deps = [
"//tests/harness/cases/other_package:cc",
],
visibility = ["//tests:__subpackages__"],
Expand Down
4 changes: 1 addition & 3 deletions tests/harness/cases/other_package/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,6 @@ go_library(

pgv_cc_proto_library(
name = "cc",
srcs = [
"embed.proto",
],
deps = [":embed_proto"],
visibility = ["//tests:__subpackages__"],
)
2 changes: 1 addition & 1 deletion tests/kitchensink/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ pgv_go_proto_library(

pgv_cc_proto_library(
name = "fixed32_cc",
srcs = ["fixed32.proto"],
deps = [":fixed32_proto"],
)

proto_library(
Expand Down
7 changes: 2 additions & 5 deletions validate/BUILD
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# gazelle:exclude validate.pb.go

load("@io_bazel_rules_go//proto:def.bzl", "go_proto_library")
load("@com_google_protobuf//:protobuf.bzl", "cc_proto_library", "py_proto_library")
load("@com_google_protobuf//:protobuf.bzl", "py_proto_library")

proto_library(
name = "validate_proto",
Expand All @@ -16,10 +16,7 @@ proto_library(

cc_proto_library(
name = "validate_cc",
srcs = ["validate.proto"],
protoc = "@com_google_protobuf//:protoc",
default_runtime = "@com_google_protobuf//:protobuf",
deps = ["@com_google_protobuf//:cc_wkt_protos"],
deps = [":validate_proto"],
visibility = ["//visibility:public"],
)

Expand Down

0 comments on commit 8f40688

Please sign in to comment.