Author: Joseph Huber
Date: 2026-06-09T08:35:07-05:00
New Revision: ee39c604feff48ce4b5396f8a7c51da86768479b

URL: 
https://github.com/llvm/llvm-project/commit/ee39c604feff48ce4b5396f8a7c51da86768479b
DIFF: 
https://github.com/llvm/llvm-project/commit/ee39c604feff48ce4b5396f8a7c51da86768479b.diff

LOG: [Clang] Support multilibs on Windows (#200212)

Summary:
This was pushed to a follow-up, and I think the previous has lingered
long enough to expand this to Windows. the per-target runtime directory
this uses is default-off, but nothing stops us from just providing this.
The interest in this is for ROCm builds on Windows to be able to provide
asan / debug builds the same way on Linux.

Added: 
    clang/test/Driver/Inputs/multilib_msvc_tree/bin/.keep
    
clang/test/Driver/Inputs/multilib_msvc_tree/include/x86_64-pc-windows-msvc/.keep
    
clang/test/Driver/Inputs/multilib_msvc_tree/include/x86_64-pc-windows-msvc/debug/.keep
    
clang/test/Driver/Inputs/multilib_msvc_tree/include/x86_64-pc-windows-msvc/noexcept/.keep
    
clang/test/Driver/Inputs/multilib_msvc_tree/include/x86_64-pc-windows-msvc/release/.keep
    clang/test/Driver/msvc-multilib.yaml

Modified: 
    clang/docs/Multilib.rst
    clang/docs/ReleaseNotes.rst
    clang/lib/Driver/ToolChains/MSVC.cpp
    clang/test/Driver/print-multi-selection-flags.c

Removed: 
    


################################################################################
diff  --git a/clang/docs/Multilib.rst b/clang/docs/Multilib.rst
index d36b73dce68cd..06c43e720ab87 100644
--- a/clang/docs/Multilib.rst
+++ b/clang/docs/Multilib.rst
@@ -48,7 +48,8 @@ EXPERIMENTAL Multilib via configuration file
 ============================================
 
 Some Clang toolchains support loading multilib configuration from a
-``multilib.yaml`` configuration file.
+``multilib.yaml`` configuration file. This is currently supported on Linux,
+Windows, and Baremetal toolchains.
 
 A ``multilib.yaml`` configuration file specifies which multilib variants are
 available, their relative location, what compilation options were used to build

diff  --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 8a00b235860e4..a569572af43ca 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -325,6 +325,9 @@ Non-comprehensive list of changes in this release
 
 - Updated support for Unicode from 15.1 to 18.0.
 
+- Linux and Windows toolchains now support Clang multilibs using
+  ``-fmultilib-flag=``.
+
 - The SafeStack builtins ``__builtin___get_unsafe_stack_ptr``,
   ``__builtin___get_unsafe_stack_bottom``, 
``__builtin___get_unsafe_stack_top``,
   and ``__builtin___get_unsafe_stack_start`` are now deprecated. Use the

diff  --git a/clang/lib/Driver/ToolChains/MSVC.cpp 
b/clang/lib/Driver/ToolChains/MSVC.cpp
index 8141f9f132421..9439e30da765c 100644
--- a/clang/lib/Driver/ToolChains/MSVC.cpp
+++ b/clang/lib/Driver/ToolChains/MSVC.cpp
@@ -205,6 +205,10 @@ void visualstudio::Linker::ConstructJob(Compilation &C, 
const JobAction &JA,
     if (TC.getVFS().exists(LibPath))
       CmdArgs.push_back(Args.MakeArgString("-libpath:" + LibPath));
   }
+  for (const auto &LibPath : TC.getFilePaths()) {
+    if (LibPath.length() > 0)
+      CmdArgs.push_back(Args.MakeArgString("-libpath:" + LibPath));
+  }
   auto CRTPath = TC.getCompilerRTPath();
   if (TC.getVFS().exists(CRTPath))
     CmdArgs.push_back(Args.MakeArgString("-libpath:" + CRTPath));
@@ -523,6 +527,8 @@ MSVCToolChain::MSVCToolChain(const Driver &D, const 
llvm::Triple &Triple,
       llvm::findVCToolChainViaSetupConfig(getVFS(), VCToolsVersion,
                                           VCToolChainPath, VSLayout) ||
       llvm::findVCToolChainViaRegistry(VCToolChainPath, VSLayout);
+
+  loadMultilibsFromYAML(Args, D);
 }
 
 Tool *MSVCToolChain::buildLinker() const {
@@ -774,6 +780,18 @@ void MSVCToolChain::AddClangSystemIncludeArgs(const 
ArgList &DriverArgs,
   if (DriverArgs.hasArg(options::OPT_nostdlibinc))
     return;
 
+  // Add multilib variant include paths in priority order.
+  for (const Multilib &M : getOrderedMultilibs()) {
+    if (M.isDefault())
+      continue;
+    if (std::optional<std::string> StdlibIncDir = getStdlibIncludePath()) {
+      SmallString<128> Dir(*StdlibIncDir);
+      llvm::sys::path::append(Dir, M.includeSuffix());
+      if (getDriver().getVFS().exists(Dir))
+        addSystemInclude(DriverArgs, CC1Args, Dir);
+    }
+  }
+
   // Honor %INCLUDE% and %EXTERNAL_INCLUDE%. It should have essential search
   // paths set by vcvarsall.bat. Skip if the user expressly set any of the
   // Windows SDK or VC Tools options.

diff  --git a/clang/test/Driver/Inputs/multilib_msvc_tree/bin/.keep 
b/clang/test/Driver/Inputs/multilib_msvc_tree/bin/.keep
new file mode 100644
index 0000000000000..e69de29bb2d1d

diff  --git 
a/clang/test/Driver/Inputs/multilib_msvc_tree/include/x86_64-pc-windows-msvc/.keep
 
b/clang/test/Driver/Inputs/multilib_msvc_tree/include/x86_64-pc-windows-msvc/.keep
new file mode 100644
index 0000000000000..e69de29bb2d1d

diff  --git 
a/clang/test/Driver/Inputs/multilib_msvc_tree/include/x86_64-pc-windows-msvc/debug/.keep
 
b/clang/test/Driver/Inputs/multilib_msvc_tree/include/x86_64-pc-windows-msvc/debug/.keep
new file mode 100644
index 0000000000000..e69de29bb2d1d

diff  --git 
a/clang/test/Driver/Inputs/multilib_msvc_tree/include/x86_64-pc-windows-msvc/noexcept/.keep
 
b/clang/test/Driver/Inputs/multilib_msvc_tree/include/x86_64-pc-windows-msvc/noexcept/.keep
new file mode 100644
index 0000000000000..e69de29bb2d1d

diff  --git 
a/clang/test/Driver/Inputs/multilib_msvc_tree/include/x86_64-pc-windows-msvc/release/.keep
 
b/clang/test/Driver/Inputs/multilib_msvc_tree/include/x86_64-pc-windows-msvc/release/.keep
new file mode 100644
index 0000000000000..e69de29bb2d1d

diff  --git a/clang/test/Driver/msvc-multilib.yaml 
b/clang/test/Driver/msvc-multilib.yaml
new file mode 100644
index 0000000000000..b650393003fd0
--- /dev/null
+++ b/clang/test/Driver/msvc-multilib.yaml
@@ -0,0 +1,87 @@
+# Basic selection where -fmultilib-flag=debug selects the debug variant.
+# RUN: %clang --multi-lib-config=%s -no-canonical-prefixes -x c %s -### -o 
/dev/null 2>&1 \
+# RUN:     --target=x86_64-pc-windows-msvc -fmultilib-flag=debug \
+# RUN:     -ccc-install-dir %S/Inputs/multilib_msvc_tree/bin \
+# RUN:   | FileCheck --check-prefix=CHECK-DEBUG %s
+# CHECK-DEBUG:      "-cc1" "-triple" "x86_64-pc-windows-msvc
+# CHECK-DEBUG:      "-internal-isystem" 
"{{[^"]*}}{{[/\\]}}x86_64-pc-windows-msvc/debug"
+# CHECK-DEBUG:      "-libpath:{{[^"]*}}/debug"
+
+# Default behavior where no variant path is prepended.
+# RUN: %clang --multi-lib-config=%s -no-canonical-prefixes -x c %s -### -o 
/dev/null 2>&1 \
+# RUN:     --target=x86_64-pc-windows-msvc \
+# RUN:     -ccc-install-dir %S/Inputs/multilib_msvc_tree/bin \
+# RUN:   | FileCheck --check-prefix=CHECK-DEFAULT %s
+# CHECK-DEFAULT-NOT: "-libpath:{{[^"]*}}/debug"
+# CHECK-DEFAULT-NOT: "-libpath:{{[^"]*}}/release"
+# CHECK-DEFAULT-NOT: "-libpath:{{[^"]*}}/noexcept"
+# CHECK-DEFAULT-NOT: "-internal-isystem" 
"{{[^"]*}}{{[/\\]}}x86_64-pc-windows-msvc/debug"
+# CHECK-DEFAULT-NOT: "-internal-isystem" 
"{{[^"]*}}{{[/\\]}}x86_64-pc-windows-msvc/release"
+# CHECK-DEFAULT-NOT: "-internal-isystem" 
"{{[^"]*}}{{[/\\]}}x86_64-pc-windows-msvc/noexcept"
+
+# Multiple matches stacking on top of each-other.
+# RUN: %clang --multi-lib-config=%s -no-canonical-prefixes -x c %s -### -o 
/dev/null 2>&1 \
+# RUN:     --target=x86_64-pc-windows-msvc -fmultilib-flag=debug 
-fno-exceptions \
+# RUN:     -ccc-install-dir %S/Inputs/multilib_msvc_tree/bin \
+# RUN:   | FileCheck --check-prefix=CHECK-LAYERED %s
+# CHECK-LAYERED:      "-internal-isystem" 
"{{[^"]*}}{{[/\\]}}x86_64-pc-windows-msvc/noexcept"
+# CHECK-LAYERED-SAME: "-internal-isystem" 
"{{[^"]*}}{{[/\\]}}x86_64-pc-windows-msvc/debug"
+# CHECK-LAYERED:      "-libpath:{{[^"]*}}/noexcept"
+# CHECK-LAYERED-SAME: "-libpath:{{[^"]*}}/debug"
+
+# Lists selected variant directories.
+# RUN: %clang --multi-lib-config=%s -no-canonical-prefixes 
-print-multi-directory 2>&1 \
+# RUN:     --target=x86_64-pc-windows-msvc -fmultilib-flag=debug \
+# RUN:   | FileCheck --check-prefix=CHECK-PRINT-DIR %s
+# CHECK-PRINT-DIR: debug
+
+# Lists all non-default variants with flags.
+# RUN: %clang --multi-lib-config=%s -no-canonical-prefixes -print-multi-lib 
2>&1 \
+# RUN:     --target=x86_64-pc-windows-msvc \
+# RUN:   | FileCheck --check-prefix=CHECK-PRINT-LIB %s
+# CHECK-PRINT-LIB: debug;@fmultilib-flag=debug
+# CHECK-PRINT-LIB: release;@fmultilib-flag=release
+# CHECK-PRINT-LIB: noexcept;@fno-exceptions
+
+# Error emitted when custom flag value is invalid.
+# RUN: not %clang --multi-lib-config=%s -no-canonical-prefixes -x c %s -### -o 
/dev/null 2>&1 \
+# RUN:     --target=x86_64-pc-windows-msvc -fmultilib-flag=nonexistent \
+# RUN:   | FileCheck --check-prefix=CHECK-NOMATCH %s
+# CHECK-NOMATCH: error: unsupported option '-fmultilib-flag=nonexistent'
+
+# Check exclusivity so that only one of debug/release selected.
+# RUN: %clang --multi-lib-config=%s -no-canonical-prefixes 
-print-multi-directory 2>&1 \
+# RUN:     --target=x86_64-pc-windows-msvc -fmultilib-flag=release \
+# RUN:   | FileCheck --check-prefix=CHECK-EXCLUSIVE %s
+# CHECK-EXCLUSIVE:     release
+# CHECK-EXCLUSIVE-NOT: debug
+
+---
+MultilibVersion: 1.0
+
+Groups:
+- Name: build-type
+  Type: Exclusive
+
+Variants:
+- Dir: .
+  Flags: []
+- Dir: debug
+  Flags: [-fmultilib-flag=debug]
+  Group: build-type
+- Dir: release
+  Flags: [-fmultilib-flag=release]
+  Group: build-type
+- Dir: noexcept
+  Flags: [-fno-exceptions]
+
+Mappings: []
+
+Flags:
+- Name: build-type
+  Values:
+  - Name: none
+  - Name: debug
+  - Name: release
+  Default: none
+...

diff  --git a/clang/test/Driver/print-multi-selection-flags.c 
b/clang/test/Driver/print-multi-selection-flags.c
index 64efddad878c5..ba7b325892f9c 100644
--- a/clang/test/Driver/print-multi-selection-flags.c
+++ b/clang/test/Driver/print-multi-selection-flags.c
@@ -1,6 +1,9 @@
 // RUN: %clang -multi-lib-config=%S/Inputs/multilib/empty.yaml 
-print-multi-flags-experimental --target=aarch64-linux -fc++-abi=itanium 
-fsanitize=address | FileCheck --check-prefix=CHECK-LINUX %s
 // CHECK-LINUX: --target=aarch64-unknown-linux
 
+// RUN: %clang -multi-lib-config=%S/Inputs/multilib/empty.yaml 
-print-multi-flags-experimental --target=x86_64-pc-windows-msvc 
-fc++-abi=itanium -fsanitize=address | FileCheck --check-prefix=CHECK-WINDOWS %s
+// CHECK-WINDOWS: --target=x86_64-pc-windows-msvc
+
 // RUN: %clang -multi-lib-config=%S/Inputs/multilib/empty.yaml 
-print-multi-flags-experimental --target=aarch64-fuchsia -fsanitize=hwaddress | 
FileCheck --check-prefix=CHECK-FUCHSIA %s
 // CHECK-FUCHSIA: --target=aarch64-unknown-fuchsia
 


        
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to