Skip to content

Commit 97a490e

Browse files
committed
ClangImporter: inject modulemaps via the VFS
This is the second step towards removal of the content injection into the Visual Studio installation. With this the new path is enabled to create the mappings to the SDK shared content. Subsequent improvements involve the introduction of new options to the Swift driver and Swift frontend: 1. `-windows-sdk-root` 2. `-windows-sdk-version` 3. `-visualc-tools-root` 4. `-visualc-tools-version` The introduction of these options will then feed into the path selection here enabling granular control over the VCRuntime and Windows SDK by the user. Thanks to @artemcm for the very helpful discussion and help on identifying a good set of options for the driver. Thanks to @stevapple for the inspiration for this patch.
1 parent fedf86f commit 97a490e

File tree

1 file changed

+109
-3
lines changed

1 file changed

+109
-3
lines changed

lib/ClangImporter/ClangIncludePaths.cpp

Lines changed: 109 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "clang/Driver/Driver.h"
1919
#include "clang/Driver/ToolChain.h"
2020
#include "clang/Frontend/CompilerInstance.h"
21+
#include "llvm/WindowsDriver/MSVCPaths.h"
2122

2223
using namespace swift;
2324

@@ -296,14 +297,119 @@ getLibStdCxxFileMapping(ASTContext &ctx) {
296297
};
297298
}
298299

300+
namespace {
301+
std::string
302+
GetWindowsAuxiliaryFile(StringRef modulemap, const SearchPathOptions &Options) {
303+
StringRef SDKPath = Options.getSDKPath();
304+
if (!SDKPath.empty()) {
305+
llvm::SmallString<261> path{SDKPath};
306+
llvm::sys::path::append(path, "usr", "share", modulemap);
307+
if (llvm::sys::fs::exists(path))
308+
return path.str().str();
309+
}
310+
311+
if (!Options.RuntimeResourcePath.empty()) {
312+
llvm::SmallString<261> path{Options.RuntimeResourcePath};
313+
llvm::sys::path::append(path, "windows", modulemap);
314+
if (llvm::sys::fs::exists(path))
315+
return path.str().str();
316+
}
317+
318+
return "";
319+
}
320+
321+
SmallVector<std::pair<std::string, std::string>, 2>
322+
GetWindowsFileMappings(ASTContext &Context) {
323+
const llvm::Triple &Triple = Context.LangOpts.Target;
324+
SmallVector<std::pair<std::string, std::string>, 2> Mappings;
325+
std::string AuxiliaryFile;
326+
327+
if (!Triple.isWindowsMSVCEnvironment())
328+
return Mappings;
329+
330+
clang::driver::Driver Driver = createClangDriver(Context);
331+
const llvm::opt::InputArgList Args = createClangArgs(Context, Driver);
332+
const clang::driver::ToolChain &ToolChain = Driver.getToolChain(Args, Triple);
333+
llvm::vfs::FileSystem &VFS = ToolChain.getVFS();
334+
335+
struct {
336+
std::string Path;
337+
std::string IncludeVersion;
338+
std::string LibraryVersion;
339+
int MajorVersion;
340+
} WindowsSDK;
341+
if (llvm::getWindowsSDKDir(VFS, {}, {}, {},
342+
WindowsSDK.Path, WindowsSDK.MajorVersion,
343+
WindowsSDK.IncludeVersion,
344+
WindowsSDK.LibraryVersion)) {
345+
llvm::SmallString<261> WinSDKInjection{WindowsSDK.Path};
346+
llvm::sys::path::append(WinSDKInjection, "Include");
347+
if (WindowsSDK.MajorVersion > 8)
348+
llvm::sys::path::append(WinSDKInjection, WindowsSDK.IncludeVersion, "um");
349+
llvm::sys::path::append(WinSDKInjection, "module.modulemap");
350+
351+
AuxiliaryFile =
352+
GetWindowsAuxiliaryFile("winsdk.modulemap", Context.SearchPathOpts);
353+
if (!AuxiliaryFile.empty())
354+
Mappings.emplace_back(std::string(WinSDKInjection), AuxiliaryFile);
355+
}
356+
357+
struct {
358+
std::string Path;
359+
std::string Version;
360+
} UCRTSDK;
361+
if (llvm::getUniversalCRTSdkDir(VFS, {}, {}, {}, UCRTSDK.Path,
362+
UCRTSDK.Version)) {
363+
llvm::SmallString<261> UCRTInjection{UCRTSDK.Path};
364+
llvm::sys::path::append(UCRTInjection, "Include", UCRTSDK.Version, "ucrt");
365+
llvm::sys::path::append(UCRTInjection, "module.modulemap");
366+
367+
AuxiliaryFile =
368+
GetWindowsAuxiliaryFile("ucrt.modulemap", Context.SearchPathOpts);
369+
if (!AuxiliaryFile.empty())
370+
Mappings.emplace_back(std::string(UCRTInjection), AuxiliaryFile);
371+
}
372+
373+
struct {
374+
std::string Path;
375+
llvm::ToolsetLayout Layout;
376+
} VCTools;
377+
if (llvm::findVCToolChainViaCommandLine(VFS, {}, {}, {}, VCTools.Path, VCTools.Layout) ||
378+
llvm::findVCToolChainViaEnvironment(VFS, VCTools.Path, VCTools.Layout) ||
379+
llvm::findVCToolChainViaSetupConfig(VFS, VCTools.Path, VCTools.Layout) ||
380+
llvm::findVCToolChainViaRegistry(VCTools.Path, VCTools.Layout)) {
381+
llvm::SmallString<261> VCToolsInjection{VCTools.Path};
382+
llvm::sys::path::append(VCToolsInjection, "include");
383+
384+
llvm::sys::path::append(VCToolsInjection, "module.modulemap");
385+
AuxiliaryFile =
386+
GetWindowsAuxiliaryFile("vcruntime.modulemap", Context.SearchPathOpts);
387+
if (!AuxiliaryFile.empty())
388+
Mappings.emplace_back(std::string(VCToolsInjection), AuxiliaryFile);
389+
390+
llvm::sys::path::remove_filename(VCToolsInjection);
391+
llvm::sys::path::append(VCToolsInjection, "vcruntime.apinotes");
392+
AuxiliaryFile =
393+
GetWindowsAuxiliaryFile("vcruntime.apinotes", Context.SearchPathOpts);
394+
if (!AuxiliaryFile.empty())
395+
Mappings.emplace_back(std::string(VCToolsInjection), AuxiliaryFile);
396+
}
397+
398+
return Mappings;
399+
}
400+
}
401+
299402
SmallVector<std::pair<std::string, std::string>, 2>
300403
swift::getClangInvocationFileMapping(ASTContext &ctx) {
301404
SmallVector<std::pair<std::string, std::string>, 2> result;
302405

406+
// Linux Mappings
303407
result.append(getGlibcFileMapping(ctx));
304-
305-
if (ctx.LangOpts.EnableCXXInterop) {
408+
if (ctx.LangOpts.EnableCXXInterop)
306409
result.append(getLibStdCxxFileMapping(ctx));
307-
}
410+
411+
// Windows Mappings
412+
result.append(GetWindowsFileMappings(ctx));
413+
308414
return result;
309415
}

0 commit comments

Comments
 (0)