mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Fix direct clang cc1 emit-pcm commands with vfs overlay on Windows (#85325)
Explicit module builds currently fail on Windows because direct-clang-cc1-module-build emit-pcm commands take overlaid system module map files as inputs but miss the clang VFS overlay. This change adds the overlay and fixes explicit module builds on Windows.
This commit is contained in:
@@ -75,6 +75,7 @@ namespace dependencies {
|
||||
namespace swift {
|
||||
enum class ResultConvention : uint8_t;
|
||||
class ASTContext;
|
||||
class CASOptions;
|
||||
class CompilerInvocation;
|
||||
class ClangImporterOptions;
|
||||
class ClangInheritanceInfo;
|
||||
@@ -83,6 +84,7 @@ class ClangNode;
|
||||
class ConcreteDeclRef;
|
||||
class Decl;
|
||||
class DeclContext;
|
||||
class DiagnosticEngine;
|
||||
class EffectiveClangContext;
|
||||
class EnumDecl;
|
||||
class FuncDecl;
|
||||
@@ -878,6 +880,25 @@ struct ClangInvocationFileMapping {
|
||||
bool requiresBuiltinHeadersInSystemModules;
|
||||
};
|
||||
|
||||
class ClangInvocationFileMappingContext {
|
||||
public:
|
||||
const LangOptions &LangOpts;
|
||||
SearchPathOptions &SearchPathOpts;
|
||||
ClangImporterOptions &ClangImporterOpts;
|
||||
const CASOptions &CASOpts;
|
||||
DiagnosticEngine &Diags;
|
||||
|
||||
ClangInvocationFileMappingContext(
|
||||
const LangOptions &LangOpts, SearchPathOptions &SearchPathOpts,
|
||||
ClangImporterOptions &ClangImporterOpts, const CASOptions &CASOpts,
|
||||
DiagnosticEngine &Diags)
|
||||
: LangOpts(LangOpts), SearchPathOpts(SearchPathOpts),
|
||||
ClangImporterOpts(ClangImporterOpts), CASOpts(CASOpts),
|
||||
Diags(Diags) {}
|
||||
|
||||
ClangInvocationFileMappingContext(const swift::ASTContext &Ctx);
|
||||
};
|
||||
|
||||
/// On Linux, some platform libraries (glibc, libstdc++) are not modularized.
|
||||
/// We inject modulemaps for those libraries into their include directories
|
||||
/// to allow using them from Swift.
|
||||
@@ -885,7 +906,7 @@ struct ClangInvocationFileMapping {
|
||||
/// `suppressDiagnostic` prevents us from emitting warning messages when we
|
||||
/// are unable to find headers.
|
||||
ClangInvocationFileMapping getClangInvocationFileMapping(
|
||||
const ASTContext &ctx,
|
||||
const ClangInvocationFileMappingContext &ctx,
|
||||
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> vfs = nullptr,
|
||||
bool suppressDiagnostic = false);
|
||||
|
||||
@@ -893,7 +914,7 @@ ClangInvocationFileMapping getClangInvocationFileMapping(
|
||||
/// primarily to inject modulemaps on platforms with non-modularized
|
||||
/// platform libraries.
|
||||
ClangInvocationFileMapping applyClangInvocationMapping(
|
||||
const ASTContext &ctx,
|
||||
const ClangInvocationFileMappingContext &ctx,
|
||||
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> baseVFS,
|
||||
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> &fileSystem,
|
||||
bool suppressDiagnostics = false);
|
||||
|
||||
@@ -202,7 +202,8 @@ ClangImporter::createClangArgs(const ClangImporterOptions &ClangImporterOpts,
|
||||
}
|
||||
|
||||
static SmallVector<std::pair<std::string, std::string>, 2>
|
||||
getLibcFileMapping(const ASTContext &ctx, StringRef modulemapFileName,
|
||||
getLibcFileMapping(const ClangInvocationFileMappingContext &ctx,
|
||||
StringRef modulemapFileName,
|
||||
std::optional<ArrayRef<StringRef>> maybeHeaderFileNames,
|
||||
const llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> &vfs,
|
||||
bool suppressDiagnostic) {
|
||||
@@ -269,7 +270,8 @@ getLibcFileMapping(const ASTContext &ctx, StringRef modulemapFileName,
|
||||
}
|
||||
|
||||
static void getLibStdCxxFileMapping(
|
||||
ClangInvocationFileMapping &fileMapping, const ASTContext &ctx,
|
||||
ClangInvocationFileMapping &fileMapping,
|
||||
const ClangInvocationFileMappingContext &ctx,
|
||||
const llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> &vfs,
|
||||
bool suppressDiagnostic) {
|
||||
assert(ctx.LangOpts.EnableCXXInterop &&
|
||||
@@ -475,7 +477,8 @@ GetPlatformAuxiliaryFile(StringRef Platform, StringRef File,
|
||||
}
|
||||
|
||||
void GetWindowsFileMappings(
|
||||
ClangInvocationFileMapping &fileMapping, const ASTContext &Context,
|
||||
ClangInvocationFileMapping &fileMapping,
|
||||
const ClangInvocationFileMappingContext &Context,
|
||||
const llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> &driverVFS,
|
||||
bool &requiresBuiltinHeadersInSystemModules) {
|
||||
const llvm::Triple &Triple = Context.LangOpts.Target;
|
||||
@@ -615,8 +618,14 @@ void GetWindowsFileMappings(
|
||||
}
|
||||
} // namespace
|
||||
|
||||
ClangInvocationFileMappingContext::ClangInvocationFileMappingContext(
|
||||
const swift::ASTContext &Ctx)
|
||||
: ClangInvocationFileMappingContext(Ctx.LangOpts, Ctx.SearchPathOpts,
|
||||
Ctx.ClangImporterOpts, Ctx.CASOpts, Ctx.Diags) {}
|
||||
|
||||
ClangInvocationFileMapping swift::getClangInvocationFileMapping(
|
||||
const ASTContext &ctx, llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> vfs,
|
||||
const ClangInvocationFileMappingContext &ctx,
|
||||
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> vfs,
|
||||
bool suppressDiagnostic) {
|
||||
ClangInvocationFileMapping result;
|
||||
if (!vfs)
|
||||
@@ -687,10 +696,11 @@ ClangInvocationFileMapping swift::getClangInvocationFileMapping(
|
||||
return result;
|
||||
}
|
||||
|
||||
ClangInvocationFileMapping swift::applyClangInvocationMapping(const ASTContext &ctx,
|
||||
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> baseVFS,
|
||||
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> &fileSystem,
|
||||
bool suppressDiagnostics) {
|
||||
ClangInvocationFileMapping swift::applyClangInvocationMapping(
|
||||
const ClangInvocationFileMappingContext &ctx,
|
||||
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> baseVFS,
|
||||
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> &fileSystem,
|
||||
bool suppressDiagnostics) {
|
||||
if (ctx.CASOpts.HasImmutableFileSystem)
|
||||
return ClangInvocationFileMapping();
|
||||
|
||||
@@ -719,13 +729,9 @@ ClangInvocationFileMapping swift::applyClangInvocationMapping(const ASTContext &
|
||||
<< "' with the following contents:\n";
|
||||
llvm::errs() << file.second << "\n";
|
||||
}
|
||||
auto contents = ctx.Allocate<char>(file.second.size() + 1);
|
||||
std::copy(file.second.begin(), file.second.end(), contents.begin());
|
||||
// null terminate the buffer.
|
||||
contents[contents.size() - 1] = '\0';
|
||||
// Note MemoryBuffer is guaranteeed to be null-terminated.
|
||||
overridenVFS->addFile(file.first, 0,
|
||||
llvm::MemoryBuffer::getMemBuffer(StringRef(
|
||||
contents.begin(), contents.size() - 1)));
|
||||
llvm::MemoryBuffer::getMemBufferCopy(file.second));
|
||||
}
|
||||
llvm::IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem> overlayVFS =
|
||||
new llvm::vfs::OverlayFileSystem(fileSystem);
|
||||
|
||||
@@ -1992,6 +1992,14 @@ ModuleDependencyInfo ModuleDependencyScanner::bridgeClangModuleDependency(
|
||||
}
|
||||
}
|
||||
|
||||
// Pass the -sdk flag to make the system header VFS overlay finable
|
||||
// for the -direct-clang-cc1-module-build emit-pcm command on Windows.
|
||||
StringRef SDKPath = ScanASTContext.SearchPathOpts.getSDKPath();
|
||||
if (!SDKPath.empty()) {
|
||||
swiftArgs.push_back("-sdk");
|
||||
swiftArgs.push_back(SDKPath.str());
|
||||
}
|
||||
|
||||
// Add args reported by the scanner.
|
||||
auto clangArgs = invocation.getCC1CommandLine();
|
||||
llvm::for_each(clangArgs, addClangArg);
|
||||
|
||||
@@ -711,6 +711,25 @@ bool CompilerInstance::setUpVirtualFileSystemOverlays() {
|
||||
new llvm::vfs::OverlayFileSystem(MemFS);
|
||||
OverlayVFS->pushOverlay(SourceMgr.getFileSystem());
|
||||
SourceMgr.setFileSystem(std::move(OverlayVFS));
|
||||
} else {
|
||||
// For non-caching -direct-clang-cc1-module-build emit-pcm build,
|
||||
// setup the clang VFS so it can find system modulemap files
|
||||
// (like vcruntime.modulemap) as an input file.
|
||||
if (Invocation.getClangImporterOptions().DirectClangCC1ModuleBuild &&
|
||||
Invocation.getFrontendOptions().RequestedAction ==
|
||||
FrontendOptions::ActionType::EmitPCM) {
|
||||
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS =
|
||||
SourceMgr.getFileSystem();
|
||||
ClangInvocationFileMappingContext Context(
|
||||
Invocation.getLangOptions(), Invocation.getSearchPathOptions(),
|
||||
Invocation.getClangImporterOptions(), Invocation.getCASOptions(),
|
||||
Diagnostics);
|
||||
ClangInvocationFileMapping FileMapping = applyClangInvocationMapping(
|
||||
Context, nullptr, VFS, /*suppressDiagnostic=*/false);
|
||||
if (!FileMapping.redirectedFiles.empty()) {
|
||||
SourceMgr.setFileSystem(std::move(VFS));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto ExpectedOverlay =
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
module SAL [system] {
|
||||
header "sal.h"
|
||||
export *
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
// REQUIRES: OS=windows-msvc
|
||||
|
||||
// Test that the -direct-clang-cc1-module-build is able to create a module from the VC runtime with an overlaid modulemap file
|
||||
|
||||
// RUN: %empty-directory(%t)
|
||||
// RUN: split-file %s %t
|
||||
|
||||
// RUN: %swift_frontend_plain -target %target-triple -module-cache-path %t/clang-module-cache -scan-dependencies -module-name Test -sdk %S/Inputs/WinSDK %t/Test.swift -o %t/deps.json
|
||||
// RUN: %{python} %S/../CAS/Inputs/BuildCommandExtractor.py %t/deps.json clang:SAL > %t/SAL.cmd
|
||||
// RUN: %swift_frontend_plain @%t/SAL.cmd
|
||||
|
||||
//--- Test.swift
|
||||
import SAL
|
||||
Reference in New Issue
Block a user