From 484a69e78fbdd7844a29aded152357e5bf1a99b3 Mon Sep 17 00:00:00 2001 From: Fabrice de Gans Date: Wed, 18 Jun 2025 15:04:35 -0700 Subject: [PATCH] Use the Windows SDK arguments over the environment If any of the Windows SDK (and MSVC)-related argument is passed in the command line, they should take priority over the environment variables like `INCLUDE` or `LIB` set by vcvarsall from the Visual Studio Developer Environment on Windows. These changes ensure that all of the arguments related to VC Tools and the Windows SDK cause the driver to ignore the environment. --- clang/lib/Driver/ToolChains/MSVC.cpp | 19 ++++++++++++------- clang/test/Driver/cl-include.c | 5 +++++ lld/COFF/Driver.cpp | 14 ++++++++------ lld/test/COFF/winsysroot.test | 4 ++++ 4 files changed, 29 insertions(+), 13 deletions(-) diff --git a/clang/lib/Driver/ToolChains/MSVC.cpp b/clang/lib/Driver/ToolChains/MSVC.cpp index ca266e3e1d1d3..0c818c4f81fc3 100644 --- a/clang/lib/Driver/ToolChains/MSVC.cpp +++ b/clang/lib/Driver/ToolChains/MSVC.cpp @@ -110,8 +110,9 @@ void visualstudio::Linker::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back(Args.MakeArgString(Twine("-libpath:") + DIAPath)); } if (!llvm::sys::Process::GetEnv("LIB") || - Args.getLastArg(options::OPT__SLASH_vctoolsdir, - options::OPT__SLASH_winsysroot)) { + Args.hasArg(options::OPT__SLASH_vctoolsdir, + options::OPT__SLASH_vctoolsversion, + options::OPT__SLASH_winsysroot)) { CmdArgs.push_back(Args.MakeArgString( Twine("-libpath:") + TC.getSubDirectoryPath(llvm::SubDirectoryType::Lib))); @@ -120,8 +121,9 @@ void visualstudio::Linker::ConstructJob(Compilation &C, const JobAction &JA, TC.getSubDirectoryPath(llvm::SubDirectoryType::Lib, "atlmfc"))); } if (!llvm::sys::Process::GetEnv("LIB") || - Args.getLastArg(options::OPT__SLASH_winsdkdir, - options::OPT__SLASH_winsysroot)) { + Args.hasArg(options::OPT__SLASH_winsdkdir, + options::OPT__SLASH_winsdkversion, + options::OPT__SLASH_winsysroot)) { if (TC.useUniversalCRT()) { std::string UniversalCRTLibPath; if (TC.getUniversalCRTLibraryPath(Args, UniversalCRTLibPath)) @@ -686,9 +688,12 @@ void MSVCToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs, return; // Honor %INCLUDE% and %EXTERNAL_INCLUDE%. It should have essential search - // paths set by vcvarsall.bat. Skip if the user expressly set a vctoolsdir. - if (!DriverArgs.getLastArg(options::OPT__SLASH_vctoolsdir, - options::OPT__SLASH_winsysroot)) { + // paths set by vcvarsall.bat. Skip if the user expressly set any of the + // Windows SDK or VC Tools options. + if (!DriverArgs.hasArg( + options::OPT__SLASH_vctoolsdir, options::OPT__SLASH_vctoolsversion, + options::OPT__SLASH_winsysroot, options::OPT__SLASH_winsdkdir, + options::OPT__SLASH_winsdkversion)) { bool Found = AddSystemIncludesFromEnv("INCLUDE"); Found |= AddSystemIncludesFromEnv("EXTERNAL_INCLUDE"); if (Found) diff --git a/clang/test/Driver/cl-include.c b/clang/test/Driver/cl-include.c index ca9e7db1e6f07..d041698c7fd3b 100644 --- a/clang/test/Driver/cl-include.c +++ b/clang/test/Driver/cl-include.c @@ -41,3 +41,8 @@ // EXTERNAL_ENV: "-internal-isystem" "/dir1" // EXTERNAL_ENV: "-internal-isystem" "/dir2" // EXTERNAL_ENV: "-internal-isystem" "/dir3" + +// /winsdkversion suppresses %INCLUDE% and %EXTERNAL_INCLUDE% +// RUN:env INCLUDE=/my/system/inc env EXTERNAL_INCLUDE=/my/system/inc2 %clang_cl /winsdkversion 99.99.9999.9 -### -- %s 2>&1 | FileCheck %s --check-prefix=SDKVERSION +// SDKVERSION-NOT: "-internal-isystem" "/my/system/inc" +// SDKVERSION-NOT: "-internal-isystem" "/my/system/inc2" diff --git a/lld/COFF/Driver.cpp b/lld/COFF/Driver.cpp index 9e28b1c50be50..8959886d8f39d 100644 --- a/lld/COFF/Driver.cpp +++ b/lld/COFF/Driver.cpp @@ -597,11 +597,12 @@ void LinkerDriver::detectWinSysRoot(const opt::InputArgList &Args) { if (A->getOption().getID() == OPT_winsysroot) path::append(diaPath, "DIA SDK"); } - useWinSysRootLibPath = Args.hasArg(OPT_lldignoreenv) || - !Process::GetEnv("LIB") || - Args.getLastArg(OPT_vctoolsdir, OPT_winsysroot); - if (Args.hasArg(OPT_lldignoreenv) || !Process::GetEnv("LIB") || - Args.getLastArg(OPT_winsdkdir, OPT_winsysroot)) { + useWinSysRootLibPath = !Process::GetEnv("LIB") || + Args.hasArg(OPT_lldignoreenv, OPT_vctoolsdir, + OPT_vctoolsversion, OPT_winsysroot); + if (!Process::GetEnv("LIB") || + Args.hasArg(OPT_lldignoreenv, OPT_winsdkdir, OPT_winsdkversion, + OPT_winsysroot)) { std::optional WinSdkDir, WinSdkVersion; if (auto *A = Args.getLastArg(OPT_winsdkdir)) WinSdkDir = A->getValue(); @@ -1551,7 +1552,8 @@ void LinkerDriver::linkerMain(ArrayRef argsArr) { // installations when operating in mingw mode. (This also makes LLD ignore // winsysroot and vctoolsdir arguments.) detectWinSysRoot(args); - if (!args.hasArg(OPT_lldignoreenv) && !args.hasArg(OPT_winsysroot)) + if (!args.hasArg(OPT_lldignoreenv, OPT_winsysroot, OPT_vctoolsdir, + OPT_vctoolsversion, OPT_winsdkdir, OPT_winsdkversion)) addLibSearchPaths(); } else { if (args.hasArg(OPT_vctoolsdir, OPT_winsysroot)) diff --git a/lld/test/COFF/winsysroot.test b/lld/test/COFF/winsysroot.test index e29e6ca115c89..c2e9f23562d4c 100644 --- a/lld/test/COFF/winsysroot.test +++ b/lld/test/COFF/winsysroot.test @@ -58,3 +58,7 @@ LIBIGNORED_MINGW: could not open 'libstd32.a' # RUN: not lld-link -lldmingw %t.obj /defaultlib:std32 /winsysroot:%t.dir/sysroot 2>&1 | FileCheck -check-prefix=IGNORED_ARG %s IGNORED_ARG: warning: ignoring /vctoolsdir or /winsysroot flags in MinGW mode + +Check that when /winsdkversion is specified, %LIB% is ignored. +# RUN: env LIB=%t.dir/sysroot/VC/Tools/MSVC/1.1.1.1/lib/x86 not lld-link %t.obj /winsdkversion:99.99.9999.9 /defaultlib:std32 2>&1 | FileCheck -check-prefix=WINSDKVERSION %s +WINSDKVERSION: could not open 'std32.lib'