Author: Joseph Huber
Date: 2026-04-14T07:00:36-05:00
New Revision: 78820cb91605693b7d768be4ebc8b66181d3e9c3

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

LOG: [Clang] Enable multilib library support for Linux/Windows (#188584)

Summary:
This PR standardizes the logic used in the baremtal build to the common
toolchain interface. We then use this to handle the support in Linux and
Windows.

The multilib functionality allows us to select variant libraries based
off of a configuration file. For example, if the `multilib.yaml` file
detects `-fsanitize=address` it will automatically use the libraries
inside of `asan/` instead. These are layered so they do not necessarily
need to be complete library builds. More documentation can be found at
https://clang.llvm.org/docs/Multilib.html.

The motivation for this is so platforms like ROCm can use a more
standard way to ship debug / asan variants of libraries like OpenMP or
similar for both GPU an CPU targets.

Added: 
    clang/test/Driver/linux-multilib.yaml
    clang/test/Driver/mingw-multilib.yaml

Modified: 
    clang/include/clang/Driver/ToolChain.h
    clang/lib/Driver/ToolChain.cpp
    clang/lib/Driver/ToolChains/BareMetal.cpp
    clang/lib/Driver/ToolChains/BareMetal.h
    clang/lib/Driver/ToolChains/CommonArgs.cpp
    clang/lib/Driver/ToolChains/Gnu.cpp
    clang/lib/Driver/ToolChains/Linux.cpp
    clang/lib/Driver/ToolChains/MinGW.cpp

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/Driver/ToolChain.h 
b/clang/include/clang/Driver/ToolChain.h
index 5b3e2c3b48676..8bda212312aee 100644
--- a/clang/include/clang/Driver/ToolChain.h
+++ b/clang/include/clang/Driver/ToolChain.h
@@ -206,6 +206,22 @@ class ToolChain {
 protected:
   MultilibSet Multilibs;
   llvm::SmallVector<Multilib> SelectedMultilibs;
+  SmallVector<std::string> MultilibMacroDefines;
+
+  using OrderedMultilibs =
+      
llvm::iterator_range<llvm::SmallVector<Multilib>::const_reverse_iterator>;
+
+  /// Get selected multilibs in priority order with default fallback.
+  OrderedMultilibs getOrderedMultilibs() const;
+
+  /// Discover and load a multilib.yaml configuration.
+  bool loadMultilibsFromYAML(const llvm::opt::ArgList &Args, const Driver &D,
+                             StringRef Fallback = {});
+
+  /// Load multilib configuration from a YAML file at \p MultilibPath,
+  std::optional<std::string> findMultilibsYAML(const llvm::opt::ArgList &Args,
+                                               const Driver &D,
+                                               StringRef FallbackDir = {});
 
   ToolChain(const Driver &D, const llvm::Triple &T,
             const llvm::opt::ArgList &Args);
@@ -715,12 +731,12 @@ class ToolChain {
   /// Add warning options that need to be passed to cc1 for this target.
   virtual void addClangWarningOptions(llvm::opt::ArgStringList &CC1Args) const;
 
-  // Get the list of extra macro defines requested by the multilib
-  // configuration.
-  virtual SmallVector<std::string>
+  /// Get the list of extra macro defines requested by the multilib
+  /// configuration.
+  SmallVector<std::string>
   getMultilibMacroDefinesStr(llvm::opt::ArgList &Args) const {
-    return {};
-  };
+    return MultilibMacroDefines;
+  }
 
   // GetRuntimeLibType - Determine the runtime library type to use with the
   // given compilation arguments.

diff  --git a/clang/lib/Driver/ToolChain.cpp b/clang/lib/Driver/ToolChain.cpp
index 945037369e4ee..c6ab3cb210382 100644
--- a/clang/lib/Driver/ToolChain.cpp
+++ b/clang/lib/Driver/ToolChain.cpp
@@ -39,6 +39,7 @@
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/FileUtilities.h"
+#include "llvm/Support/MemoryBuffer.h"
 #include "llvm/Support/Path.h"
 #include "llvm/Support/Process.h"
 #include "llvm/Support/VersionTuple.h"
@@ -105,6 +106,112 @@ ToolChain::ToolChain(const Driver &D, const llvm::Triple 
&T,
     addIfExists(getFilePaths(), Path);
 }
 
+ToolChain::OrderedMultilibs ToolChain::getOrderedMultilibs() const {
+  if (!SelectedMultilibs.empty())
+    return llvm::reverse(SelectedMultilibs);
+
+  static const llvm::SmallVector<Multilib> Default = {Multilib()};
+  return llvm::reverse(Default);
+}
+
+bool ToolChain::loadMultilibsFromYAML(const llvm::opt::ArgList &Args,
+                                      const Driver &D, StringRef Fallback) {
+  std::optional<std::string> MultilibPath =
+      findMultilibsYAML(Args, D, Fallback);
+  if (!MultilibPath)
+    return false;
+  llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> MB =
+      D.getVFS().getBufferForFile(*MultilibPath);
+  if (!MB)
+    return false;
+
+  Multilib::flags_list Flags = getMultilibFlags(Args);
+  llvm::ErrorOr<MultilibSet> ErrorOrMultilibSet =
+      MultilibSet::parseYaml(*MB.get());
+  if (ErrorOrMultilibSet.getError())
+    return false;
+
+  Multilibs = std::move(ErrorOrMultilibSet.get());
+
+  SmallVector<StringRef> CustomFlagMacroDefines;
+  bool Result =
+      Multilibs.select(D, Flags, SelectedMultilibs, &CustomFlagMacroDefines);
+
+  // Custom flag macro defines are set by processCustomFlags regardless of
+  // whether variant selection succeeds.
+  MultilibMacroDefines.clear();
+  for (StringRef Define : CustomFlagMacroDefines)
+    MultilibMacroDefines.push_back(Define.str());
+
+  if (!Result) {
+    D.Diag(clang::diag::warn_drv_missing_multilib) << llvm::join(Flags, " ");
+    SmallString<0> Data;
+    raw_svector_ostream OS(Data);
+    for (const Multilib &M : Multilibs)
+      if (!M.isError())
+        OS << "\n" << llvm::join(M.flags(), " ");
+    D.Diag(clang::diag::note_drv_available_multilibs) << OS.str();
+
+    for (const Multilib &M : SelectedMultilibs)
+      if (M.isError())
+        D.Diag(clang::diag::err_drv_multilib_custom_error)
+            << M.getErrorMessage();
+
+    SelectedMultilibs.clear();
+    return false;
+  }
+
+  // Prepend variant-specific library paths. The YAML's parent directory is
+  // the base for file paths; getRuntimePath() is the base for runtime paths.
+  StringRef YAMLBase = llvm::sys::path::parent_path(*MultilibPath);
+  std::optional<std::string> RuntimeDir = getRuntimePath();
+  size_t FileInsertPos = 0;
+  size_t LibInsertPos = 0;
+  for (const Multilib &M : getOrderedMultilibs()) {
+    if (M.isDefault())
+      continue;
+    SmallString<128> FilePath(YAMLBase);
+    llvm::sys::path::append(FilePath, M.gccSuffix());
+    getFilePaths().insert(getFilePaths().begin() + FileInsertPos,
+                          std::string(FilePath));
+    ++FileInsertPos;
+    if (RuntimeDir) {
+      SmallString<128> LibPath(*RuntimeDir);
+      llvm::sys::path::append(LibPath, M.gccSuffix());
+      getLibraryPaths().insert(getLibraryPaths().begin() + LibInsertPos,
+                               std::string(LibPath));
+      ++LibInsertPos;
+    }
+  }
+
+  return true;
+}
+
+std::optional<std::string>
+ToolChain::findMultilibsYAML(const llvm::opt::ArgList &Args, const Driver &D,
+                             StringRef FallbackDir) {
+  if (Arg *A = Args.getLastArg(options::OPT_multi_lib_config)) {
+    SmallString<128> MultilibPath(A->getValue());
+    if (!D.getVFS().exists(MultilibPath)) {
+      D.Diag(clang::diag::err_drv_no_such_file) << MultilibPath.str();
+      return std::nullopt;
+    }
+    return std::string(MultilibPath);
+  }
+
+  SmallString<128> MultilibPath;
+  if (!FallbackDir.empty())
+    MultilibPath = FallbackDir;
+  else if (std::optional<std::string> StdlibDir = getStdlibPath())
+    MultilibPath = *StdlibDir;
+  else
+    return std::nullopt;
+  llvm::sys::path::append(MultilibPath, "multilib.yaml");
+  if (!D.getVFS().exists(MultilibPath))
+    return std::nullopt;
+  return std::string(MultilibPath);
+}
+
 void ToolChain::setTripleEnvironment(llvm::Triple::EnvironmentType Env) {
   Triple.setEnvironment(Env);
   if (EffectiveTriple != llvm::Triple())

diff  --git a/clang/lib/Driver/ToolChains/BareMetal.cpp 
b/clang/lib/Driver/ToolChains/BareMetal.cpp
index 90b843aaed18a..9370eb21454e3 100644
--- a/clang/lib/Driver/ToolChains/BareMetal.cpp
+++ b/clang/lib/Driver/ToolChains/BareMetal.cpp
@@ -24,8 +24,6 @@
 #include "llvm/Support/Path.h"
 #include "llvm/Support/VirtualFileSystem.h"
 
-#include <sstream>
-
 using namespace llvm::opt;
 using namespace clang;
 using namespace clang::driver;
@@ -264,89 +262,15 @@ BareMetal::BareMetal(const Driver &D, const llvm::Triple 
&Triple,
   }
 }
 
-static void
-findMultilibsFromYAML(const ToolChain &TC, const Driver &D,
-                      StringRef MultilibPath, const ArgList &Args,
-                      DetectedMultilibs &Result,
-                      SmallVector<StringRef> &CustomFlagsMacroDefines) {
-  llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> MB =
-      D.getVFS().getBufferForFile(MultilibPath);
-  if (!MB)
-    return;
-  Multilib::flags_list Flags = TC.getMultilibFlags(Args);
-  llvm::ErrorOr<MultilibSet> ErrorOrMultilibSet =
-      MultilibSet::parseYaml(*MB.get());
-  if (ErrorOrMultilibSet.getError())
-    return;
-  Result.Multilibs = ErrorOrMultilibSet.get();
-  if (Result.Multilibs.select(D, Flags, Result.SelectedMultilibs,
-                              &CustomFlagsMacroDefines))
-    return;
-  D.Diag(clang::diag::warn_drv_missing_multilib) << llvm::join(Flags, " ");
-  std::stringstream ss;
-
-  // If multilib selection didn't complete successfully, report a list
-  // of all the configurations the user could have provided.
-  for (const Multilib &Multilib : Result.Multilibs)
-    if (!Multilib.isError())
-      ss << "\n" << llvm::join(Multilib.flags(), " ");
-  D.Diag(clang::diag::note_drv_available_multilibs) << ss.str();
-
-  // Now report any custom error messages requested by the YAML. We do
-  // this after displaying the list of available multilibs, because
-  // that list is probably large, and (in interactive use) risks
-  // scrolling the useful error message off the top of the user's
-  // terminal.
-  for (const Multilib &Multilib : Result.SelectedMultilibs)
-    if (Multilib.isError())
-      D.Diag(clang::diag::err_drv_multilib_custom_error)
-          << Multilib.getErrorMessage();
-
-  // If there was an error, clear the SelectedMultilibs vector, in
-  // case it contains partial data.
-  Result.SelectedMultilibs.clear();
-}
-
-static constexpr llvm::StringLiteral MultilibFilename = "multilib.yaml";
-
-static std::optional<llvm::SmallString<128>>
-getMultilibConfigPath(const Driver &D, const llvm::Triple &Triple,
-                      const ArgList &Args) {
-  llvm::SmallString<128> MultilibPath;
-  if (Arg *ConfigFileArg = Args.getLastArg(options::OPT_multi_lib_config)) {
-    MultilibPath = ConfigFileArg->getValue();
-    if (!D.getVFS().exists(MultilibPath)) {
-      D.Diag(clang::diag::err_drv_no_such_file) << MultilibPath.str();
-      return {};
-    }
-  } else {
-    MultilibPath = computeClangRuntimesSysRoot(D, /*IncludeTriple=*/false);
-    llvm::sys::path::append(MultilibPath, MultilibFilename);
-  }
-  return MultilibPath;
-}
-
 void BareMetal::findMultilibs(const Driver &D, const llvm::Triple &Triple,
                               const ArgList &Args) {
-  DetectedMultilibs Result;
   // Look for a multilib.yaml before trying target-specific hardwired logic.
-  // If it exists, always do what it specifies.
-  std::optional<llvm::SmallString<128>> MultilibPath =
-      getMultilibConfigPath(D, Triple, Args);
-  if (!MultilibPath)
-    return;
-  if (D.getVFS().exists(*MultilibPath)) {
-    // If multilib.yaml is found, update sysroot so it doesn't use a target
-    // specific suffix
-    SysRoot = computeClangRuntimesSysRoot(D, /*IncludeTriple=*/false);
-    SmallVector<StringRef> CustomFlagMacroDefines;
-    findMultilibsFromYAML(*this, D, *MultilibPath, Args, Result,
-                          CustomFlagMacroDefines);
-    SelectedMultilibs = Result.SelectedMultilibs;
-    Multilibs = Result.Multilibs;
-    MultilibMacroDefines.append(CustomFlagMacroDefines.begin(),
-                                CustomFlagMacroDefines.end());
+  std::string FallbackDir =
+      computeClangRuntimesSysRoot(D, /*IncludeTriple=*/false);
+  if (loadMultilibsFromYAML(Args, D, FallbackDir)) {
+    SysRoot = FallbackDir;
   } else if (isRISCVBareMetal(Triple) && !detectGCCToolchainAdjacent(D)) {
+    DetectedMultilibs Result;
     if (findRISCVMultilibs(D, Triple, Args, Result)) {
       SelectedMultilibs = Result.SelectedMultilibs;
       Multilibs = Result.Multilibs;
@@ -368,16 +292,6 @@ Tool *BareMetal::buildStaticLibTool() const {
   return new tools::baremetal::StaticLibTool(*this);
 }
 
-BareMetal::OrderedMultilibs BareMetal::getOrderedMultilibs() const {
-  // Get multilibs in reverse order because they're ordered most-specific last.
-  if (!SelectedMultilibs.empty())
-    return llvm::reverse(SelectedMultilibs);
-
-  // No multilibs selected so return a single default multilib.
-  static const llvm::SmallVector<Multilib> Default = {Multilib()};
-  return llvm::reverse(Default);
-}
-
 ToolChain::CXXStdlibType BareMetal::GetDefaultCXXStdlibType() const {
   if (getTriple().isRISCV() && IsGCCInstallationValid)
     return ToolChain::CST_Libstdcxx;
@@ -756,8 +670,3 @@ SanitizerMask BareMetal::getSupportedSanitizers() const {
   }
   return Res;
 }
-
-SmallVector<std::string>
-BareMetal::getMultilibMacroDefinesStr(llvm::opt::ArgList &Args) const {
-  return MultilibMacroDefines;
-}

diff  --git a/clang/lib/Driver/ToolChains/BareMetal.h 
b/clang/lib/Driver/ToolChains/BareMetal.h
index d3d415b337a0b..57bfb73e3399b 100644
--- a/clang/lib/Driver/ToolChains/BareMetal.h
+++ b/clang/lib/Driver/ToolChains/BareMetal.h
@@ -79,19 +79,10 @@ class LLVM_LIBRARY_VISIBILITY BareMetal : public 
Generic_ELF {
   std::string getCompilerRTPath() const override;
   SanitizerMask getSupportedSanitizers() const override;
 
-  SmallVector<std::string>
-  getMultilibMacroDefinesStr(llvm::opt::ArgList &Args) const override;
-
 private:
-  using OrderedMultilibs =
-      
llvm::iterator_range<llvm::SmallVector<Multilib>::const_reverse_iterator>;
-  OrderedMultilibs getOrderedMultilibs() const;
-
   std::string SysRoot;
 
   bool IsGCCInstallationValid;
-
-  SmallVector<std::string> MultilibMacroDefines;
 };
 
 } // namespace toolchains

diff  --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp 
b/clang/lib/Driver/ToolChains/CommonArgs.cpp
index c04e2c2b5b8c5..23545bc84ae90 100644
--- a/clang/lib/Driver/ToolChains/CommonArgs.cpp
+++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp
@@ -1416,9 +1416,16 @@ void tools::addArchSpecificRPath(const ToolChain &TC, 
const ArgList &Args,
     return;
 
   SmallVector<std::string> CandidateRPaths(TC.getArchSpecificLibPaths());
-  if (const auto CandidateRPath = TC.getStdlibPath())
-    CandidateRPaths.emplace_back(*CandidateRPath);
-
+  if (const auto StdlibPath = TC.getStdlibPath()) {
+    for (const Multilib &M : llvm::reverse(TC.getSelectedMultilibs())) {
+      if (M.isDefault())
+        continue;
+      SmallString<128> P(*StdlibPath);
+      llvm::sys::path::append(P, M.gccSuffix());
+      CandidateRPaths.emplace_back(std::string(P));
+    }
+    CandidateRPaths.emplace_back(*StdlibPath);
+  }
   for (const auto &CandidateRPath : CandidateRPaths) {
     if (TC.getVFS().exists(CandidateRPath)) {
       CmdArgs.push_back("-rpath");

diff  --git a/clang/lib/Driver/ToolChains/Gnu.cpp 
b/clang/lib/Driver/ToolChains/Gnu.cpp
index d8d537ec14b89..2e7f78127a406 100644
--- a/clang/lib/Driver/ToolChains/Gnu.cpp
+++ b/clang/lib/Driver/ToolChains/Gnu.cpp
@@ -3135,22 +3135,21 @@ void Generic_GCC::AddMultilibPaths(const Driver &D,
                                    path_list &Paths) {
   // Add the multilib suffixed paths where they are available.
   if (GCCInstallation.isValid()) {
-    assert(!SelectedMultilibs.empty());
+    const Multilib &GCCMultilib = GCCInstallation.getMultilib();
     const llvm::Triple &GCCTriple = GCCInstallation.getTriple();
     const std::string &LibPath =
         std::string(GCCInstallation.getParentLibPath());
 
     // Sourcery CodeBench MIPS toolchain holds some libraries under
     // a biarch-like suffix of the GCC installation.
-    if (const auto &PathsCallback = Multilibs.filePathsCallback())
-      for (const auto &Path : PathsCallback(SelectedMultilibs.back()))
+    if (const auto &PathsCallback =
+            GCCInstallation.getMultilibs().filePathsCallback())
+      for (const auto &Path : PathsCallback(GCCMultilib))
         addPathIfExists(D, GCCInstallation.getInstallPath() + Path, Paths);
 
     // Add lib/gcc/$triple/$version, with an optional /multilib suffix.
-    addPathIfExists(D,
-                    GCCInstallation.getInstallPath() +
-                        SelectedMultilibs.back().gccSuffix(),
-                    Paths);
+    addPathIfExists(
+        D, GCCInstallation.getInstallPath() + GCCMultilib.gccSuffix(), Paths);
 
     // Add lib/gcc/$triple/$libdir
     // For GCC built with --enable-version-specific-runtime-libs.
@@ -3177,7 +3176,7 @@ void Generic_GCC::AddMultilibPaths(const Driver &D,
     // Clang diverges from GCC's behavior.
     addPathIfExists(D,
                     LibPath + "/../" + GCCTriple.str() + "/lib/../" + OSLibDir 
+
-                        SelectedMultilibs.back().osSuffix(),
+                        GCCMultilib.osSuffix(),
                     Paths);
 
     // If the GCC installation we found is inside of the sysroot, we want to
@@ -3221,7 +3220,7 @@ void Generic_GCC::AddMultilibIncludeArgs(const ArgList 
&DriverArgs,
                               Twine(LibPath) + "/../" + GCCTriple.str() +
                                   "/include");
 
-  const auto &Callback = Multilibs.includeDirsCallback();
+  const auto &Callback = GCCInstallation.getMultilibs().includeDirsCallback();
   if (Callback) {
     for (const auto &Path : Callback(GCCInstallation.getMultilib()))
       addExternCSystemIncludeIfExists(DriverArgs, CC1Args,

diff  --git a/clang/lib/Driver/ToolChains/Linux.cpp 
b/clang/lib/Driver/ToolChains/Linux.cpp
index bde99a3dac860..c331f69c0bc2e 100644
--- a/clang/lib/Driver/ToolChains/Linux.cpp
+++ b/clang/lib/Driver/ToolChains/Linux.cpp
@@ -234,6 +234,9 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, 
const ArgList &Args)
   GCCInstallation.init(Triple, Args);
   Multilibs = GCCInstallation.getMultilibs();
   SelectedMultilibs.assign({GCCInstallation.getMultilib()});
+
+  loadMultilibsFromYAML(Args, D);
+
   llvm::Triple::ArchType Arch = Triple.getArch();
   std::string SysRoot = computeSysRoot();
   ToolChain::path_list &PPaths = getProgramPaths();
@@ -763,6 +766,18 @@ void Linux::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 (D.getVFS().exists(Dir))
+        addSystemInclude(DriverArgs, CC1Args, Dir);
+    }
+  }
+
   // After the resource directory, we prioritize the standard clang include
   // directory.
   if (std::optional<std::string> Path = getStdlibIncludePath())

diff  --git a/clang/lib/Driver/ToolChains/MinGW.cpp 
b/clang/lib/Driver/ToolChains/MinGW.cpp
index 7c01d49dd778e..7f8aec6482b5f 100644
--- a/clang/lib/Driver/ToolChains/MinGW.cpp
+++ b/clang/lib/Driver/ToolChains/MinGW.cpp
@@ -559,6 +559,8 @@ toolchains::MinGW::MinGW(const Driver &D, const 
llvm::Triple &Triple,
       getDriver().SysRoot.size())
     getFilePaths().push_back(Base + "lib");
 
+  loadMultilibsFromYAML(Args, D);
+
   NativeLLVMSupport =
       Args.getLastArgValue(options::OPT_fuse_ld_EQ, D.getPreferredLinker())
           .equals_insensitive("lld");
@@ -709,6 +711,21 @@ void toolchains::MinGW::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);
+    }
+  }
+
+  if (std::optional<std::string> Path = getStdlibIncludePath())
+    addSystemInclude(DriverArgs, CC1Args, *Path);
+
   addSystemInclude(DriverArgs, CC1Args,
                    Base + SubdirName + llvm::sys::path::get_separator() +
                        "include");

diff  --git a/clang/test/Driver/linux-multilib.yaml 
b/clang/test/Driver/linux-multilib.yaml
new file mode 100644
index 0000000000000..fca4990bb7249
--- /dev/null
+++ b/clang/test/Driver/linux-multilib.yaml
@@ -0,0 +1,78 @@
+# 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-linux-gnu -fmultilib-flag=debug --sysroot= \
+# RUN:   | FileCheck --check-prefix=CHECK-DEBUG %s
+# CHECK-DEBUG:      "-cc1" "-triple" "x86_64-unknown-linux-gnu"
+# CHECK-DEBUG:      "-L{{[^"]*}}/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-linux-gnu --sysroot= \
+# RUN:   | FileCheck --check-prefix=CHECK-DEFAULT %s
+# CHECK-DEFAULT-NOT: "-L{{[^"]*}}/debug"
+# CHECK-DEFAULT-NOT: "-L{{[^"]*}}/release"
+# CHECK-DEFAULT-NOT: "-L{{[^"]*}}/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-linux-gnu -fmultilib-flag=debug -fno-exceptions 
--sysroot= \
+# RUN:   | FileCheck --check-prefix=CHECK-LAYERED %s
+# CHECK-LAYERED:      "-L{{[^"]*}}/noexcept"
+# CHECK-LAYERED-SAME: "-L{{[^"]*}}/debug"
+
+# Lists selected variant directories.
+# RUN: %clang --multi-lib-config=%s -no-canonical-prefixes 
-print-multi-directory 2>&1 \
+# RUN:     --target=x86_64-linux-gnu -fmultilib-flag=debug --sysroot= \
+# 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-linux-gnu --sysroot= \
+# 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-linux-gnu -fmultilib-flag=nonexistent --sysroot= \
+# 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-linux-gnu -fmultilib-flag=release --sysroot= \
+# 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/mingw-multilib.yaml 
b/clang/test/Driver/mingw-multilib.yaml
new file mode 100644
index 0000000000000..6ee415adfa54f
--- /dev/null
+++ b/clang/test/Driver/mingw-multilib.yaml
@@ -0,0 +1,78 @@
+# 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-w64-windows-gnu -fmultilib-flag=debug \
+# RUN:   | FileCheck --check-prefix=CHECK-DEBUG %s
+# CHECK-DEBUG:      "-cc1" "-triple" "x86_64-w64-windows-gnu"
+# CHECK-DEBUG:      "-L{{[^"]*}}/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-w64-windows-gnu \
+# RUN:   | FileCheck --check-prefix=CHECK-DEFAULT %s
+# CHECK-DEFAULT-NOT: "-L{{[^"]*}}/debug"
+# CHECK-DEFAULT-NOT: "-L{{[^"]*}}/release"
+# CHECK-DEFAULT-NOT: "-L{{[^"]*}}/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-w64-windows-gnu -fmultilib-flag=debug 
-fno-exceptions \
+# RUN:   | FileCheck --check-prefix=CHECK-LAYERED %s
+# CHECK-LAYERED:      "-L{{[^"]*}}/noexcept"
+# CHECK-LAYERED-SAME: "-L{{[^"]*}}/debug"
+
+# Lists selected variant directories.
+# RUN: %clang --multi-lib-config=%s -no-canonical-prefixes 
-print-multi-directory 2>&1 \
+# RUN:     --target=x86_64-w64-windows-gnu -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-w64-windows-gnu \
+# 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-w64-windows-gnu -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-w64-windows-gnu -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
+...


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

Reply via email to