llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang-driver @llvm/pr-subscribers-clang Author: 徐持恒 Xu Chiheng (xu-chiheng) <details> <summary>Changes</summary> --- Patch is 35.89 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/74933.diff 5 Files Affected: - (modified) clang/lib/Driver/CMakeLists.txt (+1) - (modified) clang/lib/Driver/Driver.cpp (+4) - (added) clang/lib/Driver/ToolChains/Cygwin.cpp (+731) - (added) clang/lib/Driver/ToolChains/Cygwin.h (+125) - (modified) clang/lib/Lex/InitHeaderSearch.cpp (+4-26) ``````````diff diff --git a/clang/lib/Driver/CMakeLists.txt b/clang/lib/Driver/CMakeLists.txt index 58427e3f83c420..7ab5a1ee963515 100644 --- a/clang/lib/Driver/CMakeLists.txt +++ b/clang/lib/Driver/CMakeLists.txt @@ -51,6 +51,7 @@ add_clang_library(clangDriver ToolChains/CrossWindows.cpp ToolChains/CSKYToolChain.cpp ToolChains/Cuda.cpp + ToolChains/Cygwin.cpp ToolChains/Darwin.cpp ToolChains/DragonFly.cpp ToolChains/Flang.cpp diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp index e241706b9082ee..b6f3da3a006f4e 100644 --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -17,6 +17,7 @@ #include "ToolChains/Clang.h" #include "ToolChains/CrossWindows.h" #include "ToolChains/Cuda.h" +#include "ToolChains/Cygwin.h" #include "ToolChains/Darwin.h" #include "ToolChains/DragonFly.h" #include "ToolChains/FreeBSD.h" @@ -6263,6 +6264,9 @@ const ToolChain &Driver::getToolChain(const ArgList &Args, else TC = std::make_unique<toolchains::Generic_GCC>(*this, Target, Args); break; + case llvm::Triple::Cygnus: + TC = std::make_unique<toolchains::Cygwin>(*this, Target, Args); + break; case llvm::Triple::GNU: TC = std::make_unique<toolchains::MinGW>(*this, Target, Args); break; diff --git a/clang/lib/Driver/ToolChains/Cygwin.cpp b/clang/lib/Driver/ToolChains/Cygwin.cpp new file mode 100644 index 00000000000000..8aa9cf5c8ec034 --- /dev/null +++ b/clang/lib/Driver/ToolChains/Cygwin.cpp @@ -0,0 +1,731 @@ +//===--- Cygwin.cpp - CygwinToolChain Implementation ------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "Cygwin.h" +#include "CommonArgs.h" +#include "clang/Config/config.h" +#include "clang/Driver/Compilation.h" +#include "clang/Driver/Driver.h" +#include "clang/Driver/DriverDiagnostic.h" +#include "clang/Driver/InputInfo.h" +#include "clang/Driver/Options.h" +#include "clang/Driver/SanitizerArgs.h" +#include "llvm/Option/ArgList.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/Path.h" +#include "llvm/Support/VirtualFileSystem.h" +#include <system_error> + +using namespace clang::diag; +using namespace clang::driver; +using namespace clang; +using namespace llvm::opt; + +/// Cygwin Tools +void tools::Cygwin::Assembler::ConstructJob(Compilation &C, const JobAction &JA, + const InputInfo &Output, + const InputInfoList &Inputs, + const ArgList &Args, + const char *LinkingOutput) const { + claimNoWarnArgs(Args); + ArgStringList CmdArgs; + + if (getToolChain().getArch() == llvm::Triple::x86) { + CmdArgs.push_back("--32"); + } else if (getToolChain().getArch() == llvm::Triple::x86_64) { + CmdArgs.push_back("--64"); + } + + Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler); + + CmdArgs.push_back("-o"); + CmdArgs.push_back(Output.getFilename()); + + for (const auto &II : Inputs) + CmdArgs.push_back(II.getFilename()); + + const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as")); + C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(), + Exec, CmdArgs, Inputs, Output)); + + if (Args.hasArg(options::OPT_gsplit_dwarf)) + SplitDebugInfo(getToolChain(), C, *this, JA, Args, Output, + SplitDebugName(JA, Args, Inputs[0], Output)); +} + +void tools::Cygwin::Linker::AddLibGCC(const ArgList &Args, + ArgStringList &CmdArgs) const { + // Make use of compiler-rt if --rtlib option is used + ToolChain::RuntimeLibType RLT = getToolChain().GetRuntimeLibType(Args); + if (RLT == ToolChain::RLT_Libgcc) { + bool Static = Args.hasArg(options::OPT_static_libgcc) || + Args.hasArg(options::OPT_static); + bool Shared = Args.hasArg(options::OPT_shared); + bool CXX = getToolChain().getDriver().CCCIsCXX(); + + if (Static || (!CXX && !Shared)) { + CmdArgs.push_back("-lgcc"); + CmdArgs.push_back("-lgcc_eh"); + } else { + CmdArgs.push_back("-lgcc_s"); + CmdArgs.push_back("-lgcc"); + } + } else { + AddRunTimeLibs(getToolChain(), getToolChain().getDriver(), CmdArgs, Args); + } + + CmdArgs.push_back("-lcygwin"); +} + +void tools::Cygwin::Linker::ConstructJob(Compilation &C, const JobAction &JA, + const InputInfo &Output, + const InputInfoList &Inputs, + const ArgList &Args, + const char *LinkingOutput) const { + const ToolChain &TC = getToolChain(); + const Driver &D = TC.getDriver(); + const SanitizerArgs &Sanitize = TC.getSanitizerArgs(Args); + + ArgStringList CmdArgs; + + // Silence warning for "clang -g foo.o -o foo" + Args.ClaimAllArgs(options::OPT_g_Group); + // and "clang -emit-llvm foo.o -o foo" + Args.ClaimAllArgs(options::OPT_emit_llvm); + // and for "clang -w foo.o -o foo". Other warning options are already + // handled somewhere else. + Args.ClaimAllArgs(options::OPT_w); + + if (!D.SysRoot.empty()) + CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot)); + + if (Args.hasArg(options::OPT_s)) + CmdArgs.push_back("-s"); + + CmdArgs.push_back("-m"); + switch (TC.getArch()) { + case llvm::Triple::x86: + CmdArgs.push_back("i386pe"); + break; + case llvm::Triple::x86_64: + CmdArgs.push_back("i386pep"); + break; + case llvm::Triple::arm: + case llvm::Triple::thumb: + // FIXME: this is incorrect for WinCE + CmdArgs.push_back("thumb2pe"); + break; + case llvm::Triple::aarch64: + CmdArgs.push_back("arm64pe"); + break; + default: + D.Diag(diag::err_target_unknown_triple) << TC.getEffectiveTriple().str(); + } + + if (!Args.getLastArgValue(options::OPT_fuse_ld_EQ, "link").equals_insensitive("lld")) { + if (TC.getArch() == llvm::Triple::x86) { + CmdArgs.push_back("--wrap"); + CmdArgs.push_back("_Znwj"); + CmdArgs.push_back("--wrap"); + CmdArgs.push_back("_Znaj"); + CmdArgs.push_back("--wrap"); + CmdArgs.push_back("_ZnwjRKSt9nothrow_t"); + CmdArgs.push_back("--wrap"); + CmdArgs.push_back("_ZnajRKSt9nothrow_t"); + } else { + CmdArgs.push_back("--wrap"); + CmdArgs.push_back("_Znwm"); + CmdArgs.push_back("--wrap"); + CmdArgs.push_back("_Znam"); + CmdArgs.push_back("--wrap"); + CmdArgs.push_back("_ZnwmRKSt9nothrow_t"); + CmdArgs.push_back("--wrap"); + CmdArgs.push_back("_ZnamRKSt9nothrow_t"); + } + CmdArgs.push_back("--wrap"); + CmdArgs.push_back("_ZdlPv"); + CmdArgs.push_back("--wrap"); + CmdArgs.push_back("_ZdaPv"); + CmdArgs.push_back("--wrap"); + CmdArgs.push_back("_ZdlPvRKSt9nothrow_t"); + CmdArgs.push_back("--wrap"); + CmdArgs.push_back("_ZdaPvRKSt9nothrow_t"); + } + + Arg *SubsysArg = + Args.getLastArg(options::OPT_mwindows, options::OPT_mconsole); + if (SubsysArg && SubsysArg->getOption().matches(options::OPT_mwindows)) { + CmdArgs.push_back("--subsystem"); + CmdArgs.push_back("windows"); + } else if (SubsysArg && + SubsysArg->getOption().matches(options::OPT_mconsole)) { + CmdArgs.push_back("--subsystem"); + CmdArgs.push_back("console"); + } + + if (Args.hasArg(options::OPT_mdll)) + CmdArgs.push_back("--dll"); + else if (Args.hasArg(options::OPT_shared)) + CmdArgs.push_back("--shared"); + if (Args.hasArg(options::OPT_static)) + CmdArgs.push_back("-Bstatic"); + else + CmdArgs.push_back("-Bdynamic"); + if (Args.hasArg(options::OPT_mdll) || Args.hasArg(options::OPT_shared)) { + CmdArgs.push_back("-e"); + if (TC.getArch() == llvm::Triple::x86) + CmdArgs.push_back("__cygwin_dll_entry@12"); + else + CmdArgs.push_back("_cygwin_dll_entry"); + CmdArgs.push_back("--enable-auto-image-base"); + } + CmdArgs.push_back("--dynamicbase"); + + if (Args.hasArg(options::OPT_Z_Xlinker__no_demangle)) + CmdArgs.push_back("--no-demangle"); + + if (Arg *A = Args.getLastArg(options::OPT_mguard_EQ)) { + StringRef GuardArgs = A->getValue(); + if (GuardArgs == "none") + CmdArgs.push_back("--no-guard-cf"); + else if (GuardArgs == "cf" || GuardArgs == "cf-nochecks") + CmdArgs.push_back("--guard-cf"); + else + D.Diag(diag::err_drv_unsupported_option_argument) + << A->getSpelling() << GuardArgs; + } + + CmdArgs.push_back("-o"); + const char *OutputFile = Output.getFilename(); + // GCC implicitly adds an .exe extension if it is given an output file name + // that lacks an extension. + // GCC used to do this only when the compiler itself runs on windows, but + // since GCC 8 it does the same when cross compiling as well. + if (!llvm::sys::path::has_extension(OutputFile)) { + CmdArgs.push_back(Args.MakeArgString(Twine(OutputFile) + ".exe")); + OutputFile = CmdArgs.back(); + } else + CmdArgs.push_back(OutputFile); + + // FIXME: add -N, -n flags + Args.AddLastArg(CmdArgs, options::OPT_r); + Args.AddLastArg(CmdArgs, options::OPT_s); + Args.AddLastArg(CmdArgs, options::OPT_t); + Args.AddAllArgs(CmdArgs, options::OPT_u_Group); + Args.AddLastArg(CmdArgs, options::OPT_Z_Flag); + + // Add asan_dynamic as the first import lib before other libs. This allows + // asan to be initialized as early as possible to increase its instrumentation + // coverage to include other user DLLs which has not been built with asan. + if (Sanitize.needsAsanRt() && !Args.hasArg(options::OPT_nostdlib) && + !Args.hasArg(options::OPT_nodefaultlibs)) { + // Cygwin always links against a shared Cygwin DLL. + CmdArgs.push_back( + TC.getCompilerRTArgString(Args, "asan_dynamic", ToolChain::FT_Shared)); + } + + if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) { + if (Args.hasArg(options::OPT_shared) || Args.hasArg(options::OPT_mdll)) { + CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("crtbeginS.o"))); + } else { + CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("crt0.o"))); + CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("crtbegin.o"))); + } + if (Args.hasArg(options::OPT_pg)) + CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("gcrt0.o"))); + } + + Args.AddAllArgs(CmdArgs, options::OPT_L); + TC.AddFilePathLibArgs(Args, CmdArgs); + + // Add the compiler-rt library directories if they exist to help + // the linker find the various sanitizer, builtin, and profiling runtimes. + for (const auto &LibPath : TC.getLibraryPaths()) { + if (TC.getVFS().exists(LibPath)) + CmdArgs.push_back(Args.MakeArgString("-L" + LibPath)); + } + auto CRTPath = TC.getCompilerRTPath(); + if (TC.getVFS().exists(CRTPath)) + CmdArgs.push_back(Args.MakeArgString("-L" + CRTPath)); + + AddLinkerInputs(TC, Inputs, Args, CmdArgs, JA); + + if (C.getDriver().IsFlangMode()) { + addFortranRuntimeLibraryPath(TC, Args, CmdArgs); + addFortranRuntimeLibs(TC, CmdArgs); + } + + // TODO: Add profile stuff here + + if (TC.ShouldLinkCXXStdlib(Args)) { + bool OnlyLibstdcxxStatic = Args.hasArg(options::OPT_static_libstdcxx) && + !Args.hasArg(options::OPT_static); + if (OnlyLibstdcxxStatic) + CmdArgs.push_back("-Bstatic"); + TC.AddCXXStdlibLibArgs(Args, CmdArgs); + if (OnlyLibstdcxxStatic) + CmdArgs.push_back("-Bdynamic"); + } + + bool HasWindowsApp = false; + for (auto Lib : Args.getAllArgValues(options::OPT_l)) { + if (Lib == "windowsapp") { + HasWindowsApp = true; + break; + } + } + + if (!Args.hasArg(options::OPT_nostdlib)) { + if (!Args.hasArg(options::OPT_nodefaultlibs)) { + if (Args.hasArg(options::OPT_static)) + CmdArgs.push_back("--start-group"); + + if (Args.hasArg(options::OPT_fstack_protector) || + Args.hasArg(options::OPT_fstack_protector_strong) || + Args.hasArg(options::OPT_fstack_protector_all)) { + CmdArgs.push_back("-lssp_nonshared"); + CmdArgs.push_back("-lssp"); + } + + if (Args.hasFlag(options::OPT_fopenmp, options::OPT_fopenmp_EQ, + options::OPT_fno_openmp, false)) { + switch (TC.getDriver().getOpenMPRuntime(Args)) { + case Driver::OMPRT_OMP: + CmdArgs.push_back("-lomp"); + break; + case Driver::OMPRT_IOMP5: + CmdArgs.push_back("-liomp5md"); + break; + case Driver::OMPRT_GOMP: + CmdArgs.push_back("-lgomp"); + break; + case Driver::OMPRT_Unknown: + // Already diagnosed. + break; + } + } + + AddLibGCC(Args, CmdArgs); + + if (Sanitize.needsAsanRt()) { + // Cygwin always links against a shared Cygwin DLL. + CmdArgs.push_back(TC.getCompilerRTArgString(Args, "asan_dynamic", + ToolChain::FT_Shared)); + CmdArgs.push_back( + TC.getCompilerRTArgString(Args, "asan_dynamic_runtime_thunk")); + CmdArgs.push_back("--require-defined"); + CmdArgs.push_back(TC.getArch() == llvm::Triple::x86 + ? "___asan_seh_interceptor" + : "__asan_seh_interceptor"); + // Make sure the linker consider all object files from the dynamic + // runtime thunk. + CmdArgs.push_back("--whole-archive"); + CmdArgs.push_back( + TC.getCompilerRTArgString(Args, "asan_dynamic_runtime_thunk")); + CmdArgs.push_back("--no-whole-archive"); + } + + TC.addProfileRTLibs(Args, CmdArgs); + + if (!HasWindowsApp) { + // Add system libraries. If linking to libwindowsapp.a, that import + // library replaces all these and we shouldn't accidentally try to + // link to the normal desktop mode dlls. + if (Args.hasArg(options::OPT_mwindows)) { + CmdArgs.push_back("-lgdi32"); + CmdArgs.push_back("-lcomdlg32"); + } + CmdArgs.push_back("-ladvapi32"); + CmdArgs.push_back("-lshell32"); + CmdArgs.push_back("-luser32"); + CmdArgs.push_back("-lkernel32"); + } + + if (Args.hasArg(options::OPT_static)) { + CmdArgs.push_back("--end-group"); + } else { + AddLibGCC(Args, CmdArgs); + if (!HasWindowsApp) + CmdArgs.push_back("-lkernel32"); + } + } + + if (!Args.hasArg(options::OPT_nostartfiles)) { + // Add crtfastmath.o if available and fast math is enabled. + TC.addFastMathRuntimeIfAvailable(Args, CmdArgs); + + CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("crtend.o"))); + } + } + const char *Exec = Args.MakeArgString(TC.GetLinkerPath()); + C.addCommand(std::make_unique<Command>(JA, *this, + ResponseFileSupport::AtFileUTF8(), + Exec, CmdArgs, Inputs, Output)); +} + +static bool isCrossCompiling(const llvm::Triple &T, bool RequireArchMatch) { + llvm::Triple HostTriple(llvm::Triple::normalize(LLVM_HOST_TRIPLE)); + if (!HostTriple.isWindowsCygwinEnvironment()) + 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, + toolchains::Generic_GCC::GCCVersion &Version) { + Version = toolchains::Generic_GCC::GCCVersion::Parse("0.0.0"); + std::error_code EC; + for (llvm::sys::fs::directory_iterator LI(LibDir, EC), LE; !EC && LI != LE; + LI = LI.increment(EC)) { + StringRef VersionText = llvm::sys::path::filename(LI->path()); + auto CandidateVersion = + toolchains::Generic_GCC::GCCVersion::Parse(VersionText); + if (CandidateVersion.Major == -1) + continue; + if (CandidateVersion <= Version) + continue; + Version = CandidateVersion; + Ver = std::string(VersionText); + GccLibDir = LI->path(); + } + return Ver.size(); +} + +static llvm::Triple getLiteralTriple(const Driver &D, const llvm::Triple &T) { + llvm::Triple LiteralTriple(D.getTargetTriple()); + // The arch portion of the triple may be overridden by -m32/-m64. + LiteralTriple.setArchName(T.getArchName()); + return LiteralTriple; +} + +void toolchains::Cygwin::findGccLibDir(const llvm::Triple &LiteralTriple) { + llvm::SmallVector<llvm::SmallString<32>, 5> SubdirNames; + SubdirNames.emplace_back(getTriple().getArchName()); + SubdirNames[0] += "-pc-cygwin"; + SubdirNames.emplace_back("cygwin"); + if (SubdirName.empty()) + SubdirName = SubdirNames[0].str(); + // lib: Arch Linux, Ubuntu, Windows + // lib64: openSUSE Linux + for (StringRef CandidateLib : {"lib", "lib64"}) { + for (StringRef CandidateSysroot : SubdirNames) { + llvm::SmallString<1024> LibDir(Base); + llvm::sys::path::append(LibDir, CandidateLib, "gcc", CandidateSysroot); + if (findGccVersion(LibDir, GccLibDir, Ver, GccVer)) { + SubdirName = std::string(CandidateSysroot); + return; + } + } + } +} + +static llvm::ErrorOr<std::string> findGcc(const llvm::Triple &LiteralTriple, + const llvm::Triple &T) { + llvm::SmallVector<llvm::SmallString<32>, 5> Gccs; + Gccs.emplace_back(T.getArchName()); + Gccs[0] += "-pc-cygwin-gcc"; + Gccs.emplace_back("cygwin-gcc"); + // Please do not add "gcc" here + for (StringRef CandidateGcc : Gccs) + if (llvm::ErrorOr<std::string> GPPName = llvm::sys::findProgramByName(CandidateGcc)) + return GPPName; + return make_error_code(std::errc::no_such_file_or_directory); +} + +static llvm::ErrorOr<std::string> +findClangRelativeSysroot(const Driver &D, const llvm::Triple &LiteralTriple, + const llvm::Triple &T, std::string &SubdirName) { + llvm::SmallVector<llvm::SmallString<32>, 4> Subdirs; + Subdirs.emplace_back(T.str()); + Subdirs.emplace_back(T.getArchName()); + Subdirs[1] += "-pc-cygwin"; + 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)) { + SubdirName = std::string(CandidateSubdir); + return (ClangRoot + Sep + CandidateSubdir).str(); + } + } + return make_error_code(std::errc::no_such_file_or_directory); +} + +toolchains::Cygwin::Cygwin(const Driver &D, const llvm::Triple &Triple, + const ArgList &Args) + : ToolChain(D, Triple, Args), CudaInstallation(D, Triple, Args), + 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. + llvm::Triple LiteralTriple = getLiteralTriple(D, getTriple()); + 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( + getDriver(), LiteralTriple, getTriple(), SubdirName)) + Base = std::string(llvm::sys::path::parent_path(TargetSubdir.get())); + else if (llvm::ErrorOr<std::string> GPPName = + findGcc(LiteralTriple, getTriple())) + Base = std::string(llvm::sys::path::parent_path( + llvm::sys::path::parent_path(GPPName.get()))); + else + Base = std::string( + llvm::sys::path::parent_path(getDriver().getInstalledDir())); + + Base += llvm::sys::path::get_separator(); + findGccLibDir(LiteralTriple); + TripleDirName = SubdirName; + // GccLibDir must precede Base/lib so that the + // correct crtbegin.o ,cetend.o would be found. + getFilePaths().push_back(GccLibDir); + getFilePath... [truncated] `````````` </details> https://github.com/llvm/llvm-project/pull/74933 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits