Skip to content

Commit

Permalink
Implement proto_common.declare_generated_files.
Browse files Browse the repository at this point in the history
  • Loading branch information
comius authored and copybara-github committed Apr 12, 2022
1 parent b93f828 commit e45fb7a
Show file tree
Hide file tree
Showing 3 changed files with 98 additions and 0 deletions.
45 changes: 45 additions & 0 deletions src/main/starlark/builtins_bzl/common/proto/proto_common.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -238,12 +238,57 @@ def _experimental_should_generate_code(

return bool(included)

def _declare_generated_files(
actions,
proto_library_target,
extension,
name_mapper = None):
"""Declares generated files with a specific extension.
Use this in lang_proto_library-es when protocol compiler generates files
that correspond to .proto file names.
The function removes ".proto" extension with given one (e.g. ".pb.cc") and
declares new output files.
Args:
actions:
(ActionFactory) Obtained by ctx.actions, used to declare the files.
proto_library_target:
(Target) The proto_library to generate the files for.
Obtained as the `target` parameter from an aspect's implementation.
extension: (str) The extension to use for generated files.
name_mapper: (str->str) A function mapped over the base filename without
the extension. Used it to replace characters in the name that
cause problems in a specific programming language.
Returns:
(list[File]) The list of declared files.
"""
proto_info = proto_library_target[_builtins.toplevel.ProtoInfo]
proto_sources = proto_info.direct_sources
outputs = []

for src in proto_sources:
basename_no_ext = src.basename[:-(len(src.extension) + 1)]

if name_mapper:
basename_no_ext = name_mapper(basename_no_ext)

# Note that two proto_library rules can have the same source file, so this is actually a
# shared action. NB: This can probably result in action conflicts if the proto_library rules
# are not the same.
outputs.append(actions.declare_file(basename_no_ext + extension, sibling = src))

return outputs

proto_common = struct(
create_proto_compile_action = _create_proto_compile_action,
)

proto_common_do_not_use = struct(
compile = _compile,
declare_generated_files = _declare_generated_files,
experimental_should_generate_code = _experimental_should_generate_code,
experimental_filter_sources = _experimental_filter_sources,
ProtoLangToolchainInfo = _builtins.internal.ProtoLangToolchainInfo,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ java_test(
"//src/main/java/com/google/devtools/build/lib/actions:localhost_capacity",
"//src/main/java/com/google/devtools/build/lib/analysis:analysis_cluster",
"//src/main/java/com/google/devtools/build/lib/analysis:configured_target",
"//src/main/java/com/google/devtools/build/lib/analysis:file_provider",
"//src/main/java/com/google/devtools/build/lib/cmdline",
"//src/main/java/com/google/devtools/build/lib/packages",
"//src/main/java/com/google/devtools/build/lib/util:os",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import com.google.common.truth.Correspondence;
import com.google.devtools.build.lib.actions.ResourceSet;
import com.google.devtools.build.lib.analysis.ConfiguredTarget;
import com.google.devtools.build.lib.analysis.FileProvider;
import com.google.devtools.build.lib.analysis.actions.SpawnAction;
import com.google.devtools.build.lib.analysis.util.BuildViewTestCase;
import com.google.devtools.build.lib.cmdline.Label;
Expand Down Expand Up @@ -141,6 +142,24 @@ public final void setup() throws Exception {
" 'proto_dep': attr.label(),",
" 'toolchain': attr.label(default = '//foo:toolchain'),",
" })");

scratch.file(
"foo/declare_generated_files.bzl",
"def _impl(ctx):",
" files = proto_common_do_not_use.declare_generated_files(",
" ctx.actions,",
" ctx.attr.proto_dep,",
" ctx.attr.extension,",
" (lambda s: s.replace('-','_').replace('.','/')) if ctx.attr.python_names else None)",
" for f in files:",
" ctx.actions.write(f, '')",
" return [DefaultInfo(files = depset(files))]",
"declare_generated_files = rule(_impl,",
" attrs = {",
" 'proto_dep': attr.label(),",
" 'extension': attr.string(),",
" 'python_names': attr.bool(default = False),",
" })");
}

/** Verifies basic usage of <code>proto_common.generate_code</code>. */
Expand Down Expand Up @@ -566,4 +585,37 @@ public void shouldGenerateCode_mixed() throws Exception {
+ " (third_party/x/something.proto).\n"
+ "Separate '//third_party/x:mixed' into 2 proto_library rules.");
}

/** Verifies <code>proto_common.declare_generated_files</code> call. */
@Test
public void declareGenerateFiles_basic() throws Exception {
scratch.file(
"bar/BUILD",
TestConstants.LOAD_PROTO_LIBRARY,
"load('//foo:declare_generated_files.bzl', 'declare_generated_files')",
"proto_library(name = 'proto', srcs = ['A.proto', 'b/B.proto'])",
"declare_generated_files(name = 'simple', proto_dep = ':proto', extension = '.cc')");

ConfiguredTarget target = getConfiguredTarget("//bar:simple");

assertThat(prettyArtifactNames(target.getProvider(FileProvider.class).getFilesToBuild()))
.containsExactly("bar/A.cc", "bar/b/B.cc");
}

/** Verifies <code>proto_common.declare_generated_files</code> call for Python. */
@Test
public void declareGenerateFiles_pythonc() throws Exception {
scratch.file(
"bar/BUILD",
TestConstants.LOAD_PROTO_LIBRARY,
"load('//foo:declare_generated_files.bzl', 'declare_generated_files')",
"proto_library(name = 'proto', srcs = ['my-proto.gen.proto'])",
"declare_generated_files(name = 'simple', proto_dep = ':proto', extension = '_pb2.py',",
" python_names = True)");

ConfiguredTarget target = getConfiguredTarget("//bar:simple");

assertThat(prettyArtifactNames(target.getProvider(FileProvider.class).getFilesToBuild()))
.containsExactly("bar/my_proto/gen_pb2.py");
}
}

0 comments on commit e45fb7a

Please sign in to comment.