[bazel/protobuf.bzl] Improve py_proto_library path handling (#28040)

This change replaces the simple `basename` logic with a more general
"remove prefix" logic. This allows py_proto_library to work even when
the input proto_library's sources are contained in strict
subdirectories of their package. (This situation is not uncommon when
using remote, non-Bazel repositories that only get a single BUILD file.)
reviewable/pr27867/r1^2
Thomas Köppe 3 years ago committed by GitHub
parent 5466a0bc43
commit 90a56a3d15
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 36
      bazel/protobuf.bzl
  2. 8
      bazel/test/python_test_repo/BUILD
  3. 5
      bazel/test/python_test_repo/helloworld.proto
  4. 21
      bazel/test/python_test_repo/subdir/hello_dep.proto

@ -145,6 +145,29 @@ def get_plugin_args(
), ),
] ]
def _make_prefix(label):
"""Returns the directory prefix for a label.
@repo//foo/bar:sub/dir/file.proto => 'external/repo/foo/bar/'
//foo/bar:sub/dir/file.proto => 'foo/bar/'
//:sub/dir/file.proto => ''
That is, the prefix can be removed from a file's full path to
obtain the file's relative location within the package's effective
directory."""
wsr = label.workspace_root
pkg = label.package
if not wsr and not pkg:
return ""
elif not wsr:
return pkg + "/"
elif not pkg:
return wsr + "/"
else:
return wsr + "/" + pkg + "/"
def get_staged_proto_file(label, context, source_file): def get_staged_proto_file(label, context, source_file):
"""Copies a proto file to the appropriate location if necessary. """Copies a proto file to the appropriate location if necessary.
@ -163,7 +186,8 @@ def get_staged_proto_file(label, context, source_file):
else: else:
# Current target and source_file are in different packages (most # Current target and source_file are in different packages (most
# probably even in different repositories) # probably even in different repositories)
copied_proto = context.actions.declare_file(source_file.basename) prefix = _make_prefix(source_file.owner)
copied_proto = context.actions.declare_file(source_file.path[len(prefix):])
context.actions.run_shell( context.actions.run_shell(
inputs = [source_file], inputs = [source_file],
outputs = [copied_proto], outputs = [copied_proto],
@ -236,10 +260,14 @@ def declare_out_files(protos, context, generated_file_format):
out_file_paths = [] out_file_paths = []
for proto in protos: for proto in protos:
if not is_in_virtual_imports(proto): if not is_in_virtual_imports(proto):
out_file_paths.append(proto.basename) prefix = _make_prefix(proto.owner)
full_prefix = context.genfiles_dir.path + "/" + prefix
if proto.path.startswith(full_prefix):
out_file_paths.append(proto.path[len(full_prefix):])
elif proto.path.startswith(prefix):
out_file_paths.append(proto.path[len(prefix):])
else: else:
path = proto.path[proto.path.index(_VIRTUAL_IMPORTS) + 1:] out_file_paths.append(proto.path[proto.path.index(_VIRTUAL_IMPORTS) + 1:])
out_file_paths.append(path)
return [ return [
context.actions.declare_file( context.actions.declare_file(

@ -29,11 +29,18 @@ proto_library(
name = "helloworld_proto", name = "helloworld_proto",
srcs = ["helloworld.proto"], srcs = ["helloworld.proto"],
deps = [ deps = [
":hello_dep_proto",
"@com_google_protobuf//:duration_proto", "@com_google_protobuf//:duration_proto",
"@com_google_protobuf//:timestamp_proto", "@com_google_protobuf//:timestamp_proto",
], ],
) )
# Test that .proto files can be located in strict subdiretories of the package.
proto_library(
name = "hello_dep_proto",
srcs = ["subdir/hello_dep.proto"],
)
py_proto_library( py_proto_library(
name = "helloworld_py_pb2", name = "helloworld_py_pb2",
deps = [":helloworld_proto"], deps = [":helloworld_proto"],
@ -79,6 +86,7 @@ proto_library(
import_prefix = "google/cloud", import_prefix = "google/cloud",
strip_import_prefix = "", strip_import_prefix = "",
deps = [ deps = [
":hello_dep_proto",
"@com_google_protobuf//:duration_proto", "@com_google_protobuf//:duration_proto",
"@com_google_protobuf//:timestamp_proto", "@com_google_protobuf//:timestamp_proto",
], ],

@ -23,6 +23,7 @@ package helloworld;
import "google/protobuf/timestamp.proto"; import "google/protobuf/timestamp.proto";
import "google/protobuf/duration.proto"; import "google/protobuf/duration.proto";
import "subdir/hello_dep.proto";
// The greeting service definition. // The greeting service definition.
service Greeter { service Greeter {
@ -36,8 +37,10 @@ message HelloRequest {
google.protobuf.Timestamp request_initiation = 2; google.protobuf.Timestamp request_initiation = 2;
} }
// The response message containing the greetings // The response message containing the greetings, plus some additional
// data of a type defined in a separate .proto file.
message HelloReply { message HelloReply {
string message = 1; string message = 1;
google.protobuf.Duration request_duration = 2; google.protobuf.Duration request_duration = 2;
HelloDep dep = 3;
} }

@ -0,0 +1,21 @@
// Copyright 2019 The gRPC authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
syntax = "proto3";
package helloworld;
message HelloDep {
repeated int64 numbers = 1;
}
Loading…
Cancel
Save