aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNico Weber <thakis@chromium.org>2021-01-26 15:21:12 -0500
committerNico Weber <thakis@chromium.org>2021-01-27 06:37:51 -0500
commita5d85cbec58edc447b607f503ca4344e184dbb39 (patch)
tree5a0fe4effc55c18194eedf89a422462f400c1af2
parent00fcc036873164029d30819354fa923b7254cd81 (diff)
downloadllvm-a5d85cbec58edc447b607f503ca4344e184dbb39.zip
llvm-a5d85cbec58edc447b607f503ca4344e184dbb39.tar.gz
llvm-a5d85cbec58edc447b607f503ca4344e184dbb39.tar.bz2
clang-cl: Add /winsdkdir and /winsdkversion flags
These do for the Windows SDK path what D85998 did for %VCToolsInstallDir% with /vctoolsdir: Offer a way to set them with an explicit commandline switch. With this (and /vctoolsdir), it's possible to compile and link against hermetic vctools and winsdk directories with: out/gn/bin/clang-cl win.c -fuse-ld=lld \ /vctoolsdir path/to/VC/Tools/MSVC/14.26.28801 \ /winsdkdir path/to/win_sdk compared to a long list of -imsvc and /link /libpath: flags. While here: - Change the case of the "Include" folder inside the windows sdk from "include" to "Include" to match on-disk case. Since the Windows file system is case-insensitive this isn't a behavior change, it's just a bit cleaner. - Add libpath tests to the /vctoolsdir - Add a FIXME about reading env vars for win sdk and ucrt sdk if these flags aren't present, to match the VCToolsInstallDir logic We should also cache all these computed paths in the driver instead of computing them every time they're queried, but that's for a future patch. It'd also be nice to invent a /winsysroot: flag that sets both /vctoolsdir: and /winsdkdir: to some well-known subdirectory. That's for a future patch as well. Differential Revision: https://reviews.llvm.org/D95472
-rw-r--r--clang/include/clang/Driver/Options.td4
-rw-r--r--clang/lib/Driver/ToolChains/MSVC.cpp80
-rw-r--r--clang/lib/Driver/ToolChains/MSVC.h7
-rw-r--r--clang/test/Driver/cl-options.c10
4 files changed, 79 insertions, 22 deletions
diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index aa5b429..90f8026 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -5753,6 +5753,10 @@ def _SLASH_Tp : CLCompileJoinedOrSeparate<"Tp">,
def _SLASH_TP : CLCompileFlag<"TP">, HelpText<"Treat all source files as C++">;
def _SLASH_vctoolsdir : CLJoinedOrSeparate<"vctoolsdir">,
HelpText<"Path to the VCToolChain">, MetaVarName<"<dir>">;
+def _SLASH_winsdkdir : CLJoinedOrSeparate<"winsdkdir">,
+ HelpText<"Path to the Windows SDK">, MetaVarName<"<dir>">;
+def _SLASH_winsdkversion : CLJoinedOrSeparate<"winsdkversion">,
+ HelpText<"Full version of the Windows SDK">;
def _SLASH_volatile_iso : Option<["/", "-"], "volatile:iso", KIND_FLAG>,
Group<_SLASH_volatile_Group>, Flags<[CLOption, NoXarchOption]>,
HelpText<"Volatile loads and stores have standard semantics">;
diff --git a/clang/lib/Driver/ToolChains/MSVC.cpp b/clang/lib/Driver/ToolChains/MSVC.cpp
index f4b7a57e..6ab2fd6 100644
--- a/clang/lib/Driver/ToolChains/MSVC.cpp
+++ b/clang/lib/Driver/ToolChains/MSVC.cpp
@@ -81,8 +81,9 @@ findVCToolChainViaCommandLine(const ArgList &Args, std::string &Path,
}
// Check various environment variables to try and find a toolchain.
-static bool findVCToolChainViaEnvironment(std::string &Path,
- MSVCToolChain::ToolsetLayout &VSLayout) {
+static bool
+findVCToolChainViaEnvironment(std::string &Path,
+ MSVCToolChain::ToolsetLayout &VSLayout) {
// These variables are typically set by vcvarsall.bat
// when launching a developer command prompt.
if (llvm::Optional<std::string> VCToolsInstallDir =
@@ -355,13 +356,13 @@ void visualstudio::Linker::ConstructJob(Compilation &C, const JobAction &JA,
if (TC.useUniversalCRT()) {
std::string UniversalCRTLibPath;
- if (TC.getUniversalCRTLibraryPath(UniversalCRTLibPath))
+ if (TC.getUniversalCRTLibraryPath(Args, UniversalCRTLibPath))
CmdArgs.push_back(
Args.MakeArgString(Twine("-libpath:") + UniversalCRTLibPath));
}
std::string WindowsSdkLibPath;
- if (TC.getWindowsSDKLibraryPath(WindowsSdkLibPath))
+ if (TC.getWindowsSDKLibraryPath(Args, WindowsSdkLibPath))
CmdArgs.push_back(
Args.MakeArgString(std::string("-libpath:") + WindowsSdkLibPath));
}
@@ -1088,12 +1089,43 @@ static bool getWindows10SDKVersionFromPath(const std::string &SDKPath,
return !SDKVersion.empty();
}
+static bool getWindowsSDKDirViaCommandLine(const ArgList &Args,
+ std::string &Path, int &Major,
+ std::string &Version) {
+ if (Arg *A = Args.getLastArg(options::OPT__SLASH_winsdkdir)) {
+ // Don't validate the input; trust the value supplied by the user.
+ // The motivation is to prevent unnecessary file and registry access.
+ Path = A->getValue();
+ if (Arg *A = Args.getLastArg(options::OPT__SLASH_winsdkversion)) {
+ StringRef WinSdkVersion = A->getValue();
+ Version = WinSdkVersion.str();
+ if (WinSdkVersion.consumeInteger(10, Major))
+ return false;
+ if (!(WinSdkVersion.empty() || WinSdkVersion.startswith(".")))
+ return false;
+ } else if (getWindows10SDKVersionFromPath(Path, Version)) {
+ Major = 10;
+ }
+ return true;
+ }
+ return false;
+}
+
/// Get Windows SDK installation directory.
-static bool getWindowsSDKDir(std::string &Path, int &Major,
+static bool getWindowsSDKDir(const ArgList &Args, std::string &Path, int &Major,
std::string &WindowsSDKIncludeVersion,
std::string &WindowsSDKLibVersion) {
- std::string RegistrySDKVersion;
+ // Trust /winsdkdir: and /winsdkversion: if present.
+ if (getWindowsSDKDirViaCommandLine(
+ Args, Path, Major, WindowsSDKIncludeVersion)) {
+ WindowsSDKLibVersion = WindowsSDKIncludeVersion;
+ return true;
+ }
+
+ // FIXME: Try env vars (%WindowsSdkDir%, %UCRTVersion%) before going to registry.
+
// Try the Windows registry.
+ std::string RegistrySDKVersion;
if (!getSystemRegistryString(
"SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows\\$VERSION",
"InstallationFolder", Path, &RegistrySDKVersion))
@@ -1133,14 +1165,15 @@ static bool getWindowsSDKDir(std::string &Path, int &Major,
}
// Gets the library path required to link against the Windows SDK.
-bool MSVCToolChain::getWindowsSDKLibraryPath(std::string &path) const {
+bool MSVCToolChain::getWindowsSDKLibraryPath(
+ const ArgList &Args, std::string &path) const {
std::string sdkPath;
int sdkMajor = 0;
std::string windowsSDKIncludeVersion;
std::string windowsSDKLibVersion;
path.clear();
- if (!getWindowsSDKDir(sdkPath, sdkMajor, windowsSDKIncludeVersion,
+ if (!getWindowsSDKDir(Args, sdkPath, sdkMajor, windowsSDKIncludeVersion,
windowsSDKLibVersion))
return false;
@@ -1178,7 +1211,17 @@ bool MSVCToolChain::useUniversalCRT() const {
return !llvm::sys::fs::exists(TestPath);
}
-static bool getUniversalCRTSdkDir(std::string &Path, std::string &UCRTVersion) {
+static bool getUniversalCRTSdkDir(const ArgList &Args, std::string &Path,
+ std::string &UCRTVersion) {
+ // If /winsdkdir: is passed, use it as location for the UCRT too.
+ // FIXME: Should there be a dedicated /ucrtdir: to override /winsdkdir:?
+ int Major;
+ if (getWindowsSDKDirViaCommandLine(Args, Path, Major, UCRTVersion))
+ return true;
+
+ // FIXME: Try env vars (%UniversalCRTSdkDir%, %UCRTVersion%) before going to
+ // registry.
+
// vcvarsqueryregistry.bat for Visual Studio 2015 queries the registry
// for the specific key "KitsRoot10". So do we.
if (!getSystemRegistryString(
@@ -1189,12 +1232,13 @@ static bool getUniversalCRTSdkDir(std::string &Path, std::string &UCRTVersion) {
return getWindows10SDKVersionFromPath(Path, UCRTVersion);
}
-bool MSVCToolChain::getUniversalCRTLibraryPath(std::string &Path) const {
+bool MSVCToolChain::getUniversalCRTLibraryPath(const ArgList &Args,
+ std::string &Path) const {
std::string UniversalCRTSdkPath;
std::string UCRTVersion;
Path.clear();
- if (!getUniversalCRTSdkDir(UniversalCRTSdkPath, UCRTVersion))
+ if (!getUniversalCRTSdkDir(Args, UniversalCRTSdkPath, UCRTVersion))
return false;
StringRef ArchName = llvmArchToWindowsSDKArch(getArch());
@@ -1304,7 +1348,7 @@ void MSVCToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
if (useUniversalCRT()) {
std::string UniversalCRTSdkPath;
std::string UCRTVersion;
- if (getUniversalCRTSdkDir(UniversalCRTSdkPath, UCRTVersion)) {
+ if (getUniversalCRTSdkDir(DriverArgs, UniversalCRTSdkPath, UCRTVersion)) {
AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, UniversalCRTSdkPath,
"Include", UCRTVersion, "ucrt");
}
@@ -1314,23 +1358,23 @@ void MSVCToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
int major;
std::string windowsSDKIncludeVersion;
std::string windowsSDKLibVersion;
- if (getWindowsSDKDir(WindowsSDKDir, major, windowsSDKIncludeVersion,
- windowsSDKLibVersion)) {
+ if (getWindowsSDKDir(DriverArgs, WindowsSDKDir, major,
+ windowsSDKIncludeVersion, windowsSDKLibVersion)) {
if (major >= 8) {
// Note: windowsSDKIncludeVersion is empty for SDKs prior to v10.
// Anyway, llvm::sys::path::append is able to manage it.
AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir,
- "include", windowsSDKIncludeVersion,
+ "Include", windowsSDKIncludeVersion,
"shared");
AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir,
- "include", windowsSDKIncludeVersion,
+ "Include", windowsSDKIncludeVersion,
"um");
AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir,
- "include", windowsSDKIncludeVersion,
+ "Include", windowsSDKIncludeVersion,
"winrt");
} else {
AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir,
- "include");
+ "Include");
}
}
diff --git a/clang/lib/Driver/ToolChains/MSVC.h b/clang/lib/Driver/ToolChains/MSVC.h
index dba99ed..29abf0c 100644
--- a/clang/lib/Driver/ToolChains/MSVC.h
+++ b/clang/lib/Driver/ToolChains/MSVC.h
@@ -126,9 +126,10 @@ public:
void AddHIPIncludeArgs(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;
- bool getWindowsSDKLibraryPath(std::string &path) const;
- /// Check if Universal CRT should be used if available
- bool getUniversalCRTLibraryPath(std::string &path) const;
+ bool getWindowsSDKLibraryPath(
+ const llvm::opt::ArgList &Args, std::string &path) const;
+ bool getUniversalCRTLibraryPath(const llvm::opt::ArgList &Args,
+ std::string &path) const;
bool useUniversalCRT() const;
VersionTuple
computeMSVCVersion(const Driver *D,
diff --git a/clang/test/Driver/cl-options.c b/clang/test/Driver/cl-options.c
index 4b6d71e..487cbf0 100644
--- a/clang/test/Driver/cl-options.c
+++ b/clang/test/Driver/cl-options.c
@@ -696,8 +696,16 @@
// VCTOOLSDIR: "-triple" "{{[a-zA-Z0-9_-]*}}-pc-windows-msvc19.11.0"
// Validate that built-in include paths are based on the supplied path
-// RUN: %clang_cl -vctoolsdir "/fake" -### -- %s 2>&1 | FileCheck %s --check-prefix FAKEDIR
+// RUN: %clang_cl -vctoolsdir "/fake" -winsdkdir "/foo" -winsdkversion 10.0.12345.0 -### -- %s 2>&1 | FileCheck %s --check-prefix FAKEDIR
// FAKEDIR: "-internal-isystem" "/fake{{/|\\\\}}include"
// FAKEDIR: "-internal-isystem" "/fake{{/|\\\\}}atlmfc{{/|\\\\}}include"
+// FAKEDIR: "-internal-isystem" "/foo{{/|\\\\}}Include{{/|\\\\}}10.0.12345.0{{/|\\\\}}ucrt"
+// FAKEDIR: "-internal-isystem" "/foo{{/|\\\\}}Include{{/|\\\\}}10.0.12345.0{{/|\\\\}}shared"
+// FAKEDIR: "-internal-isystem" "/foo{{/|\\\\}}Include{{/|\\\\}}10.0.12345.0{{/|\\\\}}um"
+// FAKEDIR: "-internal-isystem" "/foo{{/|\\\\}}Include{{/|\\\\}}10.0.12345.0{{/|\\\\}}winrt"
+// FAKEDIR: "-libpath:/fake{{/|\\\\}}lib{{/|\\\\}}
+// FAKEDIR: "-libpath:/fake{{/|\\\\}}atlmfc{{/|\\\\}}lib{{/|\\\\}}
+// FAKEDIR: "-libpath:/foo{{/|\\\\}}Lib{{/|\\\\}}10.0.12345.0{{/|\\\\}}ucrt
+// FAKEDIR: "-libpath:/foo{{/|\\\\}}Lib{{/|\\\\}}10.0.12345.0{{/|\\\\}}um
void f() { }