From ebc8a830f477db3d5b1f2e8c3eac262ee5beeb37 Mon Sep 17 00:00:00 2001 From: eastb233 Date: Sun, 28 Apr 2024 16:26:19 +0800 Subject: [PATCH] [Embedded][Cross] Adapt openEuler embedded cross building system openEuler embedded LLVM toolchain will integrate target sysroot and gcc runtime libraries, so try to search corresponding path. The directory structure will be like - /path/to/llvm-toolchain/ - bin - include - lib - lib64/gcc/{Triple}/{Version} # includes gcc target runtime like libgcc.a - {Triple} - include # includes gcc target headers - sysroot # includes target sysroot --- clang/lib/Driver/ToolChains/Gnu.cpp | 24 +++++++++++ clang/lib/Driver/ToolChains/Linux.cpp | 57 ++++++++++++++++++++++++- llvm/include/llvm/TargetParser/Triple.h | 3 ++ llvm/lib/TargetParser/Triple.cpp | 4 ++ 4 files changed, 86 insertions(+), 2 deletions(-) diff --git a/clang/lib/Driver/ToolChains/Gnu.cpp b/clang/lib/Driver/ToolChains/Gnu.cpp index 42050dced99c..e140746cada5 100644 --- a/clang/lib/Driver/ToolChains/Gnu.cpp +++ b/clang/lib/Driver/ToolChains/Gnu.cpp @@ -406,6 +406,21 @@ void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA, if (!D.SysRoot.empty()) CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot)); +#ifdef BUILD_FOR_EMBEDDED + else { + // In openEuler embedded cross building, it will have a default + // sysroot when sysroot is not given. So it need pass default + // sysroot to linker (especially for lld) to find correct path + // for dynamic linker and absolute path of linker script. + if (ToolChain.isCrossCompiling()) { + const StringRef ClangDir = D.getInstalledDir(); + std::string Path = + (ClangDir + "/../" + D.getTargetTriple() + "/sysroot").str(); + if (D.getVFS().exists(Path)) + CmdArgs.push_back(Args.MakeArgString("--sysroot=" + Path)); + } + } +#endif if (IsPIE) CmdArgs.push_back("-pie"); @@ -2120,6 +2135,15 @@ void Generic_GCC::GCCInstallationDetector::init( Prefixes.push_back(std::string(GCCToolchainDir)); } else { +#ifdef BUILD_FOR_EMBEDDED + // In openEuler embedded building system, it may find gcc + // installation in recipe-sysroot. But gcc runtime libraries + // in there are stripped which causing some failures. + // So try to search integrated gcc first. + if (TargetTriple.getVendor() == llvm::Triple::openEuler) + Prefixes.push_back(D.InstalledDir + "/.."); +#endif + // If we have a SysRoot, try that first. if (!D.SysRoot.empty()) { Prefixes.push_back(D.SysRoot); diff --git a/clang/lib/Driver/ToolChains/Linux.cpp b/clang/lib/Driver/ToolChains/Linux.cpp index 6ac2efc2283c..186b45e3c437 100644 --- a/clang/lib/Driver/ToolChains/Linux.cpp +++ b/clang/lib/Driver/ToolChains/Linux.cpp @@ -334,6 +334,13 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) addPathIfExists(D, concat(SysRoot, "/lib"), Paths); addPathIfExists(D, concat(SysRoot, "/usr/lib"), Paths); + +#ifdef BUILD_FOR_EMBEDDED + // In openEuler embedded building system, target libraries + // may be installed in /lib64. + if (Triple.getVendor() == llvm::Triple::openEuler) + addPathIfExists(D, concat(SysRoot, "/lib64"), Paths); +#endif } ToolChain::RuntimeLibType Linux::GetDefaultRuntimeLibType() const { @@ -398,7 +405,8 @@ std::string Linux::computeSysRoot() const { // openEuler embedded building system needs to search // more pre-defined paths. if (GCCInstallation.isValid() && - getTriple().getVendor() == llvm::Triple::OpenEmbedded) { + (getTriple().getVendor() == llvm::Triple::OpenEmbedded || + isCrossCompiling())) { const StringRef InstallDir = GCCInstallation.getInstallPath(); const StringRef TripleStr = GCCInstallation.getTriple().str(); @@ -409,7 +417,38 @@ std::string Linux::computeSysRoot() const { // scenarios where this path takes effect. std::string Path = (InstallDir + "/../../../../../" + TripleStr).str(); - if (getVFS().exists(Path)) + // Caution that we do native compilation and cross compilation + // in the same machine. We should skip this "Path" when cross + // compiling. + if (getTriple().getVendor() == llvm::Triple::OpenEmbedded && + getVFS().exists(Path)) + return Path; + + // There are two scenarios that we try to search target sysroot + // path when cross compiling. One is that the "--gcc-toolchain=" + // option is given, and openEuler embedded GCC cross toolchain's + // sysroot path could be + // "/path/to/gcc-toolchain/lib64/gcc/aarch64-openeuler-linux-gnu/12.3.1/../../../../aarch64-openeuler-linux-gnu/sysroot" + + // Another is that we use openEuler embedded LLVM toolchain's + // integrated sysroot, that is + // "/path/to/llvm-toolchain/lib64/gcc/aarch64-openeuler-linux-gnu/12.3.1/../../../../aarch64-openeuler-linux-gnu/sysroot" + + // Note we design openEuler embedded LLVM toolchain's integrated sysroot + // has the same directory structure as GCC. It consists of several parts, + // - /path/to/llvm-toolchain/ + // - bin + // - include + // - lib + // - lib64/gcc/{Triple}/{Version} # includes gcc target runtime like libgcc.a + // - {Triple} + // - include # includes gcc target headers + // - sysroot # includes target sysroot + + // So we can use the same relative path for both scenarios. + Path = (InstallDir + "/../../../../" + TripleStr + "/sysroot").str(); + + if (isCrossCompiling() && getVFS().exists(Path)) return Path; } #endif @@ -499,10 +538,19 @@ std::string Linux::getDynamicLinker(const ArgList &Args) const { default: llvm_unreachable("unsupported architecture"); +#ifdef BUILD_FOR_EMBEDDED + case llvm::Triple::aarch64: { + bool IsopenEuler = (Triple.getVendor() == llvm::Triple::openEuler); + LibDir = IsopenEuler ? "lib64" : "lib"; + Loader = "ld-linux-aarch64.so.1"; + break; + } +#else case llvm::Triple::aarch64: LibDir = "lib"; Loader = "ld-linux-aarch64.so.1"; break; +#endif case llvm::Triple::aarch64_be: LibDir = "lib"; Loader = "ld-linux-aarch64_be.so.1"; @@ -921,6 +969,11 @@ void Linux::addLibStdCxxIncludePaths(const llvm::opt::ArgList &DriverArgs, // Cray's gcc installation puts headers under "g++" without a // version suffix. LibDir.str() + "/../include/g++", +#ifdef BUILD_FOR_EMBEDDED + // In openEuler embedded building system, if we use recipe-sysroot, + // C++ headers are in /usr/include/c++/. + LibDir.str() + "/../usr/include/c++/" + Version.Text, +#endif }; for (const auto &IncludePath : LibStdCXXIncludePathCandidates) { diff --git a/llvm/include/llvm/TargetParser/Triple.h b/llvm/include/llvm/TargetParser/Triple.h index 79ccd644a50b..e0ac050b1c7b 100644 --- a/llvm/include/llvm/TargetParser/Triple.h +++ b/llvm/include/llvm/TargetParser/Triple.h @@ -179,6 +179,9 @@ public: AMD, Mesa, SUSE, +#ifdef BUILD_FOR_EMBEDDED + openEuler, +#endif OpenEmbedded, LastVendorType = OpenEmbedded }; diff --git a/llvm/lib/TargetParser/Triple.cpp b/llvm/lib/TargetParser/Triple.cpp index d21b103aee3e..2d61113f32a8 100644 --- a/llvm/lib/TargetParser/Triple.cpp +++ b/llvm/lib/TargetParser/Triple.cpp @@ -196,6 +196,9 @@ StringRef Triple::getVendorTypeName(VendorType Kind) { case PC: return "pc"; case SCEI: return "scei"; case SUSE: return "suse"; +#ifdef BUILD_FOR_EMBEDDED + case openEuler: return "openeuler"; +#endif } llvm_unreachable("Invalid VendorType!"); @@ -572,6 +575,7 @@ static Triple::VendorType parseVendor(StringRef VendorName) { .Case("oe", Triple::OpenEmbedded) #ifdef BUILD_FOR_EMBEDDED .Case("openeulersdk", Triple::OpenEmbedded) + .Case("openeuler", Triple::openEuler) #endif .Default(Triple::UnknownVendor); } -- Gitee