thakis updated this revision to Diff 319936. thakis edited the summary of this revision. thakis added a comment.
Seems like there are no strong opinions, so now with actual code. I went with "VC/Tools/MSVC/XXX" and "Windows Kits/10" since that seems like the obvious thing. CHANGES SINCE LAST ACTION https://reviews.llvm.org/D95534/new/ https://reviews.llvm.org/D95534 Files: clang/include/clang/Driver/Options.td clang/lib/Driver/ToolChains/MSVC.cpp
Index: clang/lib/Driver/ToolChains/MSVC.cpp =================================================================== --- clang/lib/Driver/ToolChains/MSVC.cpp +++ clang/lib/Driver/ToolChains/MSVC.cpp @@ -66,14 +66,49 @@ static bool getSystemRegistryString(const char *keyPath, const char *valueName, std::string &value, std::string *phValue); +static bool getHighestNumericTupleInDirectory(StringRef Directory, std::string &Highest) { + Highest.clear(); + llvm::VersionTuple HighestTuple; + + std::error_code EC; + for (llvm::sys::fs::directory_iterator DirIt(Directory, EC), DirEnd; + DirIt != DirEnd && !EC; DirIt.increment(EC)) { + if (!llvm::sys::fs::is_directory(DirIt->path())) + continue; + StringRef CandidateName = llvm::sys::path::filename(DirIt->path()); + llvm::VersionTuple Tuple; + if (Tuple.tryParse(CandidateName)) // tryParse() returns true on error. + continue; + if (Tuple > HighestTuple) { + HighestTuple = Tuple; + Highest = CandidateName.str(); + } + } + + return !Highest.empty(); +} + // Check command line arguments to try and find a toolchain. static bool findVCToolChainViaCommandLine(const ArgList &Args, std::string &Path, MSVCToolChain::ToolsetLayout &VSLayout) { // Don't validate the input; trust the value supplied by the user. // The primary motivation is to prevent unnecessary file and registry access. - if (Arg *A = Args.getLastArg(options::OPT__SLASH_vctoolsdir)) { - Path = A->getValue(); + if (Arg *A = Args.getLastArg(options::OPT__SLASH_vctoolsdir, + options::OPT__SLASH_winsysroot)) { + if (A->getOption().getID() == options::OPT__SLASH_winsysroot) { + llvm::SmallString<128> ToolsPath(A->getValue()); + llvm::sys::path::append(ToolsPath, "VC", "Tools", "MSVC"); + std::string VCToolsVersion; + if (Arg *A = Args.getLastArg(options::OPT__SLASH_vctoolsversion)) + VCToolsVersion = A->getValue(); + else + getHighestNumericTupleInDirectory(ToolsPath, VCToolsVersion); + llvm::sys::path::append(ToolsPath, VCToolsVersion); + Path = std::string(ToolsPath.str()); + } else { + Path = A->getValue(); + } VSLayout = MSVCToolChain::ToolsetLayout::VS2017OrNewer; return true; } @@ -345,7 +380,8 @@ // they're doing. If the user passes /vctoolsdir or /winsdkdir, trust that // over env vars. if (!llvm::sys::Process::GetEnv("LIB") || - Args.getLastArg(options::OPT__SLASH_vctoolsdir)) { + Args.getLastArg(options::OPT__SLASH_vctoolsdir, + options::OPT__SLASH_winsysroot)) { CmdArgs.push_back(Args.MakeArgString( Twine("-libpath:") + TC.getSubDirectoryPath( @@ -356,7 +392,8 @@ "atlmfc"))); } if (!llvm::sys::Process::GetEnv("LIB") || - Args.getLastArg(options::OPT__SLASH_winsdkdir)) { + Args.getLastArg(options::OPT__SLASH_winsdkdir, + options::OPT__SLASH_winsysroot)) { if (TC.useUniversalCRT()) { std::string UniversalCRTLibPath; if (TC.getUniversalCRTLibraryPath(Args, UniversalCRTLibPath)) @@ -1074,37 +1111,38 @@ std::error_code EC; llvm::SmallString<128> IncludePath(SDKPath); llvm::sys::path::append(IncludePath, "Include"); - for (llvm::sys::fs::directory_iterator DirIt(IncludePath, EC), DirEnd; - DirIt != DirEnd && !EC; DirIt.increment(EC)) { - if (!llvm::sys::fs::is_directory(DirIt->path())) - continue; - StringRef CandidateName = llvm::sys::path::filename(DirIt->path()); - // If WDK is installed, there could be subfolders like "wdf" in the - // "Include" directory. - // Allow only directories which names start with "10.". - if (!CandidateName.startswith("10.")) - continue; - if (CandidateName > SDKVersion) - SDKVersion = std::string(CandidateName); - } - - return !SDKVersion.empty(); + return getHighestNumericTupleInDirectory(IncludePath, SDKVersion); } static bool getWindowsSDKDirViaCommandLine(const ArgList &Args, std::string &Path, int &Major, std::string &Version) { - if (Arg *A = Args.getLastArg(options::OPT__SLASH_winsdkdir)) { + if (Arg *A = Args.getLastArg(options::OPT__SLASH_winsdkdir, + options::OPT__SLASH_winsysroot)) { // 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; + llvm::VersionTuple SDKVersion; + if (Arg *A = Args.getLastArg(options::OPT__SLASH_winsdkversion)) + SDKVersion.tryParse(A->getValue()); + + if (A->getOption().getID() == options::OPT__SLASH_winsysroot) { + llvm::SmallString<128> SDKPath(A->getValue()); + llvm::sys::path::append(SDKPath, "Windows Kits"); + if (!SDKVersion.empty()) { + llvm::sys::path::append(SDKPath, Twine(SDKVersion.getMajor())); + } else { + std::string SDKVersion; + if (getHighestNumericTupleInDirectory(SDKPath, SDKVersion)) + llvm::sys::path::append(SDKPath, SDKVersion); + } + Path = std::string(SDKPath.str()); + } else { + Path = A->getValue(); + } + + if (!SDKVersion.empty()) { + Major = SDKVersion.getMajor(); + Version = SDKVersion.getAsString(); } else if (getWindows10SDKVersionFromPath(Path, Version)) { Major = 10; } @@ -1326,7 +1364,8 @@ // Honor %INCLUDE%. It should know essential search paths with vcvarsall.bat. // Skip if the user expressly set a vctoolsdir - if (!DriverArgs.getLastArg(options::OPT__SLASH_vctoolsdir)) { + if (!DriverArgs.getLastArg(options::OPT__SLASH_vctoolsdir, + options::OPT__SLASH_winsysroot)) { if (llvm::Optional<std::string> cl_include_dir = llvm::sys::Process::GetEnv("INCLUDE")) { SmallVector<StringRef, 8> Dirs; Index: clang/include/clang/Driver/Options.td =================================================================== --- clang/include/clang/Driver/Options.td +++ clang/include/clang/Driver/Options.td @@ -5762,10 +5762,15 @@ 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_vctoolsversion : CLJoinedOrSeparate<"vctoolsversion">, + HelpText<"For use with /winsysroot, defaults to newest found">; 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">; + HelpText<"Full version of the Windows SDK, defaults to newest found">; +def _SLASH_winsysroot : CLJoinedOrSeparate<"winsysroot">, + HelpText<"Same as /vctoolsdir <dir>/VC/Tools/MSVC/<vctoolsversion> /winsdkdir <dir>/Windows Kits/10">, + MetaVarName<"<dir>">; def _SLASH_volatile_iso : Option<["/", "-"], "volatile:iso", KIND_FLAG>, Group<_SLASH_volatile_Group>, Flags<[CLOption, NoXarchOption]>, HelpText<"Volatile loads and stores have standard semantics">;
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits