aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar Carmi Grushko <carmi@google.com>2016-04-06 20:03:56 +0000
committerGravatar Lukacs Berki <lberki@google.com>2016-04-07 11:48:11 +0000
commit802f39ecb2370b497be8ad9e307923e5aa3a7ab7 (patch)
treef9952fe904fcab201f00866eb436f434faf39201 /src
parentbae12f9e2e0b200da6da9de5e9bdc40365140f39 (diff)
Clean the API of ProtoCompileAction, in preparation for making the proto-compiler use a params file.
-- MOS_MIGRATED_REVID=119193368
Diffstat (limited to 'src')
-rw-r--r--src/main/java/com/google/devtools/build/lib/analysis/RuleContext.java1
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/proto/ProtoCompileAction.java308
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/proto/ProtoCompileActionBuilder.java297
3 files changed, 298 insertions, 308 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/RuleContext.java b/src/main/java/com/google/devtools/build/lib/analysis/RuleContext.java
index 5eac0d686a..efd137900b 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/RuleContext.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/RuleContext.java
@@ -720,6 +720,7 @@ public final class RuleContext extends TargetContext
*
* @return the {@link FilesToRunProvider} interface of the prerequisite.
*/
+ @Nullable
public FilesToRunProvider getExecutablePrerequisite(String attributeName, Mode mode) {
Attribute ruleDefinition = getAttribute(attributeName);
diff --git a/src/main/java/com/google/devtools/build/lib/rules/proto/ProtoCompileAction.java b/src/main/java/com/google/devtools/build/lib/rules/proto/ProtoCompileAction.java
deleted file mode 100644
index 94aca1cee0..0000000000
--- a/src/main/java/com/google/devtools/build/lib/rules/proto/ProtoCompileAction.java
+++ /dev/null
@@ -1,308 +0,0 @@
-// Copyright 2015 The Bazel Authors. All rights reserved.
-//
-// 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.
-
-package com.google.devtools.build.lib.rules.proto;
-
-import static com.google.common.base.Optional.absent;
-import static com.google.common.base.Preconditions.checkState;
-import static com.google.common.collect.Iterables.isEmpty;
-
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
-import com.google.common.base.Supplier;
-import com.google.common.base.Suppliers;
-import com.google.common.collect.ImmutableList;
-import com.google.devtools.build.lib.actions.Artifact;
-import com.google.devtools.build.lib.actions.ResourceSet;
-import com.google.devtools.build.lib.analysis.FilesToRunProvider;
-import com.google.devtools.build.lib.analysis.RuleConfiguredTarget.Mode;
-import com.google.devtools.build.lib.analysis.RuleContext;
-import com.google.devtools.build.lib.analysis.actions.CommandLine;
-import com.google.devtools.build.lib.analysis.actions.CustomCommandLine;
-import com.google.devtools.build.lib.analysis.actions.CustomCommandLine.CustomMultiArgv;
-import com.google.devtools.build.lib.analysis.actions.SpawnAction;
-import com.google.devtools.build.lib.util.LazyString;
-
-import java.util.List;
-
-/**
- * An action to run the protocol compiler to generate sources from .proto files.
- */
-public final class ProtoCompileAction {
-
- private static final String MNEMONIC = "GenProto";
- private static final ResourceSet GENPROTO_RESOURCE_SET =
- ResourceSet.createWithRamCpuIo(100, .1, .0);
-
- private final RuleContext ruleContext;
- private final SupportData supportData;
- private final String language;
- private final Iterable<Artifact> outputs;
- private final List<? extends CharSequence> prefixArguments;
- private final FilesToRunProvider langPluginTarget;
- private final FilesToRunProvider compilerTarget;
- private final List<String> suffixArguments;
-
- public static class Builder {
- private RuleContext ruleContext;
- private SupportData supportData;
- private String language;
- private String langPrefix;
- private Iterable<Artifact> outputs;
- private String langParameter;
- private String langPluginName;
- private String langPluginParameter;
- private Supplier<String> langPluginParameterSupplier;
- private boolean hasServices;
-
- public Builder setRuleContext(RuleContext ruleContext) {
- this.ruleContext = ruleContext;
- return this;
- }
-
- public Builder setSupportData(SupportData supportData) {
- this.supportData = supportData;
- return this;
- }
-
- public Builder setLanguage(String language) {
- this.language = language;
- return this;
- }
-
- public Builder setLangPrefix(String langPrefix) {
- this.langPrefix = langPrefix;
- return this;
- }
-
- public Builder setHasServices(boolean hasServices) {
- this.hasServices = hasServices;
- return this;
- }
-
- public Builder setOutputs(Iterable<Artifact> outputs) {
- this.outputs = outputs;
- return this;
- }
-
- public Builder setLangParameter(String langParameter) {
- this.langParameter = langParameter;
- return this;
- }
-
- public Builder setLangPluginName(String langPluginName) {
- this.langPluginName = langPluginName;
- return this;
- }
-
- public Builder setLangPluginParameter(String langPluginParameter) {
- this.langPluginParameter = langPluginParameter;
- return this;
- }
-
- public Builder setLangPluginParameterSupplier(Supplier<String> langPluginParameterSupplier) {
- this.langPluginParameterSupplier = langPluginParameterSupplier;
- return this;
- }
-
- public Builder(RuleContext ruleContext, SupportData supportData, String language,
- String langPrefix, Iterable<Artifact> outputs) {
- this.ruleContext = ruleContext;
- this.supportData = supportData;
- this.language = language;
- this.langPrefix = langPrefix;
- this.outputs = outputs;
- }
-
- /** Static class to avoid keeping a reference to this builder after build() is called. */
- private static class LazyLangPluginFlag extends LazyString {
- private final String langPrefix;
- private final Supplier<String> langPluginParameter1;
-
- LazyLangPluginFlag(String langPrefix, Supplier<String> langPluginParameter1) {
- this.langPrefix = langPrefix;
- this.langPluginParameter1 = langPluginParameter1;
- }
-
- @Override
- public String toString() {
- return String.format("--%s_out=%s", langPrefix, langPluginParameter1.get());
- }
- }
-
- public Optional<ProtoCompileAction> build() {
- checkState(langPluginParameter == null || langPluginParameterSupplier == null,
- "Only one of {langPluginParameter, langPluginParameterSupplier} should be set.");
-
- final Supplier<String> langPluginParameter1 =
- langPluginParameter == null
- ? langPluginParameterSupplier
- : Suppliers.ofInstance(langPluginParameter);
- if (isEmpty(outputs)) {
- return absent();
- }
-
- FilesToRunProvider langPluginTarget = null;
- List<? extends CharSequence> prefixArguments;
- if (langPluginName != null) {
- Preconditions.checkArgument(langParameter == null);
- Preconditions.checkArgument(langPluginParameter1 != null);
- // We pass a separate langPluginName as there are plugins that cannot be overridden
- // and thus we have to deal with "$xx_plugin" and "xx_plugin".
- langPluginTarget = ruleContext.getExecutablePrerequisite(langPluginName, Mode.HOST);
- if (ruleContext.hasErrors()) {
- return absent();
- }
- prefixArguments =
- ImmutableList.of(
- String.format(
- "--plugin=protoc-gen-%s=%s",
- langPrefix,
- langPluginTarget.getExecutable().getExecPathString()),
- new LazyLangPluginFlag(langPrefix, langPluginParameter1));
- } else {
- prefixArguments =
- (langParameter != null) ? ImmutableList.of(langParameter) : ImmutableList.<String>of();
- }
-
- List<String> suffixArguments =
- hasServices ? ImmutableList.<String>of() : ImmutableList.of("--disallow_services");
-
- FilesToRunProvider compilerTarget =
- ruleContext.getExecutablePrerequisite("$compiler", Mode.HOST);
-
- if (ruleContext.hasErrors()) {
- return absent();
- }
-
- return Optional.of(
- new ProtoCompileAction(
- ruleContext,
- supportData,
- language,
- suffixArguments,
- outputs,
- prefixArguments,
- langPluginTarget,
- compilerTarget));
- }
- }
-
- /**
- * A convenience method to register an action, if it's present.
- * @param protoCompileActionOptional
- */
- public static void registerAction(Optional<ProtoCompileAction> protoCompileActionOptional) {
- if (protoCompileActionOptional.isPresent()) {
- protoCompileActionOptional.get().registerAction();
- }
- }
-
- public ProtoCompileAction(
- RuleContext ruleContext,
- SupportData supportData,
- String language,
- List<String> suffixArguments,
- Iterable<Artifact> outputs,
- List<? extends CharSequence> prefixArguments,
- FilesToRunProvider langPluginTarget,
- FilesToRunProvider compilerTarget) {
- this.ruleContext = ruleContext;
- this.supportData = supportData;
- this.language = language;
- this.suffixArguments = suffixArguments;
- this.outputs = outputs;
- this.prefixArguments = prefixArguments;
- this.langPluginTarget = langPluginTarget;
- this.compilerTarget = compilerTarget;
- }
-
- /**
- * Registers a proto compile action with the RuleContext.
- */
- public void registerAction() {
- SpawnAction.Builder action = createAction(protoCompileCommandLine().build());
- ruleContext.registerAction(action.build(ruleContext));
- }
-
- public SpawnAction.Builder createAction(CommandLine commandLine) {
- SpawnAction.Builder builder =
- new SpawnAction.Builder().addTransitiveInputs(supportData.getTransitiveImports());
-
- // We also depend on the strict protodeps result to ensure this is run.
- if (supportData.getUsedDirectDeps() != null) {
- builder.addInput(supportData.getUsedDirectDeps());
- }
-
- if (langPluginTarget != null) {
- builder.addTool(langPluginTarget);
- }
-
- builder
- .addOutputs(outputs)
- .setResources(GENPROTO_RESOURCE_SET)
- .useDefaultShellEnvironment()
- .setExecutable(compilerTarget)
- .setCommandLine(commandLine)
- .setProgressMessage("Generating " + language + " proto_library " + ruleContext.getLabel())
- .setMnemonic(MNEMONIC);
-
- return builder;
- }
-
- /**
- * Static inner class since these objects live into the execution phase and so they must not
- * keep alive references to the surrounding analysis-phase objects.
- */
- private static class ProtoCommandLineArgv extends CustomMultiArgv {
- private final Iterable<Artifact> transitiveImports;
-
- ProtoCommandLineArgv(Iterable<Artifact> transitiveImports) {
- this.transitiveImports = transitiveImports;
- }
-
- @Override
- public Iterable<String> argv() {
- ImmutableList.Builder<String> builder = ImmutableList.builder();
- for (Artifact artifact : transitiveImports) {
- builder.add(
- "-I"
- + artifact.getRootRelativePath().getPathString()
- + "="
- + artifact.getExecPathString());
- }
- return builder.build();
- }
- }
-
- /* Commandline generator for protoc invocations. */
- public CustomCommandLine.Builder protoCompileCommandLine() {
- CustomCommandLine.Builder arguments = CustomCommandLine.builder();
- for (CharSequence charSequence : prefixArguments) {
- arguments.add(charSequence);
- }
- arguments.add(ruleContext.getFragment(ProtoConfiguration.class).protocOpts());
-
- // Add include maps
- arguments.add(new ProtoCommandLineArgv(supportData.getTransitiveImports()));
-
- for (Artifact src : supportData.getDirectProtoSources()) {
- arguments.addPath(src.getRootRelativePath());
- }
-
- arguments.add(suffixArguments);
- return arguments;
- }
-}
-
diff --git a/src/main/java/com/google/devtools/build/lib/rules/proto/ProtoCompileActionBuilder.java b/src/main/java/com/google/devtools/build/lib/rules/proto/ProtoCompileActionBuilder.java
new file mode 100644
index 0000000000..a743bc4011
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/rules/proto/ProtoCompileActionBuilder.java
@@ -0,0 +1,297 @@
+// Copyright 2016 The Bazel Authors. All rights reserved.
+//
+// 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.
+
+package com.google.devtools.build.lib.rules.proto;
+
+import static com.google.common.base.Preconditions.checkState;
+import static com.google.common.collect.Iterables.isEmpty;
+
+import com.google.common.base.Preconditions;
+import com.google.common.base.Supplier;
+import com.google.common.base.Suppliers;
+import com.google.common.collect.ImmutableList;
+import com.google.devtools.build.lib.actions.Action;
+import com.google.devtools.build.lib.actions.Artifact;
+import com.google.devtools.build.lib.actions.ResourceSet;
+import com.google.devtools.build.lib.analysis.FilesToRunProvider;
+import com.google.devtools.build.lib.analysis.RuleConfiguredTarget;
+import com.google.devtools.build.lib.analysis.RuleContext;
+import com.google.devtools.build.lib.analysis.actions.CustomCommandLine;
+import com.google.devtools.build.lib.analysis.actions.SpawnAction;
+import com.google.devtools.build.lib.util.LazyString;
+
+import javax.annotation.Nullable;
+
+/**
+ * Constructs actions to run the protocol compiler to generate sources from .proto files.
+ */
+public class ProtoCompileActionBuilder {
+ private static final String MNEMONIC = "GenProto";
+ private static final ResourceSet GENPROTO_RESOURCE_SET =
+ ResourceSet.createWithRamCpuIo(100, .1, .0);
+ private static final Action[] NO_ACTIONS = new Action[0];
+
+ private RuleContext ruleContext;
+ private SupportData supportData;
+ private String language;
+ private String langPrefix;
+ private Iterable<Artifact> outputs;
+ private String langParameter;
+ private String langPluginName;
+ private String langPluginParameter;
+ private Supplier<String> langPluginParameterSupplier;
+ private boolean hasServices;
+ private Iterable<String> additionalCommandLineArguments;
+ private Iterable<FilesToRunProvider> additionalTools;
+
+ public ProtoCompileActionBuilder setRuleContext(RuleContext ruleContext) {
+ this.ruleContext = ruleContext;
+ return this;
+ }
+
+ public ProtoCompileActionBuilder setSupportData(SupportData supportData) {
+ this.supportData = supportData;
+ return this;
+ }
+
+ public ProtoCompileActionBuilder setLanguage(String language) {
+ this.language = language;
+ return this;
+ }
+
+ public ProtoCompileActionBuilder setLangPrefix(String langPrefix) {
+ this.langPrefix = langPrefix;
+ return this;
+ }
+
+ public ProtoCompileActionBuilder setHasServices(boolean hasServices) {
+ this.hasServices = hasServices;
+ return this;
+ }
+
+ public ProtoCompileActionBuilder setOutputs(Iterable<Artifact> outputs) {
+ this.outputs = outputs;
+ return this;
+ }
+
+ public ProtoCompileActionBuilder setLangParameter(String langParameter) {
+ this.langParameter = langParameter;
+ return this;
+ }
+
+ public ProtoCompileActionBuilder setLangPluginName(String langPluginName) {
+ this.langPluginName = langPluginName;
+ return this;
+ }
+
+ public ProtoCompileActionBuilder setLangPluginParameter(String langPluginParameter) {
+ this.langPluginParameter = langPluginParameter;
+ return this;
+ }
+
+ public ProtoCompileActionBuilder setLangPluginParameterSupplier(
+ Supplier<String> langPluginParameterSupplier) {
+ this.langPluginParameterSupplier = langPluginParameterSupplier;
+ return this;
+ }
+
+ public ProtoCompileActionBuilder setAdditionalCommandLineArguments(
+ Iterable<String> additionalCmdLine) {
+ this.additionalCommandLineArguments = additionalCmdLine;
+ return this;
+ }
+
+ public ProtoCompileActionBuilder setAdditionalTools(
+ Iterable<FilesToRunProvider> additionalTools) {
+ this.additionalTools = additionalTools;
+ return this;
+ }
+
+ public ProtoCompileActionBuilder(
+ RuleContext ruleContext,
+ SupportData supportData,
+ String language,
+ String langPrefix,
+ Iterable<Artifact> outputs) {
+ this.ruleContext = ruleContext;
+ this.supportData = supportData;
+ this.language = language;
+ this.langPrefix = langPrefix;
+ this.outputs = outputs;
+ }
+
+ /**
+ * Static class to avoid keeping a reference to this builder after build() is called.
+ */
+ private static class LazyLangPluginFlag extends LazyString {
+ private final String langPrefix;
+ private final Supplier<String> langPluginParameter1;
+
+ LazyLangPluginFlag(String langPrefix, Supplier<String> langPluginParameter1) {
+ this.langPrefix = langPrefix;
+ this.langPluginParameter1 = langPluginParameter1;
+ }
+
+ @Override
+ public String toString() {
+ return String.format("--%s_out=%s", langPrefix, langPluginParameter1.get());
+ }
+ }
+
+ public Action[] build() {
+ checkState(
+ langPluginParameter == null || langPluginParameterSupplier == null,
+ "Only one of {langPluginParameter, langPluginParameterSupplier} should be set.");
+
+ if (isEmpty(outputs)) {
+ return NO_ACTIONS;
+ }
+
+ try {
+ return createAction().build(ruleContext);
+ } catch (MissingPrerequisiteException e) {
+ return NO_ACTIONS;
+ }
+ }
+
+ private SpawnAction.Builder createAction() {
+ SpawnAction.Builder result =
+ new SpawnAction.Builder().addTransitiveInputs(supportData.getTransitiveImports());
+
+ // We also depend on the strict protodeps result to ensure this is run.
+ if (supportData.getUsedDirectDeps() != null) {
+ result.addInput(supportData.getUsedDirectDeps());
+ }
+
+ FilesToRunProvider langPluginTarget = getLangPluginTarget();
+ if (langPluginTarget != null) {
+ result.addTool(langPluginTarget);
+ }
+
+ FilesToRunProvider compilerTarget =
+ ruleContext.getExecutablePrerequisite("$compiler", RuleConfiguredTarget.Mode.HOST);
+ if (ruleContext.hasErrors()) {
+ throw new MissingPrerequisiteException();
+ }
+
+ if (this.additionalTools != null) {
+ for (FilesToRunProvider tool : additionalTools) {
+ result.addTool(tool);
+ }
+ }
+
+ result
+ .addOutputs(outputs)
+ .setResources(GENPROTO_RESOURCE_SET)
+ .useDefaultShellEnvironment()
+ .setExecutable(compilerTarget)
+ .setCommandLine(createProtoCompilerCommandLine().build())
+ .setProgressMessage("Generating " + language + " proto_library " + ruleContext.getLabel())
+ .setMnemonic(MNEMONIC);
+
+ return result;
+ }
+
+ @Nullable
+ private FilesToRunProvider getLangPluginTarget() {
+ if (langPluginName == null) {
+ return null;
+ }
+ FilesToRunProvider result =
+ ruleContext.getExecutablePrerequisite(langPluginName, RuleConfiguredTarget.Mode.HOST);
+ if (ruleContext.hasErrors()) {
+ throw new MissingPrerequisiteException();
+ }
+ return result;
+ }
+
+ /**
+ * Commandline generator for protoc invocations.
+ */
+ public CustomCommandLine.Builder createProtoCompilerCommandLine() {
+ CustomCommandLine.Builder result = CustomCommandLine.builder();
+
+ if (langPluginName == null) {
+ if (langParameter != null) {
+ result.add(langParameter);
+ }
+ } else {
+ FilesToRunProvider langPluginTarget = getLangPluginTarget();
+ Supplier<String> langPluginParameter1 =
+ langPluginParameter == null
+ ? langPluginParameterSupplier
+ : Suppliers.ofInstance(langPluginParameter);
+
+ Preconditions.checkArgument(langParameter == null);
+ Preconditions.checkArgument(langPluginParameter1 != null);
+ // We pass a separate langPluginName as there are plugins that cannot be overridden
+ // and thus we have to deal with "$xx_plugin" and "xx_plugin".
+ result.add(
+ String.format(
+ "--plugin=protoc-gen-%s=%s",
+ langPrefix,
+ langPluginTarget.getExecutable().getExecPathString()));
+ result.add(new LazyLangPluginFlag(langPrefix, langPluginParameter1));
+ }
+
+ result.add(ruleContext.getFragment(ProtoConfiguration.class).protocOpts());
+
+ // Add include maps
+ result.add(new ProtoCommandLineArgv(supportData.getTransitiveImports()));
+
+ for (Artifact src : supportData.getDirectProtoSources()) {
+ result.addPath(src.getRootRelativePath());
+ }
+
+ if (!hasServices) {
+ result.add("--disallow_services");
+ }
+
+ if (additionalCommandLineArguments != null) {
+ result.add(additionalCommandLineArguments);
+ }
+
+ return result;
+ }
+
+ /**
+ * Static inner class since these objects live into the execution phase and so they must not
+ * keep alive references to the surrounding analysis-phase objects.
+ */
+ private static class ProtoCommandLineArgv extends CustomCommandLine.CustomMultiArgv {
+ private final Iterable<Artifact> transitiveImports;
+
+ ProtoCommandLineArgv(Iterable<Artifact> transitiveImports) {
+ this.transitiveImports = transitiveImports;
+ }
+
+ @Override
+ public Iterable<String> argv() {
+ ImmutableList.Builder<String> builder = ImmutableList.builder();
+ for (Artifact artifact : transitiveImports) {
+ builder.add(
+ "-I"
+ + artifact.getRootRelativePath().getPathString()
+ + "="
+ + artifact.getExecPathString());
+ }
+ return builder.build();
+ }
+ }
+
+ /**
+ * Signifies that a prerequisite could not be satisfied.
+ */
+ private static class MissingPrerequisiteException extends RuntimeException {}
+}