Add support for a cc_import() of a DLL with no interface library on Windows.
Depending on this is very nearly a no-op; the linker cannot reference DLLs with no interface library. However, it's necessary for the copy_dynamic_libraries_to_binary feature to work in cases where a DLL is referenced without use of its interface library. (e.g., LoadLibrary, or one DLL a target depends on that itself depends on another DLL).
RELNOTES: Allow cc_import() of a DLL with no interface library on Windows, used to document runtime dependencies.
PiperOrigin-RevId: 248716186
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcImport.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcImport.java
index b93932a..152768a 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcImport.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcImport.java
@@ -78,13 +78,12 @@
CppHelper.getToolchainUsingDefaultCcToolchainAttribute(ruleContext);
FeatureConfiguration featureConfiguration =
CcCommon.configureFeaturesOrReportRuleError(ruleContext, ccToolchain);
- boolean targetWindows = featureConfiguration.isEnabled(CppRuleClasses.TARGETS_WINDOWS);
Artifact staticLibrary = ruleContext.getPrerequisiteArtifact("static_library", Mode.TARGET);
Artifact sharedLibrary = ruleContext.getPrerequisiteArtifact("shared_library", Mode.TARGET);
Artifact interfaceLibrary =
ruleContext.getPrerequisiteArtifact("interface_library", Mode.TARGET);
- performErrorChecks(ruleContext, systemProvided, sharedLibrary, interfaceLibrary, targetWindows);
+ performErrorChecks(ruleContext, systemProvided, sharedLibrary, interfaceLibrary);
Artifact resolvedSymlinkDynamicLibrary = null;
Artifact resolvedSymlinkInterfaceLibrary = null;
@@ -192,8 +191,7 @@
RuleContext ruleContext,
boolean systemProvided,
Artifact sharedLibrary,
- Artifact interfaceLibrary,
- boolean targetsWindows) {
+ Artifact interfaceLibrary) {
// If the shared library will be provided by system during runtime, users are not supposed to
// specify shared_library.
if (systemProvided && sharedLibrary != null) {
@@ -206,11 +204,5 @@
ruleContext.ruleError(
"'shared_library' should be specified when 'system_provided' is false");
}
-
- if (targetsWindows && sharedLibrary != null && interfaceLibrary == null) {
- ruleContext.ruleError(
- "'interface library' must be specified when using cc_import for shared library on"
- + " Windows");
- }
}
}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/LibrariesToLinkCollector.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/LibrariesToLinkCollector.java
index 4ae243e..c8c8dbd 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/LibrariesToLinkCollector.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/LibrariesToLinkCollector.java
@@ -286,15 +286,18 @@
!Link.useStartEndLib(
input,
CppHelper.getArchiveType(cppConfiguration, ccToolchainProvider, featureConfiguration)));
+
+ expandedLinkerInputsBuilder.add(input);
if (featureConfiguration.isEnabled(CppRuleClasses.TARGETS_WINDOWS)
&& ccToolchainProvider.supportsInterfaceSharedLibraries(featureConfiguration)) {
// On Windows, dynamic library (dll) cannot be linked directly when using toolchains that
- // support interface library (eg. MSVC).
- Preconditions.checkState(
- !CppFileTypes.SHARED_LIBRARY.matches(input.getArtifact().getFilename()));
+ // support interface library (eg. MSVC). If the user is doing so, it is only to be referenced
+ // in other places (such as copy_dynamic_libraries_to_binary); skip adding it.
+ if (CppFileTypes.SHARED_LIBRARY.matches(input.getArtifact().getFilename())) {
+ return;
+ }
}
- expandedLinkerInputsBuilder.add(input);
Artifact inputArtifact = input.getArtifact();
PathFragment libDir = inputArtifact.getExecPath().getParentDirectory();
if (!libDir.equals(solibDir)
diff --git a/src/test/java/com/google/devtools/build/lib/rules/cpp/CcImportBaseConfiguredTargetTest.java b/src/test/java/com/google/devtools/build/lib/rules/cpp/CcImportBaseConfiguredTargetTest.java
index 2fe24fb..782e8cc 100644
--- a/src/test/java/com/google/devtools/build/lib/rules/cpp/CcImportBaseConfiguredTargetTest.java
+++ b/src/test/java/com/google/devtools/build/lib/rules/cpp/CcImportBaseConfiguredTargetTest.java
@@ -114,7 +114,7 @@
}
@Test
- public void testWrongCcImportDefinitionsOnWindows() throws Exception {
+ public void testRuntimeOnlyCcImportDefinitionsOnWindows() throws Exception {
AnalysisMock.get()
.ccSupport()
.setupCcToolchainConfig(
@@ -124,15 +124,22 @@
CppRuleClasses.COPY_DYNAMIC_LIBRARIES_TO_BINARY,
CppRuleClasses.TARGETS_WINDOWS));
useConfiguration();
- checkError(
- "a",
- "foo",
- "'interface library' must be specified when using cc_import for shared library on Windows",
- skylarkImplementationLoadStatement,
- "cc_import(",
- " name = 'foo',",
- " shared_library = 'libfoo.dll',",
- ")");
+ ConfiguredTarget target =
+ scratchConfiguredTarget(
+ "a",
+ "foo",
+ skylarkImplementationLoadStatement,
+ "cc_import(name = 'foo', shared_library = 'libfoo.dll')");
+ Artifact dynamicLibrary =
+ Iterables.getOnlyElement(target.get(CcInfo.PROVIDER).getCcLinkingContext().getLibraries())
+ .getResolvedSymlinkDynamicLibrary();
+ Iterable<Artifact> dynamicLibrariesForRuntime =
+ target
+ .get(CcInfo.PROVIDER)
+ .getCcLinkingContext()
+ .getDynamicLibrariesForRuntime(/* linkingStatically= */ false);
+ assertThat(dynamicLibrary).isEqualTo(null);
+ assertThat(artifactsToStrings(dynamicLibrariesForRuntime)).containsExactly("src a/libfoo.dll");
}
@Test