Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions lib/DependencyScan/ModuleDependencyScanner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -620,6 +620,23 @@ ModuleDependencyScanner::getMainModuleDependencyInfo(ModuleDecl *mainModule) {
break;
}

if (ScanASTContext.LangOpts.EnableCXXInterop) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you please add a comment with a detailed explanation for why Windows behavior differs and why the default flow in

if (lookupCxxStdLibOverlay) {
is insufficient.

Copy link
Contributor Author

@hjyamauchi hjyamauchi Dec 12, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We (and the IRGenModule code) currently assume that we always link with and add dependency on CxxStdlib if C++ interop is enabled (dynamic or static but it needs to be currently static linking for Windows.) Hence this approach in this PR. But it looks like this lookupCxxStdLibOverlay code doesn't seem to assume that. Do you know why?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this code and the lookupCxxStdLibOverlay code are orthogonal. We currently and do always link with CxxStdlib if C++ interop is enabled, dynamic or static. So, we explicitly add CxxStdlib to the (transitive) dependency set by adding a dependency to the main/root module for all platforms but in particular for Windows because it needs to know if it's static or dynamic to determine the correct library name, which this new code does. The lookupCxxStdLibOverlay code differs in that it only adds a CxxStdlib dep if a module depends on the clang std module. We still need the lookupCxxStdLibOverlay code because it affects the direct dependencies of non-root/individual modules (like adding a CxxStdlib dep to what only has a dep on the underlying std module or not adding it to the Darwin module, etc.) as the no-cxx-overlay-for-non-interop-interface.swift test checks.

StringRef mainModuleName = mainModule->getName().str();
if (mainModuleName != CXX_MODULE_NAME)
mainDependencies.addModuleImport(CXX_MODULE_NAME, /* isExported */ false,
AccessLevel::Public,
&alreadyAddedModules);
if (llvm::none_of(llvm::ArrayRef<StringRef>{CXX_MODULE_NAME,
ScanASTContext.Id_CxxStdlib.str(), "std"},
[mainModuleName](StringRef Name) {
return mainModuleName == Name;
}))
mainDependencies.addModuleImport(ScanASTContext.Id_CxxStdlib.str(),
/* isExported */ false,
AccessLevel::Public,
&alreadyAddedModules);
}

// Add any implicit module names.
for (const auto &import : importInfo.AdditionalUnloadedImports) {
mainDependencies.addModuleImport(
Expand Down
43 changes: 43 additions & 0 deletions test/ScanDependencies/win-explicit-cxx-interop-cxxstdlib.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// REQUIRES: OS=windows-msvc

// RUN: %empty-directory(%t)
// RUN: split-file %s %t
// RUN: %target-swift-frontend -scan-dependencies -module-name NoCpp \
// RUN: -module-cache-path %t/clang-module-cache -disable-objc-interop \
// RUN: -cxx-interoperability-mode=default \
// RUN: %t/NoCpp.swift -o %t/NoCpp-deps.json -I %t 2>&1
// RUN: %target-swift-frontend -scan-dependencies -module-name Cpp \
// RUN: -module-cache-path %t/clang-module-cache -disable-objc-interop \
// RUN: -cxx-interoperability-mode=default \
// RUN: %t/Cpp.swift -o %t/Cpp-deps.json -I %t 2>&1
// RUN: %target-swift-frontend -scan-dependencies -module-name Crt \
// RUN: -module-cache-path %t/clang-module-cache -disable-objc-interop \
// RUN: -cxx-interoperability-mode=default \
// RUN: %t/Crt.swift -o %t/Crt-deps.json -I %t 2>&1
// RUN: %FileCheck %s --check-prefix=NOCPP < %t/NoCpp-deps.json
// RUN: %FileCheck %s --check-prefix=CPP < %t/Cpp-deps.json
// RUN: %FileCheck %s --check-prefix=CRT < %t/Crt-deps.json

// NOCPP: "mainModuleName": "NoCpp"
// NOCPP: "linkName": "swiftCxxStdlib",
// NOCPP-NEXT: "isStatic": true,

// CPP: "mainModuleName": "Cpp"
// CPP: "linkName": "swiftCxxStdlib",
// CPP-NEXT: "isStatic": true,

// CRT: "mainModuleName": "Crt"
// CRT: "linkName": "swiftCxxStdlib",
// CRT-NEXT: "isStatic": true,

//--- NoCpp.swift
// Empty

//--- Cpp.swift
import CxxStdlib

//--- Crt.swift
import CRT