}
}
-llvm::ErrorOr<std::string> toolchains::MinGW::findGcc() {
+static llvm::ErrorOr<std::string> findGcc(const llvm::Triple &T) {
llvm::SmallVector<llvm::SmallString<32>, 2> Gccs;
- Gccs.emplace_back(getTriple().getArchName());
+ Gccs.emplace_back(T.getArchName());
Gccs[0] += "-w64-mingw32-gcc";
Gccs.emplace_back("mingw32-gcc");
// Please do not add "gcc" here
return make_error_code(std::errc::no_such_file_or_directory);
}
-llvm::ErrorOr<std::string> toolchains::MinGW::findClangRelativeSysroot() {
+static llvm::ErrorOr<std::string>
+findClangRelativeSysroot(const Driver &D, const llvm::Triple &T,
+ std::string &SubdirName) {
llvm::SmallVector<llvm::SmallString<32>, 2> Subdirs;
- Subdirs.emplace_back(getTriple().str());
- Subdirs.emplace_back(getTriple().getArchName());
+ Subdirs.emplace_back(T.str());
+ Subdirs.emplace_back(T.getArchName());
Subdirs[1] += "-w64-mingw32";
- StringRef ClangRoot =
- llvm::sys::path::parent_path(getDriver().getInstalledDir());
+ StringRef ClangRoot = llvm::sys::path::parent_path(D.getInstalledDir());
StringRef Sep = llvm::sys::path::get_separator();
for (StringRef CandidateSubdir : Subdirs) {
if (llvm::sys::fs::is_directory(ClangRoot + Sep + CandidateSubdir)) {
RocmInstallation(D, Triple, Args) {
getProgramPaths().push_back(getDriver().getInstalledDir());
+ // The sequence for detecting a sysroot here should be kept in sync with
+ // the testTriple function below.
if (getDriver().SysRoot.size())
Base = getDriver().SysRoot;
// Look for <clang-bin>/../<triplet>; if found, use <clang-bin>/.. as the
// base as it could still be a base for a gcc setup with libgcc.
- else if (llvm::ErrorOr<std::string> TargetSubdir = findClangRelativeSysroot())
+ else if (llvm::ErrorOr<std::string> TargetSubdir =
+ findClangRelativeSysroot(getDriver(), getTriple(), SubdirName))
Base = std::string(llvm::sys::path::parent_path(TargetSubdir.get()));
- else if (llvm::ErrorOr<std::string> GPPName = findGcc())
+ else if (llvm::ErrorOr<std::string> GPPName = findGcc(getTriple()))
Base = std::string(llvm::sys::path::parent_path(
llvm::sys::path::parent_path(GPPName.get())));
else
break;
}
}
+
+static bool testTriple(const Driver &D, const llvm::Triple &Triple,
+ const ArgList &Args) {
+ // If an explicit sysroot is set, that will be used and we shouldn't try to
+ // detect anything else.
+ std::string SubdirName;
+ if (D.SysRoot.size())
+ return true;
+ if (llvm::ErrorOr<std::string> TargetSubdir =
+ findClangRelativeSysroot(D, Triple, SubdirName))
+ return true;
+ if (llvm::ErrorOr<std::string> GPPName = findGcc(Triple))
+ return true;
+ // If we neither found a colocated sysroot or a matching gcc executable,
+ // conclude that we can't know if this is the correct spelling of the triple.
+ return false;
+}
+
+static llvm::Triple adjustTriple(const Driver &D, const llvm::Triple &Triple,
+ const ArgList &Args) {
+ // First test if the original triple can find a sysroot with the triple
+ // name.
+ if (testTriple(D, Triple, Args))
+ return Triple;
+ llvm::SmallVector<llvm::StringRef, 3> Archs;
+ // If not, test a couple other possible arch names that might be what was
+ // intended.
+ if (Triple.getArch() == llvm::Triple::x86) {
+ Archs.emplace_back("i386");
+ Archs.emplace_back("i586");
+ Archs.emplace_back("i686");
+ } else if (Triple.getArch() == llvm::Triple::arm ||
+ Triple.getArch() == llvm::Triple::thumb) {
+ Archs.emplace_back("armv7");
+ }
+ for (auto A : Archs) {
+ llvm::Triple TestTriple(Triple);
+ TestTriple.setArchName(A);
+ if (testTriple(D, TestTriple, Args))
+ return TestTriple;
+ }
+ // If none was found, just proceed with the original value.
+ return Triple;
+}
+
+void toolchains::MinGW::fixTripleArch(const Driver &D, llvm::Triple &Triple,
+ const ArgList &Args) {
+ if (Triple.getArch() == llvm::Triple::x86 ||
+ Triple.getArch() == llvm::Triple::arm ||
+ Triple.getArch() == llvm::Triple::thumb)
+ Triple = adjustTriple(D, Triple, Args);
+}
// RUN: mkdir -p %T/testroot-clang/bin
// RUN: ln -s %clang %T/testroot-clang/bin/x86_64-w64-mingw32-clang
// RUN: ln -s %S/Inputs/mingw_ubuntu_posix_tree/usr/x86_64-w64-mingw32 %T/testroot-clang/x86_64-w64-mingw32
+// RUN: ln -s %S/Inputs/mingw_arch_tree/usr/i686-w64-mingw32 %T/testroot-clang/i686-w64-mingw32
// If we find a gcc in the path with the right triplet prefix, pick that as
// the libgcc directory:
// 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
+
+
+// If the user requests a different arch via the -m32 option, which changes
+// x86_64 into i386, check that the driver notices that it can't find a
+// sysroot for i386 but there is one for i686, and uses that one.
+// (In practice, the real usecase is when using an unprefixed native clang
+// that defaults to x86_64 mingw, but it's easier to test this in cross setups
+// with symlinks, like the other tests here.)
+
+// RUN: env "PATH=%T/testroot-gcc/bin:%PATH%" %T/testroot-clang/bin/x86_64-w64-mingw32-clang --target=x86_64-w64-mingw32 -m32 -rtlib=compiler-rt -stdlib=libstdc++ --sysroot="" -c -### %s 2>&1 | FileCheck -check-prefix=CHECK_TESTROOT_CLANG_I686 %s
+// CHECK_TESTROOT_CLANG_I686: "{{[^"]+}}/testroot-clang{{/|\\\\}}i686-w64-mingw32{{/|\\\\}}include"