[clang] ee39c60 - [Clang] Support multilibs on Windows (#200212)
via cfe-commits
cfe-commits at lists.llvm.org
Tue Jun 9 06:35:11 PDT 2026
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
More information about the cfe-commits
mailing list