|  | @@ -4,132 +4,81 @@ This is an internal rule used by cc_grpc_library, and shouldn't be used
 | 
	
		
			
				|  |  |  directly.
 | 
	
		
			
				|  |  |  """
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -load(
 | 
	
		
			
				|  |  | -    "//bazel:protobuf.bzl",
 | 
	
		
			
				|  |  | -    "get_include_protoc_args",
 | 
	
		
			
				|  |  | -    "get_plugin_args",
 | 
	
		
			
				|  |  | -    "get_proto_root",
 | 
	
		
			
				|  |  | -    "proto_path_to_generated_filename",
 | 
	
		
			
				|  |  | -)
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -_GRPC_PROTO_HEADER_FMT = "{}.grpc.pb.h"
 | 
	
		
			
				|  |  | -_GRPC_PROTO_SRC_FMT = "{}.grpc.pb.cc"
 | 
	
		
			
				|  |  | -_GRPC_PROTO_MOCK_HEADER_FMT = "{}_mock.grpc.pb.h"
 | 
	
		
			
				|  |  | -_PROTO_HEADER_FMT = "{}.pb.h"
 | 
	
		
			
				|  |  | -_PROTO_SRC_FMT = "{}.pb.cc"
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -def _strip_package_from_path(label_package, path):
 | 
	
		
			
				|  |  | -    if len(label_package) == 0:
 | 
	
		
			
				|  |  | -        return path
 | 
	
		
			
				|  |  | -    if not path.startswith(label_package + "/"):
 | 
	
		
			
				|  |  | -        fail("'{}' does not lie within '{}'.".format(path, label_package))
 | 
	
		
			
				|  |  | -    return path[len(label_package + "/"):]
 | 
	
		
			
				|  |  | +def generate_cc_impl(ctx):
 | 
	
		
			
				|  |  | +  """Implementation of the generate_cc rule."""
 | 
	
		
			
				|  |  | +  protos = [f for src in ctx.attr.srcs for f in src.proto.direct_sources]
 | 
	
		
			
				|  |  | +  includes = [f for src in ctx.attr.srcs for f in src.proto.transitive_imports]
 | 
	
		
			
				|  |  | +  outs = []
 | 
	
		
			
				|  |  | +  # label_len is length of the path from WORKSPACE root to the location of this build file
 | 
	
		
			
				|  |  | +  label_len = 0
 | 
	
		
			
				|  |  | +  # proto_root is the directory relative to which generated include paths should be
 | 
	
		
			
				|  |  | +  proto_root = ""
 | 
	
		
			
				|  |  | +  if ctx.label.package:
 | 
	
		
			
				|  |  | +    # The +1 is for the trailing slash.
 | 
	
		
			
				|  |  | +    label_len += len(ctx.label.package) + 1
 | 
	
		
			
				|  |  | +  if ctx.label.workspace_root:
 | 
	
		
			
				|  |  | +    label_len += len(ctx.label.workspace_root) + 1
 | 
	
		
			
				|  |  | +    proto_root = "/" + ctx.label.workspace_root
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -def _join_directories(directories):
 | 
	
		
			
				|  |  | -    massaged_directories = [directory for directory in directories if len(directory) != 0]
 | 
	
		
			
				|  |  | -    return "/".join(massaged_directories)
 | 
	
		
			
				|  |  | +  if ctx.executable.plugin:
 | 
	
		
			
				|  |  | +    outs += [proto.path[label_len:-len(".proto")] + ".grpc.pb.h" for proto in protos]
 | 
	
		
			
				|  |  | +    outs += [proto.path[label_len:-len(".proto")] + ".grpc.pb.cc" for proto in protos]
 | 
	
		
			
				|  |  | +    if ctx.attr.generate_mocks:
 | 
	
		
			
				|  |  | +      outs += [proto.path[label_len:-len(".proto")] + "_mock.grpc.pb.h" for proto in protos]
 | 
	
		
			
				|  |  | +  else:
 | 
	
		
			
				|  |  | +    outs += [proto.path[label_len:-len(".proto")] + ".pb.h" for proto in protos]
 | 
	
		
			
				|  |  | +    outs += [proto.path[label_len:-len(".proto")] + ".pb.cc" for proto in protos]
 | 
	
		
			
				|  |  | +  out_files = [ctx.actions.declare_file(out) for out in outs]
 | 
	
		
			
				|  |  | +  dir_out = str(ctx.genfiles_dir.path + proto_root)
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -def generate_cc_impl(ctx):
 | 
	
		
			
				|  |  | -    """Implementation of the generate_cc rule."""
 | 
	
		
			
				|  |  | -    protos = [f for src in ctx.attr.srcs for f in src.proto.direct_sources]
 | 
	
		
			
				|  |  | -    includes = [
 | 
	
		
			
				|  |  | -        f
 | 
	
		
			
				|  |  | -        for src in ctx.attr.srcs
 | 
	
		
			
				|  |  | -        for f in src.proto.transitive_imports
 | 
	
		
			
				|  |  | -    ]
 | 
	
		
			
				|  |  | -    outs = []
 | 
	
		
			
				|  |  | -    proto_root = get_proto_root(
 | 
	
		
			
				|  |  | -        ctx.label.workspace_root,
 | 
	
		
			
				|  |  | -    )
 | 
	
		
			
				|  |  | +  arguments = []
 | 
	
		
			
				|  |  | +  if ctx.executable.plugin:
 | 
	
		
			
				|  |  | +    arguments += ["--plugin=protoc-gen-PLUGIN=" + ctx.executable.plugin.path]
 | 
	
		
			
				|  |  | +    flags = list(ctx.attr.flags)
 | 
	
		
			
				|  |  | +    if ctx.attr.generate_mocks:
 | 
	
		
			
				|  |  | +      flags.append("generate_mock_code=true")
 | 
	
		
			
				|  |  | +    arguments += ["--PLUGIN_out=" + ",".join(flags) + ":" + dir_out]
 | 
	
		
			
				|  |  | +    tools = [ctx.executable.plugin]
 | 
	
		
			
				|  |  | +  else:
 | 
	
		
			
				|  |  | +    arguments += ["--cpp_out=" + ",".join(ctx.attr.flags) + ":" + dir_out]
 | 
	
		
			
				|  |  | +    tools = []
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    label_package = _join_directories([ctx.label.workspace_root, ctx.label.package])
 | 
	
		
			
				|  |  | -    if ctx.executable.plugin:
 | 
	
		
			
				|  |  | -        outs += [
 | 
	
		
			
				|  |  | -            proto_path_to_generated_filename(
 | 
	
		
			
				|  |  | -                _strip_package_from_path(label_package, proto.path),
 | 
	
		
			
				|  |  | -                _GRPC_PROTO_HEADER_FMT,
 | 
	
		
			
				|  |  | -            )
 | 
	
		
			
				|  |  | -            for proto in protos
 | 
	
		
			
				|  |  | -        ]
 | 
	
		
			
				|  |  | -        outs += [
 | 
	
		
			
				|  |  | -            proto_path_to_generated_filename(
 | 
	
		
			
				|  |  | -                _strip_package_from_path(label_package, proto.path),
 | 
	
		
			
				|  |  | -                _GRPC_PROTO_SRC_FMT,
 | 
	
		
			
				|  |  | -            )
 | 
	
		
			
				|  |  | -            for proto in protos
 | 
	
		
			
				|  |  | -        ]
 | 
	
		
			
				|  |  | -        if ctx.attr.generate_mocks:
 | 
	
		
			
				|  |  | -            outs += [
 | 
	
		
			
				|  |  | -                proto_path_to_generated_filename(
 | 
	
		
			
				|  |  | -                    _strip_package_from_path(label_package, proto.path),
 | 
	
		
			
				|  |  | -                    _GRPC_PROTO_MOCK_HEADER_FMT,
 | 
	
		
			
				|  |  | -                )
 | 
	
		
			
				|  |  | -                for proto in protos
 | 
	
		
			
				|  |  | -            ]
 | 
	
		
			
				|  |  | +  # Import protos relative to their workspace root so that protoc prints the
 | 
	
		
			
				|  |  | +  # right include paths.
 | 
	
		
			
				|  |  | +  for include in includes:
 | 
	
		
			
				|  |  | +    directory = include.path
 | 
	
		
			
				|  |  | +    if directory.startswith("external"):
 | 
	
		
			
				|  |  | +      external_sep = directory.find("/")
 | 
	
		
			
				|  |  | +      repository_sep = directory.find("/", external_sep + 1)
 | 
	
		
			
				|  |  | +      arguments += ["--proto_path=" + directory[:repository_sep]]
 | 
	
		
			
				|  |  |      else:
 | 
	
		
			
				|  |  | -        outs += [
 | 
	
		
			
				|  |  | -            proto_path_to_generated_filename(
 | 
	
		
			
				|  |  | -                _strip_package_from_path(label_package, proto.path),
 | 
	
		
			
				|  |  | -                _PROTO_HEADER_FMT,
 | 
	
		
			
				|  |  | -            )
 | 
	
		
			
				|  |  | -            for proto in protos
 | 
	
		
			
				|  |  | -        ]
 | 
	
		
			
				|  |  | -        outs += [
 | 
	
		
			
				|  |  | -            proto_path_to_generated_filename(
 | 
	
		
			
				|  |  | -                _strip_package_from_path(label_package, proto.path),
 | 
	
		
			
				|  |  | -                _PROTO_SRC_FMT,
 | 
	
		
			
				|  |  | -            )
 | 
	
		
			
				|  |  | -            for proto in protos
 | 
	
		
			
				|  |  | -        ]
 | 
	
		
			
				|  |  | -    out_files = [ctx.actions.declare_file(out) for out in outs]
 | 
	
		
			
				|  |  | -    dir_out = str(ctx.genfiles_dir.path + proto_root)
 | 
	
		
			
				|  |  | +      arguments += ["--proto_path=."]
 | 
	
		
			
				|  |  | +  # Include the output directory so that protoc puts the generated code in the
 | 
	
		
			
				|  |  | +  # right directory.
 | 
	
		
			
				|  |  | +  arguments += ["--proto_path={0}{1}".format(dir_out, proto_root)]
 | 
	
		
			
				|  |  | +  arguments += [proto.path for proto in protos]
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    arguments = []
 | 
	
		
			
				|  |  | -    if ctx.executable.plugin:
 | 
	
		
			
				|  |  | -        arguments += get_plugin_args(
 | 
	
		
			
				|  |  | -            ctx.executable.plugin,
 | 
	
		
			
				|  |  | -            ctx.attr.flags,
 | 
	
		
			
				|  |  | -            dir_out,
 | 
	
		
			
				|  |  | -            ctx.attr.generate_mocks,
 | 
	
		
			
				|  |  | -        )
 | 
	
		
			
				|  |  | -        tools = [ctx.executable.plugin]
 | 
	
		
			
				|  |  | +  # create a list of well known proto files if the argument is non-None
 | 
	
		
			
				|  |  | +  well_known_proto_files = []
 | 
	
		
			
				|  |  | +  if ctx.attr.well_known_protos:
 | 
	
		
			
				|  |  | +    f = ctx.attr.well_known_protos.files.to_list()[0].dirname
 | 
	
		
			
				|  |  | +    if f != "external/com_google_protobuf/src/google/protobuf":
 | 
	
		
			
				|  |  | +      print("Error: Only @com_google_protobuf//:well_known_protos is supported")
 | 
	
		
			
				|  |  |      else:
 | 
	
		
			
				|  |  | -        arguments += ["--cpp_out=" + ",".join(ctx.attr.flags) + ":" + dir_out]
 | 
	
		
			
				|  |  | -        tools = []
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    arguments += get_include_protoc_args(includes)
 | 
	
		
			
				|  |  | +      # f points to "external/com_google_protobuf/src/google/protobuf"
 | 
	
		
			
				|  |  | +      # add -I argument to protoc so it knows where to look for the proto files.
 | 
	
		
			
				|  |  | +      arguments += ["-I{0}".format(f + "/../..")]
 | 
	
		
			
				|  |  | +      well_known_proto_files = [f for f in ctx.attr.well_known_protos.files]
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    # Include the output directory so that protoc puts the generated code in the
 | 
	
		
			
				|  |  | -    # right directory.
 | 
	
		
			
				|  |  | -    arguments += ["--proto_path={0}{1}".format(dir_out, proto_root)]
 | 
	
		
			
				|  |  | -    arguments += [proto.path for proto in protos]
 | 
	
		
			
				|  |  | +  ctx.actions.run(
 | 
	
		
			
				|  |  | +      inputs = protos + includes + well_known_proto_files,
 | 
	
		
			
				|  |  | +      tools = tools,
 | 
	
		
			
				|  |  | +      outputs = out_files,
 | 
	
		
			
				|  |  | +      executable = ctx.executable._protoc,
 | 
	
		
			
				|  |  | +      arguments = arguments,
 | 
	
		
			
				|  |  | +  )
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    # create a list of well known proto files if the argument is non-None
 | 
	
		
			
				|  |  | -    well_known_proto_files = []
 | 
	
		
			
				|  |  | -    if ctx.attr.well_known_protos:
 | 
	
		
			
				|  |  | -        f = ctx.attr.well_known_protos.files.to_list()[0].dirname
 | 
	
		
			
				|  |  | -        if f != "external/com_google_protobuf/src/google/protobuf":
 | 
	
		
			
				|  |  | -            print(
 | 
	
		
			
				|  |  | -                "Error: Only @com_google_protobuf//:well_known_protos is supported",
 | 
	
		
			
				|  |  | -            )
 | 
	
		
			
				|  |  | -        else:
 | 
	
		
			
				|  |  | -            # f points to "external/com_google_protobuf/src/google/protobuf"
 | 
	
		
			
				|  |  | -            # add -I argument to protoc so it knows where to look for the proto files.
 | 
	
		
			
				|  |  | -            arguments += ["-I{0}".format(f + "/../..")]
 | 
	
		
			
				|  |  | -            well_known_proto_files = [
 | 
	
		
			
				|  |  | -                f
 | 
	
		
			
				|  |  | -                for f in ctx.attr.well_known_protos.files
 | 
	
		
			
				|  |  | -            ]
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    ctx.actions.run(
 | 
	
		
			
				|  |  | -        inputs = protos + includes + well_known_proto_files,
 | 
	
		
			
				|  |  | -        tools = tools,
 | 
	
		
			
				|  |  | -        outputs = out_files,
 | 
	
		
			
				|  |  | -        executable = ctx.executable._protoc,
 | 
	
		
			
				|  |  | -        arguments = arguments,
 | 
	
		
			
				|  |  | -    )
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    return struct(files = depset(out_files))
 | 
	
		
			
				|  |  | +  return struct(files=depset(out_files))
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  _generate_cc = rule(
 | 
	
		
			
				|  |  |      attrs = {
 | 
	
	
		
			
				|  | @@ -147,8 +96,10 @@ _generate_cc = rule(
 | 
	
		
			
				|  |  |              mandatory = False,
 | 
	
		
			
				|  |  |              allow_empty = True,
 | 
	
		
			
				|  |  |          ),
 | 
	
		
			
				|  |  | -        "well_known_protos": attr.label(mandatory = False),
 | 
	
		
			
				|  |  | -        "generate_mocks": attr.bool(
 | 
	
		
			
				|  |  | +        "well_known_protos" : attr.label(
 | 
	
		
			
				|  |  | +            mandatory = False,
 | 
	
		
			
				|  |  | +        ),
 | 
	
		
			
				|  |  | +        "generate_mocks" : attr.bool(
 | 
	
		
			
				|  |  |              default = False,
 | 
	
		
			
				|  |  |              mandatory = False,
 | 
	
		
			
				|  |  |          ),
 | 
	
	
		
			
				|  | @@ -164,10 +115,7 @@ _generate_cc = rule(
 | 
	
		
			
				|  |  |  )
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  def generate_cc(well_known_protos, **kwargs):
 | 
	
		
			
				|  |  | -    if well_known_protos:
 | 
	
		
			
				|  |  | -        _generate_cc(
 | 
	
		
			
				|  |  | -            well_known_protos = "@com_google_protobuf//:well_known_protos",
 | 
	
		
			
				|  |  | -            **kwargs
 | 
	
		
			
				|  |  | -        )
 | 
	
		
			
				|  |  | -    else:
 | 
	
		
			
				|  |  | -        _generate_cc(**kwargs)
 | 
	
		
			
				|  |  | +  if well_known_protos:
 | 
	
		
			
				|  |  | +    _generate_cc(well_known_protos="@com_google_protobuf//:well_known_protos", **kwargs)
 | 
	
		
			
				|  |  | +  else:
 | 
	
		
			
				|  |  | +    _generate_cc(**kwargs)
 |