Skip to content

Use the Windows SDK arguments over the environment #144805

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged

Conversation

Steelskin
Copy link
Contributor

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.

@llvmbot llvmbot added clang Clang issues not falling into any other category clang:driver 'clang' and 'clang++' user-facing binaries. Not 'clang-cl' labels Jun 18, 2025
@llvmbot
Copy link
Member

llvmbot commented Jun 18, 2025

@llvm/pr-subscribers-lld
@llvm/pr-subscribers-lld-coff
@llvm/pr-subscribers-platform-windows
@llvm/pr-subscribers-clang-driver

@llvm/pr-subscribers-clang

Author: Fabrice de Gans (Steelskin)

Changes

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.


Full diff: https://github.com/llvm/llvm-project/pull/144805.diff

1 Files Affected:

  • (modified) clang/lib/Driver/ToolChains/MSVC.cpp (+24-15)
diff --git a/clang/lib/Driver/ToolChains/MSVC.cpp b/clang/lib/Driver/ToolChains/MSVC.cpp
index 1e244865b2117..632cc3a0a8b9b 100644
--- a/clang/lib/Driver/ToolChains/MSVC.cpp
+++ b/clang/lib/Driver/ToolChains/MSVC.cpp
@@ -94,10 +94,14 @@ void visualstudio::Linker::ConstructJob(Compilation &C, const JobAction &JA,
   // If the VC environment hasn't been configured (perhaps because the user
   // did not run vcvarsall), try to build a consistent link environment.  If
   // the environment variable is set however, assume the user knows what
-  // they're doing. If the user passes /vctoolsdir or /winsdkdir, trust that
-  // over env vars.
-  if (const Arg *A = Args.getLastArg(options::OPT__SLASH_diasdkdir,
-                                     options::OPT__SLASH_winsysroot)) {
+  // they're doing. If the user passes /vctoolsdir or /winsdkdir or any of the
+  // other Windows SDK options, trust that over env vars.
+  const Arg *A = Args.getLastArg(options::OPT__SLASH_vctoolsdir,
+                                 options::OPT__SLASH_vctoolsversion,
+                                 options::OPT__SLASH_winsysroot,
+                                 options::OPT__SLASH_winsdkdir,
+                                 options::OPT__SLASH_winsdkversion);
+  if (A) {
     // cl.exe doesn't find the DIA SDK automatically, so this too requires
     // explicit flags and doesn't automatically look in "DIA SDK" relative
     // to the path we found for VCToolChainPath.
@@ -110,9 +114,7 @@ void visualstudio::Linker::ConstructJob(Compilation &C, const JobAction &JA,
                             llvm::archToLegacyVCArch(TC.getArch()));
     CmdArgs.push_back(Args.MakeArgString(Twine("-libpath:") + DIAPath));
   }
-  if (!llvm::sys::Process::GetEnv("LIB") ||
-      Args.getLastArg(options::OPT__SLASH_vctoolsdir,
-                      options::OPT__SLASH_winsysroot)) {
+  if (!llvm::sys::Process::GetEnv("LIB") || A) {
     CmdArgs.push_back(Args.MakeArgString(
         Twine("-libpath:") +
         TC.getSubDirectoryPath(llvm::SubDirectoryType::Lib)));
@@ -120,9 +122,7 @@ void visualstudio::Linker::ConstructJob(Compilation &C, const JobAction &JA,
         Twine("-libpath:") +
         TC.getSubDirectoryPath(llvm::SubDirectoryType::Lib, "atlmfc")));
   }
-  if (!llvm::sys::Process::GetEnv("LIB") ||
-      Args.getLastArg(options::OPT__SLASH_winsdkdir,
-                      options::OPT__SLASH_winsysroot)) {
+  if (!llvm::sys::Process::GetEnv("LIB") || A) {
     if (TC.useUniversalCRT()) {
       std::string UniversalCRTLibPath;
       if (TC.getUniversalCRTLibraryPath(Args, UniversalCRTLibPath))
@@ -677,9 +677,18 @@ void MSVCToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
     AddSystemIncludesFromEnv(Var);
   }
 
+  // Check if the user has explicitly set a vctoolsdir or any of the
+  // Windows SDK options. If so, we assume the user knows what they're doing
+  // and don't try to find the include directories automatically.
+  // If not, we try to find the include directories automatically.
+  const Arg *A = DriverArgs.getLastArg(options::OPT__SLASH_vctoolsdir,
+                                       options::OPT__SLASH_vctoolsversion,
+                                       options::OPT__SLASH_winsysroot,
+                                       options::OPT__SLASH_winsdkdir,
+                                       options::OPT__SLASH_winsdkversion);
+
   // Add DIA SDK include if requested.
-  if (const Arg *A = DriverArgs.getLastArg(options::OPT__SLASH_diasdkdir,
-                                           options::OPT__SLASH_winsysroot)) {
+  if (A) {
     // cl.exe doesn't find the DIA SDK automatically, so this too requires
     // explicit flags and doesn't automatically look in "DIA SDK" relative
     // to the path we found for VCToolChainPath.
@@ -694,9 +703,9 @@ 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 options.
+  if (!A) {
     bool Found = AddSystemIncludesFromEnv("INCLUDE");
     Found |= AddSystemIncludesFromEnv("EXTERNAL_INCLUDE");
     if (Found)

Copy link

github-actions bot commented Jun 18, 2025

✅ With the latest revision this PR passed the C/C++ code formatter.

@compnerd
Copy link
Member

We should add a test for this behaviour like we have for the other options.

@Steelskin Steelskin force-pushed the fabrice/no-include-for-win-sdk-version branch from c35dcb3 to 5b875ae Compare June 19, 2025 00:56
@Steelskin Steelskin force-pushed the fabrice/no-include-for-win-sdk-version branch from 5b875ae to 65576f1 Compare June 19, 2025 03:23
@dpaoliello
Copy link
Contributor

Just to confirm, does this make clang-cl line up with cl's behavior?

@compnerd
Copy link
Member

Just to confirm, does this make clang-cl line up with cl's behavior?

I suspect not; these options are clang-cl specific.

@Steelskin
Copy link
Contributor Author

Steelskin commented Jun 23, 2025

Just to confirm, does this make clang-cl line up with cl's behavior?

As @compnerd said, this is clang-cl specific. None of these options exist in cl.exe.
I am looking at the test failure on Linux but I believe this is unrelated, I'll rebase and re-run.

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.
@Steelskin Steelskin force-pushed the fabrice/no-include-for-win-sdk-version branch from 65576f1 to 6c9e043 Compare June 23, 2025 15:14
Copy link
Member

@compnerd compnerd left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, this looks pretty good to me now.

@compnerd compnerd merged commit 85d250c into llvm:main Jun 24, 2025
9 of 10 checks passed
DrSergei pushed a commit to DrSergei/llvm-project that referenced this pull request Jun 24, 2025
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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:driver 'clang' and 'clang++' user-facing binaries. Not 'clang-cl' clang Clang issues not falling into any other category lld:COFF lld platform:windows
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants