Allow ImplicitOutputsFunctions to be overriden on Rule creation. -- MOS_MIGRATED_REVID=129787305
diff --git a/src/main/java/com/google/devtools/build/lib/packages/Package.java b/src/main/java/com/google/devtools/build/lib/packages/Package.java index b05e6ae..e3f5954 100644 --- a/src/main/java/com/google/devtools/build/lib/packages/Package.java +++ b/src/main/java/com/google/devtools/build/lib/packages/Package.java
@@ -1021,7 +1021,32 @@ RuleClass ruleClass, Location location, AttributeContainer attributeContainer) { - return new Rule(pkg, label, ruleClass, location, attributeContainer); + return new Rule( + pkg, + label, + ruleClass, + location, + attributeContainer); + } + + /** + * Same to {@link #createRule(Label, RuleClass, Location, AttributeContainer)}, except + * allows specifying an {@link ImplicitOutputsFunction} override. Only use if you know what + * you're doing. + */ + Rule createRule( + Label label, + RuleClass ruleClass, + Location location, + AttributeContainer attributeContainer, + ImplicitOutputsFunction implicitOutputsFunction) { + return new Rule( + pkg, + label, + ruleClass, + location, + attributeContainer, + implicitOutputsFunction); } /**
diff --git a/src/main/java/com/google/devtools/build/lib/packages/Rule.java b/src/main/java/com/google/devtools/build/lib/packages/Rule.java index 02971e0..b99e55e 100644 --- a/src/main/java/com/google/devtools/build/lib/packages/Rule.java +++ b/src/main/java/com/google/devtools/build/lib/packages/Rule.java
@@ -77,17 +77,40 @@ private final Location location; + private final ImplicitOutputsFunction implicitOutputsFunction; + // Initialized in the call to populateOutputFiles. private List<OutputFile> outputFiles; private ListMultimap<String, OutputFile> outputFileMap; - Rule(Package pkg, Label label, RuleClass ruleClass, Location location, + Rule( + Package pkg, + Label label, + RuleClass ruleClass, + Location location, AttributeContainer attributeContainer) { + this( + pkg, + label, + ruleClass, + location, + attributeContainer, + ruleClass.getDefaultImplicitOutputsFunction()); + } + + Rule( + Package pkg, + Label label, + RuleClass ruleClass, + Location location, + AttributeContainer attributeContainer, + ImplicitOutputsFunction implicitOutputsFunction) { this.pkg = Preconditions.checkNotNull(pkg); this.label = label; this.ruleClass = Preconditions.checkNotNull(ruleClass); this.location = Preconditions.checkNotNull(location); this.attributes = attributeContainer; + this.implicitOutputsFunction = implicitOutputsFunction; this.containsErrors = false; } @@ -252,6 +275,10 @@ return location; } + public ImplicitOutputsFunction getImplicitOutputsFunction() { + return implicitOutputsFunction; + } + @Override public Rule getAssociatedRule() { return this; @@ -478,7 +505,7 @@ throws InterruptedException { try { RawAttributeMapper attributeMap = RawAttributeMapper.of(this); - for (String out : ruleClass.getImplicitOutputsFunction().getImplicitOutputs(attributeMap)) { + for (String out : implicitOutputsFunction.getImplicitOutputs(attributeMap)) { try { addOutputFile(pkgBuilder.createLabel(out), eventHandler); } catch (LabelSyntaxException e) {
diff --git a/src/main/java/com/google/devtools/build/lib/packages/RuleClass.java b/src/main/java/com/google/devtools/build/lib/packages/RuleClass.java index 62f8a24..751e6cf 100644 --- a/src/main/java/com/google/devtools/build/lib/packages/RuleClass.java +++ b/src/main/java/com/google/devtools/build/lib/packages/RuleClass.java
@@ -1136,18 +1136,21 @@ } /** - * Returns the function which determines the set of implicit outputs - * generated by a given rule. + * Returns the default function for determining the set of implicit outputs generated by a given + * rule. If not otherwise specified, this will be the implementation used by {@link Rule}s + * created with this {@link RuleClass}. * - * <p>An implicit output is an OutputFile that automatically comes into - * existence when a rule of this class is declared, and whose name is derived - * from the name of the rule. + * <p>Do not use this value to calculate implicit outputs for a rule, instead use + * {@link Rule#getImplicitOutputsFunction()}. * - * <p>Implicit outputs are a widely-relied upon. All ".so", - * and "_deploy.jar" targets referenced in BUILD files are examples. + * <p>An implicit output is an OutputFile that automatically comes into existence when a rule of + * this class is declared, and whose name is derived from the name of the rule. + * + * <p>Implicit outputs are a widely-relied upon. All ".so", and "_deploy.jar" targets referenced + * in BUILD files are examples. */ @VisibleForTesting - public ImplicitOutputsFunction getImplicitOutputsFunction() { + public ImplicitOutputsFunction getDefaultImplicitOutputsFunction() { return implicitOutputsFunction; } @@ -1349,9 +1352,15 @@ Label ruleLabel, AttributeValuesMap attributeValues, Location location, - AttributeContainer attributeContainer) + AttributeContainer attributeContainer, + ImplicitOutputsFunction implicitOutputsFunction) throws LabelSyntaxException, InterruptedException { - Rule rule = pkgBuilder.createRule(ruleLabel, this, location, attributeContainer); + Rule rule = pkgBuilder.createRule( + ruleLabel, + this, + location, + attributeContainer, + implicitOutputsFunction); populateRuleAttributeValues(rule, pkgBuilder, attributeValues, NullEventHandler.INSTANCE); rule.populateOutputFiles(NullEventHandler.INSTANCE, pkgBuilder); return rule;
diff --git a/src/main/java/com/google/devtools/build/lib/rules/SkylarkRuleContext.java b/src/main/java/com/google/devtools/build/lib/rules/SkylarkRuleContext.java index b95554c..994a1cd 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/SkylarkRuleContext.java +++ b/src/main/java/com/google/devtools/build/lib/rules/SkylarkRuleContext.java
@@ -174,12 +174,11 @@ addOutput(outputsBuilder, "executable", ruleContext.createOutputArtifact()); } ImplicitOutputsFunction implicitOutputsFunction = - ruleContext.getRule().getRuleClassObject().getImplicitOutputsFunction(); + ruleContext.getRule().getImplicitOutputsFunction(); if (implicitOutputsFunction instanceof SkylarkImplicitOutputsFunction) { SkylarkImplicitOutputsFunction func = - (SkylarkImplicitOutputsFunction) - ruleContext.getRule().getRuleClassObject().getImplicitOutputsFunction(); + (SkylarkImplicitOutputsFunction) implicitOutputsFunction; for (Map.Entry<String, String> entry : func.calculateOutputs(RawAttributeMapper.of(ruleContext.getRule())).entrySet()) { addOutput( @@ -655,7 +654,7 @@ } @SkylarkCallable(name = "info_file", structField = true, documented = false, - doc = "Returns the file that is used to hold the non-volatile workspace status for the " + doc = "Returns the file that is used to hold the non-volatile workspace status for the " + "current build request.") public Artifact getStableWorkspaceStatus() { return ruleContext.getAnalysisEnvironment().getStableWorkspaceStatusArtifact();
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcLibrary.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcLibrary.java index 4ebdb4f..0785b36 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcLibrary.java +++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcLibrary.java
@@ -131,8 +131,7 @@ // wrt. implicit output files, if the contract says so. Behavior here differs between Bazel // and Blaze. .setGenerateLinkActionsIfEmpty( - ruleContext.getRule().getRuleClassObject().getImplicitOutputsFunction() - != ImplicitOutputsFunction.NONE) + ruleContext.getRule().getImplicitOutputsFunction() != ImplicitOutputsFunction.NONE) .setLinkType(linkType) .setNeverLink(neverLink) .addPrecompiledFiles(precompiledFiles); @@ -195,9 +194,9 @@ } else if (!createDynamicLibrary && ruleContext.attributes().isConfigurable("srcs", BuildType.LABEL_LIST)) { // If "srcs" is configurable, the .so output is always declared because the logic that - // determines implicit outs doesn't know which value of "srcs" will ultimately get chosen. - // Here, where we *do* have the correct value, it may not contain any source files to - // generate an .so with. If that's the case, register a fake generating action to prevent + // determines implicit outs doesn't know which value of "srcs" will ultimately get chosen. + // Here, where we *do* have the correct value, it may not contain any source files to + // generate an .so with. If that's the case, register a fake generating action to prevent // a "no generating action for this artifact" error. Artifact solibArtifact = CppHelper.getLinuxLinkedArtifact(ruleContext, LinkTargetType.DYNAMIC_LIBRARY);