Author: Martin Storsjö Date: 2023-01-17T00:39:12+02:00 New Revision: fd15cb935d7aae25ad62bfe06fe9f17cea585978
URL: https://github.com/llvm/llvm-project/commit/fd15cb935d7aae25ad62bfe06fe9f17cea585978 DIFF: https://github.com/llvm/llvm-project/commit/fd15cb935d7aae25ad62bfe06fe9f17cea585978.diff LOG: [clang] [MinGW] Avoid adding <base>/include and <base>/lib when cross compiling The MinGW compiler driver first tries to deduce the root of the toolchain installation (either clang itself or a separate cross mingw gcc installation). On top of this root, a number of include and lib paths are added (some added unconditionally, some only if they exist): - <base>/x86_64-w64-mingw32/include - <base>/include - <base>/include/x86_64-w64-windows-gnu (Some more are also added for libstdc++ and/or libc++.) The first one is the one commonly used for MinGW targets so far. For LLVM runtimes installed with the LLVM_ENABLE_PER_TARGET_RUNTIME_DIR option, the latter two are used though (this is currently not the default, not yet at least). For cross compiling, if base is a separate dedicated directory, this is fine, but when using the sysroots of a distro-installed cross mingw toolchain, base is /usr - and having /usr/include in the include path for cross compilation is a potential source for problems; see https://github.com/llvm/llvm-project/issues/59871. If not cross compiling though, <base>/include needs to be included too. E.g. in the case of msys2, most headers are in e.g. /mingw64/include while the compiler is /mingw64/bin/clang. When cross compiling, if the sysroot has been explicitly set by the user, keep <base>/include too. (In the case of a distro provided cross gcc toolchain in /usr, the sysroot needs to be set to /usr and not /usr/x86_64-w64-mingw32 though, to be able to find libgcc files under /usr/lib/gcc/x86_64-w64-mingw32. So with such a toolchain, setting the sysroot explicitly does retain the problem.) All in all - this avoids adding /usr/include and /usr/lib to the include/lib paths when doing mingw cross compilation with a distro-provided sysroot in /usr/x86_64-w64-mingw32. Test that the include directory is omitted in the mingw-sysroot.cpp tests, when cross compiling. That test is only ever executed on non-Windows hosts, since it uses symlinks to set up fake environments with colocated compilers and header/lib directories. There aren't really any current corresponding tests for the same implicit behaviours when actually running on Windows. Differential Revision: https://reviews.llvm.org/D141206 Added: Modified: clang/lib/Driver/ToolChains/MinGW.cpp clang/test/Driver/mingw-sysroot.cpp Removed: ################################################################################ diff --git a/clang/lib/Driver/ToolChains/MinGW.cpp b/clang/lib/Driver/ToolChains/MinGW.cpp index 4d4c9b5930cfe..908484fcc0b81 100644 --- a/clang/lib/Driver/ToolChains/MinGW.cpp +++ b/clang/lib/Driver/ToolChains/MinGW.cpp @@ -348,6 +348,15 @@ void tools::MinGW::Linker::ConstructJob(Compilation &C, const JobAction &JA, Exec, CmdArgs, Inputs, Output)); } +static bool isCrossCompiling(const llvm::Triple &T, bool RequireArchMatch) { + llvm::Triple HostTriple(llvm::Triple::normalize(LLVM_HOST_TRIPLE)); + if (HostTriple.getOS() != llvm::Triple::Win32) + return true; + if (RequireArchMatch && HostTriple.getArch() != T.getArch()) + return true; + return false; +} + // Simplified from Generic_GCC::GCCInstallationDetector::ScanLibDirForGCCTriple. static bool findGccVersion(StringRef LibDir, std::string &GccLibDir, std::string &Ver, @@ -487,7 +496,13 @@ toolchains::MinGW::MinGW(const Driver &D, const llvm::Triple &Triple, getFilePaths().push_back( (Base + SubdirName + llvm::sys::path::get_separator() + "mingw/lib").str()); - getFilePaths().push_back(Base + "lib"); + // Only include <base>/lib if we're not cross compiling (not even for + // windows->windows to a diff erent arch), or if the sysroot has been set + // (where we presume the user has pointed it at an arch specific + // subdirectory). + if (!::isCrossCompiling(getTriple(), /*RequireArchMatch=*/true) || + getDriver().SysRoot.size()) + getFilePaths().push_back(Base + "lib"); NativeLLVMSupport = Args.getLastArgValue(options::OPT_fuse_ld_EQ, CLANG_DEFAULT_LINKER) @@ -649,7 +664,13 @@ void toolchains::MinGW::AddClangSystemIncludeArgs(const ArgList &DriverArgs, addSystemInclude(DriverArgs, CC1Args, Base + SubdirName + llvm::sys::path::get_separator() + "usr/include"); - addSystemInclude(DriverArgs, CC1Args, Base + "include"); + // Only include <base>/include if we're not cross compiling (but do allow it + // if we're on Windows and building for Windows on another architecture), + // or if the sysroot has been set (where we presume the user has pointed it + // at an arch specific subdirectory). + if (!::isCrossCompiling(getTriple(), /*RequireArchMatch=*/false) || + getDriver().SysRoot.size()) + addSystemInclude(DriverArgs, CC1Args, Base + "include"); } void toolchains::MinGW::addClangTargetOptions( diff --git a/clang/test/Driver/mingw-sysroot.cpp b/clang/test/Driver/mingw-sysroot.cpp index 17f2b975a10c3..911dab4927073 100644 --- a/clang/test/Driver/mingw-sysroot.cpp +++ b/clang/test/Driver/mingw-sysroot.cpp @@ -22,7 +22,12 @@ // If we find a gcc in the path with the right triplet prefix, pick that as // sysroot: -// RUN: env "PATH=%T/testroot-gcc/bin:%PATH%" %clang -target x86_64-w64-mingw32 -rtlib=platform -stdlib=libstdc++ --sysroot="" -c -### %s 2>&1 | FileCheck -check-prefix=CHECK_TESTROOT_GCC %s +// This test is only executed on non-Windows systems, i.e. only when +// cross compiling. Check that we don't add the tool root's plain include +// directory to the path - this would end up including /usr/include for +// cross toolchains installed in /usr. + +// RUN: env "PATH=%T/testroot-gcc/bin:%PATH%" %clang -target x86_64-w64-mingw32 -rtlib=platform -stdlib=libstdc++ --sysroot="" -c -### %s 2>&1 | FileCheck -check-prefix=CHECK_TESTROOT_GCC %s --implicit-check-not="\"{{.*}}/testroot-gcc{{/|\\\\}}include\"" // CHECK_TESTROOT_GCC: "-internal-isystem" "[[BASE:[^"]+]]/testroot-gcc{{/|\\\\}}lib{{/|\\\\}}gcc{{/|\\\\}}x86_64-w64-mingw32{{/|\\\\}}10.2-posix{{/|\\\\}}include{{/|\\\\}}c++" // CHECK_TESTROOT_GCC-SAME: {{^}} "-internal-isystem" "[[BASE]]/testroot-gcc{{/|\\\\}}lib{{/|\\\\}}gcc{{/|\\\\}}x86_64-w64-mingw32{{/|\\\\}}10.2-posix{{/|\\\\}}include{{/|\\\\}}c++{{/|\\\\}}x86_64-w64-mingw32" // CHECK_TESTROOT_GCC-SAME: {{^}} "-internal-isystem" "[[BASE]]/testroot-gcc{{/|\\\\}}lib{{/|\\\\}}gcc{{/|\\\\}}x86_64-w64-mingw32{{/|\\\\}}10.2-posix{{/|\\\\}}include{{/|\\\\}}c++{{/|\\\\}}backward" @@ -32,6 +37,13 @@ // CHECK_TESTROOT_GCC: "-internal-isystem" "[[BASE]]/testroot-gcc{{/|\\\\}}x86_64-w64-mingw32{{/|\\\\}}include" +// If we pass --sysroot explicitly, then we do include <sysroot>/include +// even when cross compiling. +// RUN: %clang -target x86_64-w64-mingw32 -rtlib=platform -stdlib=libstdc++ --sysroot="%T/testroot-gcc" -c -### %s 2>&1 | FileCheck -check-prefix=CHECK_TESTROOT_GCC_EXPLICIT %s + +// CHECK_TESTROOT_GCC_EXPLICIT: "-internal-isystem" "{{[^"]+}}/testroot-gcc{{/|\\\\}}include" + + // If there's a matching sysroot next to the clang binary itself, prefer that // over a gcc in the path: _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits