Skip to content

Commit 4ca1b5e

Browse files
authored
[clang] [MinGW] Don't look for a GCC in path if the install base has a proper mingw sysroot (#76949)
This fixes uses of the MSYS2 clang64 environment compilers, if another set of GCC based compilers are available further back in PATH (which may be explicitly added, or inherited unintentionally from other software installed). (The issue in the clang64 environment can be worked around somewhat by installing *-gcc-compat packages which present aliases named <triple>-gcc within the clang64 environment as well.) This fixes msys2/MINGW-packages#11495 and msys2/MINGW-packages#19279.
1 parent 360996a commit 4ca1b5e

File tree

2 files changed

+51
-2
lines changed

2 files changed

+51
-2
lines changed

clang/lib/Driver/ToolChains/MinGW.cpp

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -471,12 +471,23 @@ findClangRelativeSysroot(const Driver &D, const llvm::Triple &LiteralTriple,
471471
return make_error_code(std::errc::no_such_file_or_directory);
472472
}
473473

474+
static bool looksLikeMinGWSysroot(const std::string &Directory) {
475+
StringRef Sep = llvm::sys::path::get_separator();
476+
if (!llvm::sys::fs::exists(Directory + Sep + "include" + Sep + "_mingw.h"))
477+
return false;
478+
if (!llvm::sys::fs::exists(Directory + Sep + "lib" + Sep + "libkernel32.a"))
479+
return false;
480+
return true;
481+
}
482+
474483
toolchains::MinGW::MinGW(const Driver &D, const llvm::Triple &Triple,
475484
const ArgList &Args)
476485
: ToolChain(D, Triple, Args), CudaInstallation(D, Triple, Args),
477486
RocmInstallation(D, Triple, Args) {
478487
getProgramPaths().push_back(getDriver().getInstalledDir());
479488

489+
std::string InstallBase =
490+
std::string(llvm::sys::path::parent_path(getDriver().getInstalledDir()));
480491
// The sequence for detecting a sysroot here should be kept in sync with
481492
// the testTriple function below.
482493
llvm::Triple LiteralTriple = getLiteralTriple(D, getTriple());
@@ -487,13 +498,17 @@ toolchains::MinGW::MinGW(const Driver &D, const llvm::Triple &Triple,
487498
else if (llvm::ErrorOr<std::string> TargetSubdir = findClangRelativeSysroot(
488499
getDriver(), LiteralTriple, getTriple(), SubdirName))
489500
Base = std::string(llvm::sys::path::parent_path(TargetSubdir.get()));
501+
// If the install base of Clang seems to have mingw sysroot files directly
502+
// in the toplevel include and lib directories, use this as base instead of
503+
// looking for a triple prefixed GCC in the path.
504+
else if (looksLikeMinGWSysroot(InstallBase))
505+
Base = InstallBase;
490506
else if (llvm::ErrorOr<std::string> GPPName =
491507
findGcc(LiteralTriple, getTriple()))
492508
Base = std::string(llvm::sys::path::parent_path(
493509
llvm::sys::path::parent_path(GPPName.get())));
494510
else
495-
Base = std::string(
496-
llvm::sys::path::parent_path(getDriver().getInstalledDir()));
511+
Base = InstallBase;
497512

498513
Base += llvm::sys::path::get_separator();
499514
findGccLibDir(LiteralTriple);
@@ -778,9 +793,15 @@ static bool testTriple(const Driver &D, const llvm::Triple &Triple,
778793
if (D.SysRoot.size())
779794
return true;
780795
llvm::Triple LiteralTriple = getLiteralTriple(D, Triple);
796+
std::string InstallBase =
797+
std::string(llvm::sys::path::parent_path(D.getInstalledDir()));
781798
if (llvm::ErrorOr<std::string> TargetSubdir =
782799
findClangRelativeSysroot(D, LiteralTriple, Triple, SubdirName))
783800
return true;
801+
// If the install base itself looks like a mingw sysroot, we'll use that
802+
// - don't use any potentially unrelated gcc to influence what triple to use.
803+
if (looksLikeMinGWSysroot(InstallBase))
804+
return false;
784805
if (llvm::ErrorOr<std::string> GPPName = findGcc(LiteralTriple, Triple))
785806
return true;
786807
// If we neither found a colocated sysroot or a matching gcc executable,

clang/test/Driver/mingw-sysroot.cpp

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,12 @@
1414
// RUN: ln -s %S/Inputs/mingw_ubuntu_posix_tree/usr/x86_64-w64-mingw32 %T/testroot-clang/x86_64-w64-mingw32
1515
// RUN: ln -s %S/Inputs/mingw_arch_tree/usr/i686-w64-mingw32 %T/testroot-clang/i686-w64-mingw32
1616

17+
// RUN: rm -rf %T/testroot-clang-native
18+
// RUN: mkdir -p %T/testroot-clang-native/bin
19+
// RUN: ln -s %clang %T/testroot-clang-native/bin/clang
20+
// RUN: mkdir -p %T/testroot-clang-native/include/_mingw.h
21+
// RUN: mkdir -p %T/testroot-clang-native/lib/libkernel32.a
22+
1723
// RUN: rm -rf %T/testroot-custom-triple
1824
// RUN: mkdir -p %T/testroot-custom-triple/bin
1925
// RUN: ln -s %clang %T/testroot-custom-triple/bin/clang
@@ -58,6 +64,28 @@
5864
// RUN: env "PATH=%T/testroot-gcc/bin:%PATH%" %T/testroot-gcc/bin/x86_64-w64-mingw32-clang -target x86_64-w64-mingw32 -rtlib=platform -stdlib=libstdc++ --sysroot="" -c -### %s 2>&1 | FileCheck -check-prefix=CHECK_TESTROOT_GCC %s
5965

6066

67+
// If we're executing clang from a directory with what looks like a mingw sysroot,
68+
// with headers in <base>/include and libs in <base>/lib, use that rather than looking
69+
// for another GCC in the path.
70+
//
71+
// Note, this test has a surprising quirk: We're testing with an install directory,
72+
// testroot-clang-native, which lacks the "x86_64-w64-mingw32" subdirectory, it only
73+
// has the include and lib subdirectories without any triple prefix.
74+
//
75+
// Since commit fd15cb935d7aae25ad62bfe06fe9f17cea585978, we avoid using the
76+
// <base>/include and <base>/lib directories when cross compiling. So technically, this
77+
// case testcase only works exactly as expected when running on x86_64 Windows, when
78+
// this target isn't considered cross compiling.
79+
//
80+
// However we do still pass the include directory <base>/x86_64-w64-mingw32/include to
81+
// the -cc1 interface, even if it is missing. Thus, this test looks for this path name,
82+
// that indicates that we did choose the right base, even if this particular directory
83+
// actually doesn't exist here.
84+
85+
// RUN: env "PATH=%T/testroot-gcc/bin:%PATH%" %T/testroot-clang-native/bin/clang -target x86_64-w64-mingw32 -rtlib=compiler-rt -stdlib=libstdc++ --sysroot="" -c -### %s 2>&1 | FileCheck -check-prefix=CHECK_TESTROOT_CLANG_NATIVE %s
86+
// CHECK_TESTROOT_CLANG_NATIVE: "{{[^"]+}}/testroot-clang-native{{/|\\\\}}x86_64-w64-mingw32{{/|\\\\}}include"
87+
88+
6189
// If the user requests a different arch via the -m32 option, which changes
6290
// x86_64 into i386, check that the driver notices that it can't find a
6391
// sysroot for i386 but there is one for i686, and uses that one.

0 commit comments

Comments
 (0)