Add a generic additional_linker_inputs attribute on cc_binary rules.
This can be used to provide additional inputs that can be referenced by $(location) in linkopts.
RELNOTES: Add a generic additional_linker_inputs attribute on cc_binary rules.
PiperOrigin-RevId: 247973418
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/Expander.java b/src/main/java/com/google/devtools/build/lib/analysis/Expander.java
index 0e40e1e..e48ed8f 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/Expander.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/Expander.java
@@ -34,10 +34,19 @@
private final RuleContext ruleContext;
private final TemplateContext templateContext;
+ @Nullable ImmutableMap<Label, ImmutableCollection<Artifact>> labelMap;
Expander(RuleContext ruleContext, TemplateContext templateContext) {
+ this(ruleContext, templateContext, /* labelMap= */ null);
+ }
+
+ Expander(
+ RuleContext ruleContext,
+ TemplateContext templateContext,
+ @Nullable ImmutableMap<Label, ImmutableCollection<Artifact>> labelMap) {
this.ruleContext = ruleContext;
this.templateContext = templateContext;
+ this.labelMap = labelMap;
}
/**
@@ -46,8 +55,8 @@
*/
private Expander withLocations(boolean execPaths, boolean allowData) {
TemplateContext newTemplateContext =
- new LocationTemplateContext(templateContext, ruleContext, null, execPaths, allowData);
- return new Expander(ruleContext, newTemplateContext);
+ new LocationTemplateContext(templateContext, ruleContext, labelMap, execPaths, allowData);
+ return new Expander(ruleContext, newTemplateContext, labelMap);
}
/**
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 8b62449..ca8da90 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
@@ -1136,6 +1136,10 @@
return new Expander(this, getConfigurationMakeVariableContext());
}
+ public Expander getExpander(ImmutableMap<Label, ImmutableCollection<Artifact>> labelMap) {
+ return new Expander(this, getConfigurationMakeVariableContext(), labelMap);
+ }
+
/**
* Returns a cached context that maps Make variable names (string) to values (string) without any
* extra {@link MakeVariableSupplier}.
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/cpp/BazelCppRuleClasses.java b/src/main/java/com/google/devtools/build/lib/bazel/rules/cpp/BazelCppRuleClasses.java
index f2d0fba..25b837a 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/rules/cpp/BazelCppRuleClasses.java
+++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/cpp/BazelCppRuleClasses.java
@@ -472,6 +472,18 @@
@Override
public RuleClass build(RuleClass.Builder builder, RuleDefinitionEnvironment env) {
return builder
+ /*<!-- #BLAZE_RULE($cc_binary_base).ATTRIBUTE(additional_linker_inputs) -->
+ Pass these files to the C++ linker command.
+ <p>
+ For example, compiled Windows .res files can be provided here to be embedded in
+ the binary target.
+ </p>
+ <!-- #END_BLAZE_RULE.ATTRIBUTE -->*/
+ .add(
+ attr("additional_linker_inputs", LABEL_LIST)
+ .orderIndependent()
+ .direct_compile_time_input()
+ .allowedFileTypes(FileTypeSet.ANY_FILE))
/*<!-- #BLAZE_RULE($cc_binary_base).ATTRIBUTE(malloc) -->
Override the default dependency on malloc.
<p>
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcBinary.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcBinary.java
index 5a08694..69067a6 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcBinary.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcBinary.java
@@ -360,6 +360,7 @@
.merge(precompiledFileObjects)
.merge(compilationInfo.getCcCompilationOutputs())
.build();
+ Iterable<Artifact> additionalLinkerInputs = common.getAdditionalLinkerInputs();
// Allows the dynamic library generated for code of default dynamic mode targets to be linked
// separately. The main use case for default dynamic mode is the cc_test rule. The same behavior
@@ -479,6 +480,7 @@
common,
precompiledFiles,
ccCompilationOutputs,
+ additionalLinkerInputs,
ccLinkingOutputs,
ccCompilationContext,
fake,
@@ -672,6 +674,7 @@
CcCommon common,
PrecompiledFiles precompiledFiles,
CcCompilationOutputs ccCompilationOutputs,
+ Iterable<Artifact> additionalLinkerInputs,
CcLinkingOutputs ccLinkingOutputs,
CcCompilationContext ccCompilationContext,
boolean fake,
@@ -708,7 +711,8 @@
ruleContext.getSymbolGenerator())
.setGrepIncludes(CppHelper.getGrepIncludes(ruleContext))
.setIsStampingEnabled(AnalysisUtils.isStampingEnabled(ruleContext))
- .setTestOrTestOnlyTarget(ruleContext.isTestTarget() || ruleContext.isTestOnlyTarget());
+ .setTestOrTestOnlyTarget(ruleContext.isTestTarget() || ruleContext.isTestOnlyTarget())
+ .addNonCodeLinkerInputs(additionalLinkerInputs);
CcInfo depsCcInfo = CcInfo.builder().setCcLinkingContext(depsCcLinkingContext).build();
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcCommon.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcCommon.java
index 1a9ad14..36ecb13 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcCommon.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcCommon.java
@@ -676,6 +676,14 @@
}
/**
+ * Returns all additional linker inputs specified in the |additional_linker_inputs| attribute of
+ * the rule.
+ */
+ List<Artifact> getAdditionalLinkerInputs() {
+ return ruleContext.getPrerequisiteArtifacts("additional_linker_inputs", Mode.TARGET).list();
+ }
+
+ /**
* Replaces shared library artifact with mangled symlink and creates related
* symlink action. For artifacts that should retain filename (e.g. libraries
* with SONAME tag), link is created to the parent directory instead.
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppHelper.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppHelper.java
index d0c381d..4b8e27d 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppHelper.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppHelper.java
@@ -15,12 +15,14 @@
package com.google.devtools.build.lib.rules.cpp;
import static com.google.devtools.build.lib.packages.BuildType.LABEL;
+import static com.google.devtools.build.lib.packages.BuildType.LABEL_LIST;
import static com.google.devtools.build.lib.packages.BuildType.NODEP_LABEL;
import static java.nio.charset.StandardCharsets.UTF_8;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function;
import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableCollection;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
@@ -32,8 +34,10 @@
import com.google.devtools.build.lib.actions.MiddlemanFactory;
import com.google.devtools.build.lib.actions.ParamFileInfo;
import com.google.devtools.build.lib.actions.ParameterFile;
+import com.google.devtools.build.lib.analysis.AliasProvider;
import com.google.devtools.build.lib.analysis.AnalysisUtils;
import com.google.devtools.build.lib.analysis.Expander;
+import com.google.devtools.build.lib.analysis.FileProvider;
import com.google.devtools.build.lib.analysis.PlatformConfiguration;
import com.google.devtools.build.lib.analysis.RuleConfiguredTargetBuilder;
import com.google.devtools.build.lib.analysis.RuleContext;
@@ -165,7 +169,18 @@
public static List<String> expandLinkopts(
RuleContext ruleContext, String attrName, Iterable<String> values) {
List<String> result = new ArrayList<>();
- Expander expander = ruleContext.getExpander().withDataExecLocations();
+ ImmutableMap.Builder<Label, ImmutableCollection<Artifact>> builder = ImmutableMap.builder();
+
+ if (ruleContext.attributes().has("additional_linker_inputs", LABEL_LIST)) {
+ for (TransitiveInfoCollection current :
+ ruleContext.getPrerequisites("additional_linker_inputs", Mode.TARGET)) {
+ builder.put(
+ AliasProvider.getDependencyLabel(current),
+ ImmutableList.copyOf(current.getProvider(FileProvider.class).getFilesToBuild()));
+ }
+ }
+
+ Expander expander = ruleContext.getExpander(builder.build()).withDataExecLocations();
for (String value : values) {
expander.tokenizeAndExpandMakeVars(result, attrName, value);
}