diff options
Diffstat (limited to 'src')
5 files changed, 84 insertions, 1 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/cpp/BazelCcBinaryRule.java b/src/main/java/com/google/devtools/build/lib/bazel/rules/cpp/BazelCcBinaryRule.java index df577ad7d9..74d15d78f7 100644 --- a/src/main/java/com/google/devtools/build/lib/bazel/rules/cpp/BazelCcBinaryRule.java +++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/cpp/BazelCcBinaryRule.java @@ -15,6 +15,7 @@ package com.google.devtools.build.lib.bazel.rules.cpp; import static com.google.devtools.build.lib.packages.Attribute.attr; +import static com.google.devtools.build.lib.packages.BuildType.LABEL; import static com.google.devtools.build.lib.syntax.Type.BOOLEAN; import com.google.devtools.build.lib.analysis.BaseRuleClasses; @@ -25,6 +26,7 @@ import com.google.devtools.build.lib.packages.RuleClass; import com.google.devtools.build.lib.packages.RuleClass.Builder; import com.google.devtools.build.lib.rules.cpp.CppConfiguration; import com.google.devtools.build.lib.rules.cpp.CppRuleClasses; +import com.google.devtools.build.lib.util.FileType; /** Rule definition for cc_binary rules. */ public final class BazelCcBinaryRule implements RuleDefinition { @@ -73,6 +75,11 @@ public final class BazelCcBinaryRule implements RuleDefinition { attr("linkshared", BOOLEAN) .value(false) .nonconfigurable("used to *determine* the rule's configuration")) + /*<!-- #BLAZE_RULE(cc_binary).ATTRIBUTE(linkopts_file) --> + A file with additional options to pass to the linker. The file can be generated during + execution. + <!-- #END_BLAZE_RULE.ATTRIBUTE -->*/ + .add(attr("linkopts_file", LABEL).allowedFileTypes(FileType.of("linkopts_file"))) .cfg(CppRuleClasses.LIPO_ON_DEMAND) .build(); } 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 61f6c2a18c..727db97d60 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 @@ -13,6 +13,8 @@ // limitations under the License. package com.google.devtools.build.lib.rules.cpp; +import static com.google.devtools.build.lib.packages.BuildType.LABEL; + import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Function; import com.google.common.base.Preconditions; @@ -165,6 +167,7 @@ public abstract class CcBinary implements RuleConfiguredTargetFactory { return CcBinary.init(semantics, context, /*fake =*/ false); } + // TODO(plf): Split up this method. public static ConfiguredTarget init(CppSemantics semantics, RuleContext ruleContext, boolean fake) throws InterruptedException, RuleErrorException { ruleContext.checkSrcsSamePackage(true); @@ -286,6 +289,12 @@ public abstract class CcBinary implements RuleConfiguredTargetFactory { linkCompileOutputSeparately, semantics); linkActionBuilder.setUseTestOnlyFlags(ruleContext.isTestTarget()); + if (ruleContext.isAttrDefined("linkopts_file", LABEL)) { + Artifact linkoptsFile = ruleContext.getPrerequisiteArtifact("linkopts_file", Mode.DONT_CHECK); + if (linkoptsFile != null) { + linkActionBuilder.setLinkoptsParamFile(linkoptsFile); + } + } if (linkStaticness == LinkStaticness.DYNAMIC) { linkActionBuilder.setRuntimeInputs( ArtifactCategory.DYNAMIC_LIBRARY, diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppActionConfigs.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppActionConfigs.java index a12e21ddad..29e78c3d9d 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppActionConfigs.java +++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppActionConfigs.java @@ -439,6 +439,7 @@ public class CppActionConfigs { " implies: 'libraries_to_link'", " implies: 'force_pic_flags'", " implies: 'legacy_link_flags'", + " implies: 'linkopts_file'", " implies: 'linker_param_file'", " implies: 'fission_support'", " implies: 'sysroot'", @@ -462,6 +463,7 @@ public class CppActionConfigs { " implies: 'library_search_directories'", " implies: 'libraries_to_link'", " implies: 'legacy_link_flags'", + " implies: 'linkopts_file'", " implies: 'linker_param_file'", " implies: 'fission_support'", " implies: 'sysroot'", @@ -1057,6 +1059,29 @@ public class CppActionConfigs { " }", "}"), ifTrue( + !existingFeatureNames.contains("linkopts_file"), + "feature {", + " name: 'linkopts_file'", + " flag_set {", + " expand_if_all_available: 'linkopts_file'", + " action: 'c++-link-executable'", + " action: 'c++-link-dynamic-library'", + " flag_group {", + " flag: '-Wl,@%{linkopts_file}'", + " }", + " }", + " flag_set {", + " expand_if_all_available: 'linkopts_file'", + " action: 'c++-link-static-library'", + " action: 'c++-link-alwayslink-static-library'", + " action: 'c++-link-pic-static-library'", + " action: 'c++-link-alwayslink-pic-static-library'", + " flag_group {", + " flag: '@%{linkopts_file}'", + " }", + " }", + "}"), + ifTrue( !existingFeatureNames.contains("linker_param_file"), "feature {", " name: 'linker_param_file'", diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppLinkActionBuilder.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppLinkActionBuilder.java index 200bd3a7ae..e0cd9a44d9 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppLinkActionBuilder.java +++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppLinkActionBuilder.java @@ -111,6 +111,9 @@ public class CppLinkActionBuilder { */ public static final String LINKER_PARAM_FILE_VARIABLE = "linker_param_file"; + /** A build variable for linker flags read from a file provided by the user. */ + public static final String LINK_OPTS_FILE_VARIABLE = "linkopts_file"; + /** A build variable for the execpath of the output of the linker. */ public static final String OUTPUT_EXECPATH_VARIABLE = "output_execpath"; @@ -195,6 +198,7 @@ public class CppLinkActionBuilder { private final ImmutableSet.Builder<Linkstamp> linkstampsBuilder = ImmutableSet.builder(); private ImmutableList<String> additionalLinkstampDefines = ImmutableList.of(); private final List<String> linkopts = new ArrayList<>(); + private Artifact linkoptsFile; private LinkTargetType linkType = LinkTargetType.STATIC_LIBRARY; private LinkStaticness linkStaticness = LinkStaticness.FULLY_STATIC; private String libraryIdentifier = null; @@ -918,6 +922,7 @@ public class CppLinkActionBuilder { runtimeLinkerInputs, /* output= */ null, paramFile, + linkoptsFile, thinltoParamFile, thinltoMergedObjectFile, ltoOutputRootPrefix, @@ -932,6 +937,7 @@ public class CppLinkActionBuilder { runtimeLinkerInputs, output, paramFile, + linkoptsFile, thinltoParamFile, thinltoMergedObjectFile, /* ltoOutputRootPrefix= */ PathFragment.EMPTY_FRAGMENT, @@ -1273,7 +1279,7 @@ public class CppLinkActionBuilder { for (VariablesExtension variablesExtension : variablesExtensions) { addVariablesExtension(variablesExtension); } - return this; + return this; } /** @@ -1474,6 +1480,15 @@ public class CppLinkActionBuilder { return this; } + /** Will pass a file with additional options to the linker. */ + public CppLinkActionBuilder setLinkoptsParamFile(Artifact linkoptsFile) { + Preconditions.checkState(this.linkoptsFile == null); + Preconditions.checkNotNull(linkoptsFile); + this.linkoptsFile = linkoptsFile; + addActionInput(linkoptsFile); + return this; + } + /** Sets whether this link action will be used for a cc_fake_binary; false by default. */ public CppLinkActionBuilder setFake(boolean fake) { this.fake = fake; @@ -1593,6 +1608,7 @@ public class CppLinkActionBuilder { private final Artifact interfaceLibraryBuilder; private final Artifact interfaceLibraryOutput; private final Artifact paramFile; + private final Artifact linkoptsFile; private final Artifact thinltoParamFile; private final Artifact thinltoMergedObjectFile; private final PathFragment ltoOutputRootPrefix; @@ -1607,6 +1623,7 @@ public class CppLinkActionBuilder { ImmutableList<LinkerInput> runtimeLinkerInputs, Artifact output, Artifact paramFile, + Artifact linkoptsFile, Artifact thinltoParamFile, Artifact thinltoMergedObjectFile, PathFragment ltoOutputRootPrefix, @@ -1621,6 +1638,7 @@ public class CppLinkActionBuilder { this.interfaceLibraryBuilder = interfaceLibraryBuilder; this.interfaceLibraryOutput = interfaceLibraryOutput; this.paramFile = paramFile; + this.linkoptsFile = linkoptsFile; this.thinltoParamFile = thinltoParamFile; this.thinltoMergedObjectFile = thinltoMergedObjectFile; this.ltoOutputRootPrefix = ltoOutputRootPrefix; @@ -1679,6 +1697,10 @@ public class CppLinkActionBuilder { buildVariables.addStringVariable(LINKER_PARAM_FILE_VARIABLE, paramFile.getExecPathString()); } + if (linkoptsFile != null) { + buildVariables.addStringVariable(LINK_OPTS_FILE_VARIABLE, linkoptsFile.getExecPathString()); + } + // output exec path if (outputArtifact != null) { buildVariables.addStringVariable( diff --git a/src/test/java/com/google/devtools/build/lib/rules/cpp/LinkBuildVariablesTest.java b/src/test/java/com/google/devtools/build/lib/rules/cpp/LinkBuildVariablesTest.java index aa21798b4c..1f039cf095 100644 --- a/src/test/java/com/google/devtools/build/lib/rules/cpp/LinkBuildVariablesTest.java +++ b/src/test/java/com/google/devtools/build/lib/rules/cpp/LinkBuildVariablesTest.java @@ -105,6 +105,26 @@ public class LinkBuildVariablesTest extends LinkBuildVariablesTestCase { } @Test + public void testLinkoptsFileIsExported() throws Exception { + AnalysisMock.get().ccSupport().setupCrosstool(mockToolsConfig); + useConfiguration(); + + scratch.file( + "x/BUILD", + "cc_binary(", + " name = 'bin',", + " srcs = ['bin.cc'],", + " linkopts_file= 'bin.linkopts_file'", + ")"); + + ConfiguredTarget target = getConfiguredTarget("//x:bin"); + Variables variables = getLinkBuildVariables(target, Link.LinkTargetType.EXECUTABLE); + String variableValue = + getVariableValue(variables, CppLinkActionBuilder.LINK_OPTS_FILE_VARIABLE); + assertThat(variableValue).matches("x/bin.linkopts_file"); + } + + @Test public void testInterfaceLibraryBuildingVariablesWhenGenerationPossible() throws Exception { // Make sure the interface shared object generation is enabled in the configuration // (which it is not by default for some windows toolchains) |