diff --git a/site/docs/crosstool-reference.md b/site/docs/crosstool-reference.md index cb2d71c48ae8ca..ea2504d358439c 100644 --- a/site/docs/crosstool-reference.md +++ b/site/docs/crosstool-reference.md @@ -1035,4 +1035,11 @@ conditions. libraries. This makes incremental relinking faster. + + supports_dynamic_linker + + If enabled, C++ rules will know the toolchain can produce shared + libraries. + + 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 de63cc9cc46bc1..176889ad03934b 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 @@ -163,7 +163,7 @@ public static void init( .addLinkstamps(ruleContext.getPrerequisites("linkstamp", Mode.TARGET)); Artifact soImplArtifact = null; - boolean supportsDynamicLinker = ccToolchain.supportsDynamicLinker(); + boolean supportsDynamicLinker = ccToolchain.supportsDynamicLinker(featureConfiguration); // TODO(djasper): This is hacky. We should actually try to figure out whether we generate // ccOutputs. boolean createDynamicLibrary = diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchainProvider.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchainProvider.java index 29748451c85a70..c5773d9eb7ea00 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchainProvider.java +++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchainProvider.java @@ -553,11 +553,10 @@ public boolean supportsGoldLinker() { return toolchainInfo.supportsGoldLinker(); } - /** - * Returns whether the toolchain supports dynamic linking. - */ - public boolean supportsDynamicLinker() { - return toolchainInfo.supportsDynamicLinker(); + /** Returns whether the toolchain supports dynamic linking. */ + public boolean supportsDynamicLinker(FeatureConfiguration featureConfiguration) { + return toolchainInfo.supportsDynamicLinker() + || featureConfiguration.isEnabled(CppRuleClasses.SUPPORTS_DYNAMIC_LINKER); } /** diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppRuleClasses.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppRuleClasses.java index f1e1ed75326d2a..6fd1c2eefcb79c 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppRuleClasses.java +++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppRuleClasses.java @@ -391,6 +391,11 @@ public static Label ccToolchainTypeAttribute(RuleDefinitionEnvironment env) { /** A feature marking that the toolchain can use --start-lib/--end-lib flags */ public static final String SUPPORTS_START_END_LIB = "supports_start_end_lib"; + /** + * A feature marking that the toolchain can produce binaries that load shared libraries at + * runtime. + */ + public static final String SUPPORTS_DYNAMIC_LINKER = "supports_dynamic_linker"; /** Ancestor for all rules that do include scanning. */ public static final class CcIncludeScanningRule implements RuleDefinition { @Override diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppToolchainInfo.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppToolchainInfo.java index 691600aea7901e..d4a996fd648c27 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppToolchainInfo.java +++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppToolchainInfo.java @@ -332,11 +332,7 @@ public static CppToolchainInfo create( this.supportsFission = supportsFission; this.supportsStartEndLib = supportsStartEndLib; this.supportsEmbeddedRuntimes = supportsEmbeddedRuntimes; - this.supportsDynamicLinker = - supportsDynamicLinker - || toolchainFeatures - .getActivatableNames() - .contains(CppRuleClasses.DYNAMIC_LINKING_MODE); + this.supportsDynamicLinker = supportsDynamicLinker; this.supportsInterfaceSharedLibraries = supportsInterfaceSharedLibraries; this.supportsGoldLinker = supportsGoldLinker; this.toolchainNeedsPic = toolchainNeedsPic; diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/proto/CcProtoAspect.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/proto/CcProtoAspect.java index 016e9e1fa9f68d..fe1c57b8bfab0b 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/cpp/proto/CcProtoAspect.java +++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/proto/CcProtoAspect.java @@ -308,7 +308,7 @@ private CcLinkingHelper initializeLinkingHelper( helper.addDeps(deps); // TODO(dougk): Configure output artifact with action_config // once proto compile action is configurable from the crosstool. - if (!toolchain.supportsDynamicLinker()) { + if (!toolchain.supportsDynamicLinker(featureConfiguration)) { helper.setShouldCreateDynamicLibrary(false); } return helper; diff --git a/src/test/java/com/google/devtools/build/lib/packages/util/MockCcSupport.java b/src/test/java/com/google/devtools/build/lib/packages/util/MockCcSupport.java index 41e07358748c1c..8c2baf013920d2 100644 --- a/src/test/java/com/google/devtools/build/lib/packages/util/MockCcSupport.java +++ b/src/test/java/com/google/devtools/build/lib/packages/util/MockCcSupport.java @@ -62,6 +62,9 @@ public boolean apply(Artifact artifact) { public static final String DYNAMIC_LINKING_MODE_FEATURE = "feature { name: '" + CppRuleClasses.DYNAMIC_LINKING_MODE + "'}"; + public static final String SUPPORTS_DYNAMIC_LINKER_FEATURE = + "feature { name: '" + CppRuleClasses.SUPPORTS_DYNAMIC_LINKER + " enabled: true'}"; + /** Feature expected by the C++ rules when pic build is requested */ public static final String PIC_FEATURE = "" diff --git a/src/test/java/com/google/devtools/build/lib/rules/cpp/CcToolchainTest.java b/src/test/java/com/google/devtools/build/lib/rules/cpp/CcToolchainTest.java index d03c7a3fdb449e..586fefa9dbee8d 100644 --- a/src/test/java/com/google/devtools/build/lib/rules/cpp/CcToolchainTest.java +++ b/src/test/java/com/google/devtools/build/lib/rules/cpp/CcToolchainTest.java @@ -774,7 +774,7 @@ private void writeStarlarkRule() throws IOException { } @Test - public void testSupportsDynamicLinkerCheckFeatures() throws Exception { + public void testSupportsDynamicLinkerIsFalseWhenFeatureNotSet() throws Exception { scratch.file("a/BUILD", "cc_toolchain_alias(name = 'b')"); getAnalysisMock() @@ -789,7 +789,29 @@ public void testSupportsDynamicLinkerCheckFeatures() throws Exception { CcToolchainProvider toolchainProvider = (CcToolchainProvider) target.get(ToolchainInfo.PROVIDER); - assertThat(toolchainProvider.supportsDynamicLinker()).isTrue(); + assertThat(toolchainProvider.supportsDynamicLinker(FeatureConfiguration.EMPTY)).isFalse(); + } + + @Test + public void testSupportsDynamicLinkerIsTrueWhenFeatureSet() throws Exception { + scratch.file("a/BUILD", "cc_toolchain_alias(name = 'b')"); + + getAnalysisMock() + .ccSupport() + .setupCrosstool( + mockToolsConfig, + MockCcSupport.DYNAMIC_LINKING_MODE_FEATURE, + MockCcSupport.SUPPORTS_DYNAMIC_LINKER_FEATURE); + + // To make sure the toolchain doesn't define linking_mode_flags { mode: DYNAMIC } as that would + // also result in supportsDynamicLinker returning true + useConfiguration("--compiler=compiler_no_dyn_linker"); + + ConfiguredTarget target = getConfiguredTarget("//a:b"); + CcToolchainProvider toolchainProvider = + (CcToolchainProvider) target.get(ToolchainInfo.PROVIDER); + + assertThat(toolchainProvider.supportsDynamicLinker(FeatureConfiguration.EMPTY)).isFalse(); } // Tests CcCommon::enableStaticLinkCppRuntimesFeature when supports_embedded_runtimes is not