FI, here are the patches I am currently using to get the package built.
D54378 and 54379 are still being discussed upstream, and the last two
still need to be cleaned and submitted upstream.

Samuel
Add Hurd support.

Patch by samuel.thiba...@ens-lyon.org

Differential Revision: https://reviews.llvm.org/D54079

Index: openmp/runtime/src/kmp.h
===================================================================
--- openmp/runtime/src/kmp.h.orig
+++ openmp/runtime/src/kmp.h
@@ -1048,6 +1048,10 @@ extern kmp_uint64 __kmp_now_nsec();
 /* TODO: tune for KMP_OS_NETBSD */
 #define KMP_INIT_WAIT 1024U /* initial number of spin-tests   */
 #define KMP_NEXT_WAIT 512U /* susequent number of spin-tests */
+#elif KMP_OS_HURD
+/* TODO: tune for KMP_OS_HURD */
+#define KMP_INIT_WAIT 1024U /* initial number of spin-tests   */
+#define KMP_NEXT_WAIT 512U /* susequent number of spin-tests */
 #endif
 
 #if KMP_ARCH_X86 || KMP_ARCH_X86_64
Index: openmp/runtime/src/kmp_ftn_entry.h
===================================================================
--- openmp/runtime/src/kmp_ftn_entry.h.orig
+++ openmp/runtime/src/kmp_ftn_entry.h
@@ -369,7 +369,7 @@ int FTN_STDCALL KMP_EXPAND_NAME(FTN_GET_
 #else
   int gtid;
 
-#if KMP_OS_DARWIN || KMP_OS_FREEBSD || KMP_OS_NETBSD
+#if KMP_OS_DARWIN || KMP_OS_FREEBSD || KMP_OS_NETBSD || KMP_OS_HURD
   gtid = __kmp_entry_gtid();
 #elif KMP_OS_WINDOWS
   if (!__kmp_init_parallel ||
Index: openmp/runtime/src/kmp_platform.h
===================================================================
--- openmp/runtime/src/kmp_platform.h.orig
+++ openmp/runtime/src/kmp_platform.h
@@ -22,6 +22,7 @@
 #define KMP_OS_DARWIN 0
 #define KMP_OS_WINDOWS 0
 #define KMP_OS_CNK 0
+#define KMP_OS_HURD 0
 #define KMP_OS_UNIX 0 /* disjunction of KMP_OS_LINUX, KMP_OS_DARWIN etc. */
 
 #ifdef _WIN32
@@ -59,13 +60,18 @@
 #define KMP_OS_CNK 1
 #endif
 
+#if (defined __GNU__)
+#undef KMP_OS_HURD
+#define KMP_OS_HURD 1
+#endif
+
 #if (1 !=                                                                      \
      KMP_OS_LINUX + KMP_OS_FREEBSD + KMP_OS_NETBSD + KMP_OS_DARWIN +           \
-         KMP_OS_WINDOWS)
+         KMP_OS_WINDOWS + KMP_OS_HURD)
 #error Unknown OS
 #endif
 
-#if KMP_OS_LINUX || KMP_OS_FREEBSD || KMP_OS_NETBSD || KMP_OS_DARWIN
+#if KMP_OS_LINUX || KMP_OS_FREEBSD || KMP_OS_NETBSD || KMP_OS_DARWIN || KMP_OS_HURD
 #undef KMP_OS_UNIX
 #define KMP_OS_UNIX 1
 #endif
Index: openmp/runtime/src/kmp_runtime.cpp
===================================================================
--- openmp/runtime/src/kmp_runtime.cpp.orig
+++ openmp/runtime/src/kmp_runtime.cpp
@@ -7643,7 +7643,7 @@ __kmp_determine_reduction_method(
 #if KMP_ARCH_X86_64 || KMP_ARCH_PPC64 || KMP_ARCH_AARCH64 || KMP_ARCH_MIPS64
 
 #if KMP_OS_LINUX || KMP_OS_FREEBSD || KMP_OS_NETBSD || KMP_OS_WINDOWS ||       \
-    KMP_OS_DARWIN
+    KMP_OS_DARWIN || KMP_OS_HURD
 
     int teamsize_cutoff = 4;
 
@@ -7670,7 +7670,7 @@ __kmp_determine_reduction_method(
 
 #elif KMP_ARCH_X86 || KMP_ARCH_ARM || KMP_ARCH_AARCH || KMP_ARCH_MIPS
 
-#if KMP_OS_LINUX || KMP_OS_WINDOWS
+#if KMP_OS_LINUX || KMP_OS_WINDOWS || KMP_OS_HURD
 
     // basic tuning
 
Index: openmp/runtime/src/thirdparty/ittnotify/ittnotify_static.c
===================================================================
--- openmp/runtime/src/thirdparty/ittnotify/ittnotify_static.c.orig
+++ openmp/runtime/src/thirdparty/ittnotify/ittnotify_static.c
@@ -70,6 +70,10 @@ static const char* ittnotify_lib_name =
 #define ANDROID_ITTNOTIFY_DEFAULT_PATH  "/data/data/com.intel.vtune/intel/libittnotify.so"
 #endif
 
+#ifndef PATH_MAX
+#define PATH_MAX 4096
+#endif
+
 
 #ifndef LIB_VAR_NAME
 #if ITT_ARCH==ITT_ARCH_IA32 || ITT_ARCH==ITT_ARCH_ARM || ITT_ARCH==ITT_ARCH_MIPS
Index: openmp/runtime/src/z_Linux_util.cpp
===================================================================
--- openmp/runtime/src/z_Linux_util.cpp.orig
+++ openmp/runtime/src/z_Linux_util.cpp
@@ -444,8 +444,7 @@ void __kmp_terminate_thread(int gtid) {
    determined exactly, FALSE if incremental refinement is necessary. */
 static kmp_int32 __kmp_set_stack_info(int gtid, kmp_info_t *th) {
   int stack_data;
-#if KMP_OS_LINUX || KMP_OS_FREEBSD || KMP_OS_NETBSD
-  /* Linux* OS only -- no pthread_getattr_np support on OS X* */
+#if KMP_OS_LINUX || KMP_OS_FREEBSD || KMP_OS_NETBSD || KMP_OS_HURD
   pthread_attr_t attr;
   int status;
   size_t size = 0;
@@ -497,7 +496,7 @@ static void *__kmp_launch_worker(void *t
   sigset_t new_set, old_set;
 #endif /* KMP_BLOCK_SIGNALS */
   void *exit_val;
-#if KMP_OS_LINUX || KMP_OS_FREEBSD || KMP_OS_NETBSD
+#if KMP_OS_LINUX || KMP_OS_FREEBSD || KMP_OS_NETBSD || KMP_OS_HURD
   void *volatile padding = 0;
 #endif
   int gtid;
@@ -1765,7 +1764,7 @@ static int __kmp_get_xproc(void) {
 
   int r = 0;
 
-#if KMP_OS_LINUX || KMP_OS_FREEBSD || KMP_OS_NETBSD
+#if KMP_OS_LINUX || KMP_OS_FREEBSD || KMP_OS_NETBSD || KMP_OS_HURD
 
   r = sysconf(_SC_NPROCESSORS_ONLN);
 
@@ -1953,9 +1952,9 @@ int __kmp_is_address_mapped(void *addr)
   int found = 0;
   int rc;
 
-#if KMP_OS_LINUX || KMP_OS_FREEBSD
+#if KMP_OS_LINUX || KMP_OS_FREEBSD || KMP_OS_HURD
 
-  /* On Linux* OS, read the /proc/<pid>/maps pseudo-file to get all the address
+  /* On GNUish OSes, read the /proc/<pid>/maps pseudo-file to get all the address
      ranges mapped into the address space. */
 
   char *name = __kmp_str_format("/proc/%d/maps", getpid());
Index: llvm-toolchain-7-7/libcxx/src/thread.cpp
===================================================================
--- llvm-toolchain-7-7.orig/libcxx/src/thread.cpp
+++ llvm-toolchain-7-7/libcxx/src/thread.cpp
@@ -19,9 +19,9 @@
 
 #if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
 # include <sys/param.h>
-# if defined(BSD)
+# if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) || defined(__APPLE__)
 #   include <sys/sysctl.h>
-# endif // defined(BSD)
+# endif
 #endif // defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
 
 #if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) || defined(__CloudABI__) || defined(__Fuchsia__)
Index: llvm-toolchain-7-7/libcxx/include/__config
===================================================================
--- llvm-toolchain-7-7.orig/libcxx/include/__config
+++ llvm-toolchain-7-7/libcxx/include/__config
@@ -1110,6 +1110,7 @@ _LIBCPP_FUNC_VIS extern "C" void __sanit
       defined(__Fuchsia__) || \
       defined(__NetBSD__) || \
       defined(__linux__) || \
+      defined(__GNU__) || \
       defined(__APPLE__) || \
       defined(__CloudABI__) || \
       defined(__sun__) || \
Index: llvm-toolchain-7-7.0.1~+rc2/include/llvm/ADT/Triple.h
===================================================================
--- llvm-toolchain-7-7.0.1~+rc2.orig/include/llvm/ADT/Triple.h
+++ llvm-toolchain-7-7.0.1~+rc2/include/llvm/ADT/Triple.h
@@ -182,7 +182,8 @@ public:
     Mesa3D,
     Contiki,
     AMDPAL,     // AMD PAL Runtime
-    LastOSType = AMDPAL
+    Hurd,       // GNU/Hurd
+    LastOSType = Hurd
   };
   enum EnvironmentType {
     UnknownEnvironment,
@@ -578,9 +579,15 @@ public:
     return getOS() == Triple::KFreeBSD;
   }
 
+  /// Tests whether the OS is Hurd.
+  bool isOSHurd() const {
+    return getOS() == Triple::Hurd;
+  }
+
   /// Tests whether the OS uses glibc.
   bool isOSGlibc() const {
-    return (getOS() == Triple::Linux || getOS() == Triple::KFreeBSD) &&
+    return (getOS() == Triple::Linux || getOS() == Triple::KFreeBSD ||
+            getOS() == Triple::Hurd) &&
            !isAndroid();
   }
 
Index: llvm-toolchain-7-7.0.1~+rc2/lib/Support/Triple.cpp
===================================================================
--- llvm-toolchain-7-7.0.1~+rc2.orig/lib/Support/Triple.cpp
+++ llvm-toolchain-7-7.0.1~+rc2/lib/Support/Triple.cpp
@@ -209,6 +209,7 @@ StringRef Triple::getOSTypeName(OSType K
   case Mesa3D: return "mesa3d";
   case Contiki: return "contiki";
   case AMDPAL: return "amdpal";
+  case Hurd: return "hurd";
   }
 
   llvm_unreachable("Invalid OSType");
@@ -502,6 +503,7 @@ static Triple::OSType parseOS(StringRef
     .StartsWith("mesa3d", Triple::Mesa3D)
     .StartsWith("contiki", Triple::Contiki)
     .StartsWith("amdpal", Triple::AMDPAL)
+    .StartsWith("hurd", Triple::Hurd)
     .Default(Triple::UnknownOS);
 }
 
Index: llvm/unittests/ADT/TripleTest.cpp
===================================================================
--- llvm/unittests/ADT/TripleTest.cpp	(révision 346226)
+++ llvm/unittests/ADT/TripleTest.cpp	(copie de travail)
@@ -93,6 +93,12 @@
   EXPECT_EQ(Triple::Contiki, T.getOS());
   EXPECT_EQ(Triple::UnknownEnvironment, T.getEnvironment());
 
+  T = Triple("i386-pc-hurd-gnu");
+  EXPECT_EQ(Triple::x86, T.getArch());
+  EXPECT_EQ(Triple::PC, T.getVendor());
+  EXPECT_EQ(Triple::Hurd, T.getOS());
+  EXPECT_EQ(Triple::GNU, T.getEnvironment());
+
   T = Triple("x86_64-pc-linux-gnu");
   EXPECT_EQ(Triple::x86_64, T.getArch());
   EXPECT_EQ(Triple::PC, T.getVendor());
Index: llvm-toolchain-7-7.0.1~+rc2/clang/lib/Basic/Targets/OSTargets.h
===================================================================
--- llvm-toolchain-7-7.0.1~+rc2.orig/clang/lib/Basic/Targets/OSTargets.h
+++ llvm-toolchain-7-7.0.1~+rc2/clang/lib/Basic/Targets/OSTargets.h
@@ -270,6 +270,27 @@ public:
   }
 };
 
+// Hurd target
+template <typename Target>
+class LLVM_LIBRARY_VISIBILITY HurdTargetInfo : public OSTargetInfo<Target> {
+protected:
+  void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
+                    MacroBuilder &Builder) const override {
+    // Linux defines; list based off of gcc output
+    DefineStd(Builder, "unix", Opts);
+    Builder.defineMacro("__GNU__");
+    Builder.defineMacro("__GLIBC__");
+    Builder.defineMacro("__ELF__");
+    if (Opts.POSIXThreads)
+      Builder.defineMacro("_REENTRANT");
+    if (Opts.CPlusPlus)
+      Builder.defineMacro("_GNU_SOURCE");
+  }
+public:
+  HurdTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
+      : OSTargetInfo<Target>(Triple, Opts) {}
+};
+
 // Minix Target
 template <typename Target>
 class LLVM_LIBRARY_VISIBILITY MinixTargetInfo : public OSTargetInfo<Target> {
Index: llvm-toolchain-7-7.0.1~+rc2/clang/lib/Basic/Targets.cpp
===================================================================
--- llvm-toolchain-7-7.0.1~+rc2.orig/clang/lib/Basic/Targets.cpp
+++ llvm-toolchain-7-7.0.1~+rc2/clang/lib/Basic/Targets.cpp
@@ -495,6 +495,8 @@ TargetInfo *AllocateTarget(const llvm::T
       return new NaClTargetInfo<X86_32TargetInfo>(Triple, Opts);
     case llvm::Triple::ELFIAMCU:
       return new MCUX86_32TargetInfo(Triple, Opts);
+    case llvm::Triple::Hurd:
+      return new HurdTargetInfo<X86_32TargetInfo>(Triple, Opts);
     default:
       return new X86_32TargetInfo(Triple, Opts);
     }
Index: llvm-toolchain-7-7.0.1~+rc2/clang/lib/Driver/CMakeLists.txt
===================================================================
--- llvm-toolchain-7-7.0.1~+rc2.orig/clang/lib/Driver/CMakeLists.txt
+++ llvm-toolchain-7-7.0.1~+rc2/clang/lib/Driver/CMakeLists.txt
@@ -47,6 +47,7 @@ add_clang_library(clangDriver
   ToolChains/Haiku.cpp
   ToolChains/HIP.cpp
   ToolChains/Hexagon.cpp
+  ToolChains/Hurd.cpp
   ToolChains/Linux.cpp
   ToolChains/MipsLinux.cpp
   ToolChains/MinGW.cpp
Index: llvm-toolchain-7-7.0.1~+rc2/clang/lib/Driver/Driver.cpp
===================================================================
--- llvm-toolchain-7-7.0.1~+rc2.orig/clang/lib/Driver/Driver.cpp
+++ llvm-toolchain-7-7.0.1~+rc2/clang/lib/Driver/Driver.cpp
@@ -26,6 +26,7 @@
 #include "ToolChains/HIP.h"
 #include "ToolChains/Haiku.h"
 #include "ToolChains/Hexagon.h"
+#include "ToolChains/Hurd.h"
 #include "ToolChains/Lanai.h"
 #include "ToolChains/Linux.h"
 #include "ToolChains/MSVC.h"
@@ -399,6 +400,13 @@ static llvm::Triple computeTargetTriple(
 
   llvm::Triple Target(llvm::Triple::normalize(TargetTriple));
 
+  // GNU/Hurd's triple should have been -hurd-gnu*, but was historically made
+  // -gnu* only, and we can not change this, so we have to detect that case as
+  // being the Hurd OS.
+  if (TargetTriple.find("unknown-gnu") != StringRef::npos ||
+      TargetTriple.find("pc-gnu") != StringRef::npos)
+    Target.setOSName("hurd");
+
   // Handle Apple-specific options available here.
   if (Target.isOSBinFormatMachO()) {
     // If an explicit Darwin arch name is given, that trumps all.
@@ -4374,6 +4382,9 @@ const ToolChain &Driver::getToolChain(co
     case llvm::Triple::Contiki:
       TC = llvm::make_unique<toolchains::Contiki>(*this, Target, Args);
       break;
+    case llvm::Triple::Hurd:
+      TC = llvm::make_unique<toolchains::Hurd>(*this, Target, Args);
+      break;
     default:
       // Of these targets, Hexagon is the only one that might have
       // an OS of Linux, in which case it got handled above already.
Index: llvm-toolchain-7-7.0.1~+rc2/clang/lib/Driver/ToolChains/Clang.cpp
===================================================================
--- llvm-toolchain-7-7.0.1~+rc2.orig/clang/lib/Driver/ToolChains/Clang.cpp
+++ llvm-toolchain-7-7.0.1~+rc2/clang/lib/Driver/ToolChains/Clang.cpp
@@ -528,7 +528,7 @@ static bool useFramePointerForTargetByDe
     return !areOptimizationsEnabled(Args);
   }
 
-  if (Triple.isOSLinux() || Triple.getOS() == llvm::Triple::CloudABI) {
+  if (Triple.isOSLinux() || Triple.getOS() == llvm::Triple::CloudABI || Triple.isOSHurd()) {
     switch (Triple.getArch()) {
     // Don't use a frame pointer on linux if optimizing for certain targets.
     case llvm::Triple::mips64:
Index: llvm-toolchain-7-7.0.1~+rc2/clang/lib/Driver/ToolChains/Gnu.cpp
===================================================================
--- llvm-toolchain-7-7.0.1~+rc2.orig/clang/lib/Driver/ToolChains/Gnu.cpp
+++ llvm-toolchain-7-7.0.1~+rc2/clang/lib/Driver/ToolChains/Gnu.cpp
@@ -1846,7 +1846,9 @@ void Generic_GCC::GCCInstallationDetecto
       "i686-linux-gnu",       "i686-pc-linux-gnu",     "i486-linux-gnu",
       "i386-linux-gnu",       "i386-redhat-linux6E",   "i686-redhat-linux",
       "i586-redhat-linux",    "i386-redhat-linux",     "i586-suse-linux",
-      "i486-slackware-linux", "i686-montavista-linux", "i586-linux-gnu"};
+      "i486-slackware-linux", "i686-montavista-linux", "i586-linux-gnu",
+      "i386-gnu",             "i486-gnu",              "i586-gnu",
+      "i686-gnu"};
 
   static const char *const MIPSLibDirs[] = {"/lib"};
   static const char *const MIPSTriples[] = {"mips-linux-gnu", "mips-mti-linux",
@@ -2210,6 +2212,9 @@ void Generic_GCC::GCCInstallationDetecto
       // triple.
       {"i386-linux-gnu/gcc/" + CandidateTriple.str(), "../../..",
        (TargetArch == llvm::Triple::x86 &&
+        TargetTriple.getOS() != llvm::Triple::Solaris)},
+      {"i386-gnu/gcc/" + CandidateTriple.str(), "../../..",
+       (TargetArch == llvm::Triple::x86 &&
         TargetTriple.getOS() != llvm::Triple::Solaris)}};
 
   for (auto &Suffix : Suffixes) {
Index: llvm-toolchain-7-7.0.1~+rc2/clang/lib/Driver/ToolChains/Hurd.cpp
===================================================================
--- /dev/null
+++ llvm-toolchain-7-7.0.1~+rc2/clang/lib/Driver/ToolChains/Hurd.cpp
@@ -0,0 +1,191 @@
+//===--- Hurd.cpp - Hurd ToolChain Implementations --------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Hurd.h"
+#include "CommonArgs.h"
+#include "clang/Basic/VirtualFileSystem.h"
+#include "clang/Config/config.h"
+#include "clang/Driver/Driver.h"
+#include "clang/Driver/Options.h"
+#include "llvm/Support/Path.h"
+
+using namespace clang::driver;
+using namespace clang::driver::toolchains;
+using namespace clang;
+using namespace llvm::opt;
+
+using tools::addPathIfExists;
+
+/// Get our best guess at the multiarch triple for a target.
+///
+/// Debian-based systems are starting to use a multiarch setup where they use
+/// a target-triple directory in the library and header search paths.
+/// Unfortunately, this triple does not align with the vanilla target triple,
+/// so we provide a rough mapping here.
+static std::string getMultiarchTriple(const Driver &D,
+                                      const llvm::Triple &TargetTriple,
+                                      StringRef SysRoot) {
+  // For most architectures, just use whatever we have rather than trying to be
+  // clever.
+  switch (TargetTriple.getArch()) {
+  default:
+    break;
+
+  // We use the existence of '/lib/<triple>' as a directory to detect some
+  // common hurd triples that don't quite match the Clang triple for both
+  // 32-bit and 64-bit targets. Multiarch fixes its install triples to these
+  // regardless of what the actual target triple is.
+  case llvm::Triple::x86:
+    if (D.getVFS().exists(SysRoot + "/lib/i386-gnu"))
+      return "i386-gnu";
+    break;
+  }
+
+  return TargetTriple.str();
+}
+
+static StringRef getOSLibDir(const llvm::Triple &Triple, const ArgList &Args) {
+  // It happens that only x86 and PPC use the 'lib32' variant of oslibdir, and
+  // using that variant while targeting other architectures causes problems
+  // because the libraries are laid out in shared system roots that can't cope
+  // with a 'lib32' library search path being considered. So we only enable
+  // them when we know we may need it.
+  //
+  // FIXME: This is a bit of a hack. We should really unify this code for
+  // reasoning about oslibdir spellings with the lib dir spellings in the
+  // GCCInstallationDetector, but that is a more significant refactoring.
+
+  if (Triple.getArch() == llvm::Triple::x86)
+    return "lib32";
+
+  return Triple.isArch32Bit() ? "lib" : "lib64";
+}
+
+Hurd::Hurd(const Driver &D, const llvm::Triple &Triple,
+                 const ArgList &Args)
+    : Generic_ELF(D, Triple, Args) {
+  std::string SysRoot = computeSysRoot();
+  path_list &Paths = getFilePaths();
+
+  const std::string OSLibDir = getOSLibDir(Triple, Args);
+  const std::string MultiarchTriple = getMultiarchTriple(D, Triple, SysRoot);
+
+  // Similar to the logic for GCC above, if we currently running Clang inside
+  // of the requested system root, add its parent library paths to
+  // those searched.
+  // FIXME: It's not clear whether we should use the driver's installed
+  // directory ('Dir' below) or the ResourceDir.
+  if (StringRef(D.Dir).startswith(SysRoot)) {
+    addPathIfExists(D, D.Dir + "/../lib/" + MultiarchTriple, Paths);
+    addPathIfExists(D, D.Dir + "/../" + OSLibDir, Paths);
+  }
+
+  addPathIfExists(D, SysRoot + "/lib/" + MultiarchTriple, Paths);
+  addPathIfExists(D, SysRoot + "/lib/../" + OSLibDir, Paths);
+
+  addPathIfExists(D, SysRoot + "/usr/lib/" + MultiarchTriple, Paths);
+  addPathIfExists(D, SysRoot + "/usr/lib/../" + OSLibDir, Paths);
+
+  // If we are currently running Clang inside of the requested system root, add
+  // its parent library path to those searched.
+  // FIXME: It's not clear whether we should use the driver's installed
+  // directory ('Dir' below) or the ResourceDir.
+  if (StringRef(D.Dir).startswith(SysRoot))
+    addPathIfExists(D, D.Dir + "/../lib", Paths);
+
+  addPathIfExists(D, SysRoot + "/lib", Paths);
+  addPathIfExists(D, SysRoot + "/usr/lib", Paths);
+}
+
+bool Hurd::HasNativeLLVMSupport() const { return true; }
+
+Tool *Hurd::buildLinker() const { return new tools::gnutools::Linker(*this); }
+
+Tool *Hurd::buildAssembler() const {
+  return new tools::gnutools::Assembler(*this);
+}
+
+std::string Hurd::computeSysRoot() const {
+  if (!getDriver().SysRoot.empty())
+    return getDriver().SysRoot;
+
+  return std::string();
+}
+
+std::string Hurd::getDynamicLinker(const ArgList &Args) const {
+  const llvm::Triple::ArchType Arch = getArch();
+
+  if (Arch == llvm::Triple::x86)
+    return "/lib/ld.so";
+
+  llvm_unreachable("unsupported architecture");
+}
+
+void Hurd::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
+                                     ArgStringList &CC1Args) const {
+  const Driver &D = getDriver();
+  std::string SysRoot = computeSysRoot();
+
+  if (DriverArgs.hasArg(clang::driver::options::OPT_nostdinc))
+    return;
+
+  if (!DriverArgs.hasArg(options::OPT_nostdlibinc))
+    addSystemInclude(DriverArgs, CC1Args, SysRoot + "/usr/local/include");
+
+  if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
+    SmallString<128> P(D.ResourceDir);
+    llvm::sys::path::append(P, "include");
+    addSystemInclude(DriverArgs, CC1Args, P);
+  }
+
+  if (DriverArgs.hasArg(options::OPT_nostdlibinc))
+    return;
+
+  // Check for configure-time C include directories.
+  StringRef CIncludeDirs(C_INCLUDE_DIRS);
+  if (CIncludeDirs != "") {
+    SmallVector<StringRef, 5> dirs;
+    CIncludeDirs.split(dirs, ":");
+    for (StringRef dir : dirs) {
+      StringRef Prefix =
+          llvm::sys::path::is_absolute(dir) ? StringRef(SysRoot) : "";
+      addExternCSystemInclude(DriverArgs, CC1Args, Prefix + dir);
+    }
+    return;
+  }
+
+  // Lacking those, try to detect the correct set of system includes for the
+  // target triple.
+
+  const StringRef X86MultiarchIncludeDirs[] = {
+      "/usr/include/i386-gnu"};
+
+  ArrayRef<StringRef> MultiarchIncludeDirs;
+  switch (getTriple().getArch()) {
+  case llvm::Triple::x86:
+    MultiarchIncludeDirs = X86MultiarchIncludeDirs;
+    break;
+  default:
+    break;
+  }
+
+  for (StringRef Dir : MultiarchIncludeDirs) {
+    if (D.getVFS().exists(SysRoot + Dir)) {
+      addExternCSystemInclude(DriverArgs, CC1Args, SysRoot + Dir);
+      break;
+    }
+  }
+
+  // Add an include of '/include' directly. This isn't provided by default by
+  // system GCCs, but is often used with cross-compiling GCCs, and harmless to
+  // add even when Clang is acting as-if it were a system compiler.
+  addExternCSystemInclude(DriverArgs, CC1Args, SysRoot + "/include");
+
+  addExternCSystemInclude(DriverArgs, CC1Args, SysRoot + "/usr/include");
+}
Index: llvm-toolchain-7-7.0.1~+rc2/clang/lib/Driver/ToolChains/Hurd.h
===================================================================
--- /dev/null
+++ llvm-toolchain-7-7.0.1~+rc2/clang/lib/Driver/ToolChains/Hurd.h
@@ -0,0 +1,46 @@
+//===--- Hurd.h - Hurd ToolChain Implementations ----------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_Hurd_H
+#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_Hurd_H
+
+#include "Gnu.h"
+#include "clang/Driver/ToolChain.h"
+
+namespace clang {
+namespace driver {
+namespace toolchains {
+
+class LLVM_LIBRARY_VISIBILITY Hurd : public Generic_ELF {
+public:
+  Hurd(const Driver &D, const llvm::Triple &Triple,
+          const llvm::opt::ArgList &Args);
+
+  bool HasNativeLLVMSupport() const override;
+
+  void
+  AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
+                            llvm::opt::ArgStringList &CC1Args) const override;
+
+  virtual std::string computeSysRoot() const;
+
+  virtual std::string getDynamicLinker(const llvm::opt::ArgList &Args) const;
+
+  std::vector<std::string> ExtraOpts;
+
+protected:
+  Tool *buildAssembler() const override;
+  Tool *buildLinker() const override;
+};
+
+} // end namespace toolchains
+} // end namespace driver
+} // end namespace clang
+
+#endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_Hurd_H
Index: llvm-toolchain-7-7.0.1~+rc2/clang/lib/Frontend/InitHeaderSearch.cpp
===================================================================
--- llvm-toolchain-7-7.0.1~+rc2.orig/clang/lib/Frontend/InitHeaderSearch.cpp
+++ llvm-toolchain-7-7.0.1~+rc2/clang/lib/Frontend/InitHeaderSearch.cpp
@@ -260,6 +260,7 @@ void InitHeaderSearch::AddDefaultCInclud
 
   switch (os) {
   case llvm::Triple::Linux:
+  case llvm::Triple::Hurd:
   case llvm::Triple::Solaris:
     llvm_unreachable("Include management is handled in the driver.");
 
Index: llvm-toolchain-7-7.0.1~+rc2/clang/lib/Driver/ToolChains/Hurd.cpp
===================================================================
--- llvm-toolchain-7-7.0.1~+rc2.orig/clang/lib/Driver/ToolChains/Hurd.cpp
+++ llvm-toolchain-7-7.0.1~+rc2/clang/lib/Driver/ToolChains/Hurd.cpp
@@ -67,15 +67,102 @@ static StringRef getOSLibDir(const llvm:
   return Triple.isArch32Bit() ? "lib" : "lib64";
 }
 
+static void addMultilibsFilePaths(const Driver &D, const MultilibSet &Multilibs,
+                                  const Multilib &Multilib,
+                                  StringRef InstallPath,
+                                  ToolChain::path_list &Paths) {
+  if (const auto &PathsCallback = Multilibs.filePathsCallback())
+    for (const auto &Path : PathsCallback(Multilib))
+      addPathIfExists(D, InstallPath + Path, Paths);
+}
+
 Hurd::Hurd(const Driver &D, const llvm::Triple &Triple,
                  const ArgList &Args)
     : Generic_ELF(D, Triple, Args) {
+  GCCInstallation.init(Triple, Args);
+  Multilibs = GCCInstallation.getMultilibs();
   std::string SysRoot = computeSysRoot();
+
+  // Cross-compiling binutils and GCC installations (vanilla and openSUSE at
+  // least) put various tools in a triple-prefixed directory off of the parent
+  // of the GCC installation. We use the GCC triple here to ensure that we end
+  // up with tools that support the same amount of cross compiling as the
+  // detected GCC installation. For example, if we find a GCC installation
+  // targeting x86_64, but it is a bi-arch GCC installation, it can also be
+  // used to target i386.
+  // FIXME: This seems unlikely to be Linux- or Hurd-specific.
+  ToolChain::path_list &PPaths = getProgramPaths();
+  PPaths.push_back(Twine(GCCInstallation.getParentLibPath() + "/../" +
+                         GCCInstallation.getTriple().str() + "/bin")
+                       .str());
+
+#ifdef ENABLE_LINKER_BUILD_ID
+  ExtraOpts.push_back("--build-id");
+#endif
+
+  // The selection of paths to try here is designed to match the patterns which
+  // the GCC driver itself uses, as this is part of the GCC-compatible driver.
+  // This was determined by running GCC in a fake filesystem, creating all
+  // possible permutations of these directories, and seeing which ones it added
+  // to the link paths.
   path_list &Paths = getFilePaths();
 
   const std::string OSLibDir = getOSLibDir(Triple, Args);
   const std::string MultiarchTriple = getMultiarchTriple(D, Triple, SysRoot);
 
+  // Add the multilib suffixed paths where they are available.
+  if (GCCInstallation.isValid()) {
+    const llvm::Triple &GCCTriple = GCCInstallation.getTriple();
+    const std::string &LibPath = GCCInstallation.getParentLibPath();
+    const Multilib &Multilib = GCCInstallation.getMultilib();
+    const MultilibSet &Multilibs = GCCInstallation.getMultilibs();
+
+    // Add toolchain / multilib specific file paths.
+    addMultilibsFilePaths(D, Multilibs, Multilib,
+                          GCCInstallation.getInstallPath(), Paths);
+
+    // Sourcery CodeBench MIPS toolchain holds some libraries under
+    // a biarch-like suffix of the GCC installation.
+    addPathIfExists(D, GCCInstallation.getInstallPath() + Multilib.gccSuffix(),
+                    Paths);
+
+    // GCC cross compiling toolchains will install target libraries which ship
+    // as part of the toolchain under <prefix>/<triple>/<libdir> rather than as
+    // any part of the GCC installation in
+    // <prefix>/<libdir>/gcc/<triple>/<version>. This decision is somewhat
+    // debatable, but is the reality today. We need to search this tree even
+    // when we have a sysroot somewhere else. It is the responsibility of
+    // whomever is doing the cross build targeting a sysroot using a GCC
+    // installation that is *not* within the system root to ensure two things:
+    //
+    //  1) Any DSOs that are linked in from this tree or from the install path
+    //     above must be present on the system root and found via an
+    //     appropriate rpath.
+    //  2) There must not be libraries installed into
+    //     <prefix>/<triple>/<libdir> unless they should be preferred over
+    //     those within the system root.
+    //
+    // Note that this matches the GCC behavior. See the below comment for where
+    // Clang diverges from GCC's behavior.
+    addPathIfExists(D, LibPath + "/../" + GCCTriple.str() + "/lib/../" +
+                           OSLibDir + Multilib.osSuffix(),
+                    Paths);
+
+    // If the GCC installation we found is inside of the sysroot, we want to
+    // prefer libraries installed in the parent prefix of the GCC installation.
+    // It is important to *not* use these paths when the GCC installation is
+    // outside of the system root as that can pick up unintended libraries.
+    // This usually happens when there is an external cross compiler on the
+    // host system, and a more minimal sysroot available that is the target of
+    // the cross. Note that GCC does include some of these directories in some
+    // configurations but this seems somewhere between questionable and simply
+    // a bug.
+    if (StringRef(LibPath).startswith(SysRoot)) {
+      addPathIfExists(D, LibPath + "/" + MultiarchTriple, Paths);
+      addPathIfExists(D, LibPath + "/../" + OSLibDir, Paths);
+    }
+  }
+
   // Similar to the logic for GCC above, if we currently running Clang inside
   // of the requested system root, add its parent library paths to
   // those searched.
@@ -92,8 +179,40 @@ Hurd::Hurd(const Driver &D, const llvm::
   addPathIfExists(D, SysRoot + "/usr/lib/" + MultiarchTriple, Paths);
   addPathIfExists(D, SysRoot + "/usr/lib/../" + OSLibDir, Paths);
 
-  // If we are currently running Clang inside of the requested system root, add
-  // its parent library path to those searched.
+  // Try walking via the GCC triple path in case of biarch or multiarch GCC
+  // installations with strange symlinks.
+  if (GCCInstallation.isValid()) {
+    addPathIfExists(D,
+                    SysRoot + "/usr/lib/" + GCCInstallation.getTriple().str() +
+                        "/../../" + OSLibDir,
+                    Paths);
+
+    // Add the 'other' biarch variant path
+    Multilib BiarchSibling;
+    if (GCCInstallation.getBiarchSibling(BiarchSibling)) {
+      addPathIfExists(D, GCCInstallation.getInstallPath() +
+                             BiarchSibling.gccSuffix(),
+                      Paths);
+    }
+
+    // See comments above on the multilib variant for details of why this is
+    // included even from outside the sysroot.
+    const std::string &LibPath = GCCInstallation.getParentLibPath();
+    const llvm::Triple &GCCTriple = GCCInstallation.getTriple();
+    const Multilib &Multilib = GCCInstallation.getMultilib();
+    addPathIfExists(D, LibPath + "/../" + GCCTriple.str() + "/lib" +
+                           Multilib.osSuffix(),
+                    Paths);
+
+    // See comments above on the multilib variant for details of why this is
+    // only included from within the sysroot.
+    if (StringRef(LibPath).startswith(SysRoot))
+      addPathIfExists(D, LibPath, Paths);
+  }
+
+  // Similar to the logic for GCC above, if we are currently running Clang
+  // inside of the requested system root, add its parent library path to those
+  // searched.
   // FIXME: It's not clear whether we should use the driver's installed
   // directory ('Dir' below) or the ResourceDir.
   if (StringRef(D.Dir).startswith(SysRoot))
@@ -161,6 +280,16 @@ void Hurd::AddClangSystemIncludeArgs(con
   // Lacking those, try to detect the correct set of system includes for the
   // target triple.
 
+  // Add include directories specific to the selected multilib set and multilib.
+  if (GCCInstallation.isValid()) {
+    const auto &Callback = Multilibs.includeDirsCallback();
+    if (Callback) {
+      for (const auto &Path : Callback(GCCInstallation.getMultilib()))
+        addExternCSystemIncludeIfExists(
+            DriverArgs, CC1Args, GCCInstallation.getInstallPath() + Path);
+    }
+  }
+
   const StringRef X86MultiarchIncludeDirs[] = {
       "/usr/include/i386-gnu"};
 
@@ -187,3 +316,94 @@ void Hurd::AddClangSystemIncludeArgs(con
 
   addExternCSystemInclude(DriverArgs, CC1Args, SysRoot + "/usr/include");
 }
+
+static std::string DetectLibcxxIncludePath(StringRef base) {
+  std::error_code EC;
+  int MaxVersion = 0;
+  std::string MaxVersionString = "";
+  for (llvm::sys::fs::directory_iterator LI(base, EC), LE; !EC && LI != LE;
+       LI = LI.increment(EC)) {
+    StringRef VersionText = llvm::sys::path::filename(LI->path());
+    int Version;
+    if (VersionText[0] == 'v' &&
+        !VersionText.slice(1, StringRef::npos).getAsInteger(10, Version)) {
+      if (Version > MaxVersion) {
+        MaxVersion = Version;
+        MaxVersionString = VersionText;
+      }
+    }
+  }
+  return MaxVersion ? (base + "/" + MaxVersionString).str() : "";
+}
+
+void Hurd::addLibCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
+                                 llvm::opt::ArgStringList &CC1Args) const {
+  const std::string& SysRoot = computeSysRoot();
+  const std::string LibCXXIncludePathCandidates[] = {
+      DetectLibcxxIncludePath(getDriver().ResourceDir + "/include/c++"),
+      DetectLibcxxIncludePath(getDriver().Dir + "/../include/c++"),
+      // If this is a development, non-installed, clang, libcxx will
+      // not be found at ../include/c++ but it likely to be found at
+      // one of the following two locations:
+      DetectLibcxxIncludePath(SysRoot + "/usr/local/include/c++"),
+      DetectLibcxxIncludePath(SysRoot + "/usr/include/c++") };
+  for (const auto &IncludePath : LibCXXIncludePathCandidates) {
+    if (IncludePath.empty() || !getVFS().exists(IncludePath))
+      continue;
+    // Use the first candidate that exists.
+    addSystemInclude(DriverArgs, CC1Args, IncludePath);
+    return;
+  }
+}
+
+void Hurd::addLibStdCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
+                                    llvm::opt::ArgStringList &CC1Args) const {
+  // We need a detected GCC installation on Hurd to provide libstdc++'s
+  // headers.
+  if (!GCCInstallation.isValid())
+    return;
+
+  // By default, look for the C++ headers in an include directory adjacent to
+  // the lib directory of the GCC installation. Note that this is expect to be
+  // equivalent to '/usr/include/c++/X.Y' in almost all cases.
+  StringRef LibDir = GCCInstallation.getParentLibPath();
+  StringRef InstallDir = GCCInstallation.getInstallPath();
+  StringRef TripleStr = GCCInstallation.getTriple().str();
+  const Multilib &Multilib = GCCInstallation.getMultilib();
+  const std::string GCCMultiarchTriple = getMultiarchTriple(
+      getDriver(), GCCInstallation.getTriple(), getDriver().SysRoot);
+  const std::string TargetMultiarchTriple =
+      getMultiarchTriple(getDriver(), getTriple(), getDriver().SysRoot);
+  const GCCVersion &Version = GCCInstallation.getVersion();
+
+  // The primary search for libstdc++ supports multiarch variants.
+  if (addLibStdCXXIncludePaths(LibDir.str() + "/../include",
+                               "/c++/" + Version.Text, TripleStr,
+                               GCCMultiarchTriple, TargetMultiarchTriple,
+                               Multilib.includeSuffix(), DriverArgs, CC1Args))
+    return;
+
+  // Otherwise, fall back on a bunch of options which don't use multiarch
+  // layouts for simplicity.
+  const std::string LibStdCXXIncludePathCandidates[] = {
+      // Gentoo is weird and places its headers inside the GCC install,
+      // so if the first attempt to find the headers fails, try these patterns.
+      InstallDir.str() + "/include/g++-v" + Version.Text,
+      InstallDir.str() + "/include/g++-v" + Version.MajorStr + "." +
+          Version.MinorStr,
+      InstallDir.str() + "/include/g++-v" + Version.MajorStr,
+      // Android standalone toolchain has C++ headers in yet another place.
+      LibDir.str() + "/../" + TripleStr.str() + "/include/c++/" + Version.Text,
+      // Freescale SDK C++ headers are directly in <sysroot>/usr/include/c++,
+      // without a subdirectory corresponding to the gcc version.
+      LibDir.str() + "/../include/c++",
+  };
+
+  for (const auto &IncludePath : LibStdCXXIncludePathCandidates) {
+    if (addLibStdCXXIncludePaths(IncludePath, /*Suffix*/ "", TripleStr,
+                                 /*GCCMultiarchTriple*/ "",
+                                 /*TargetMultiarchTriple*/ "",
+                                 Multilib.includeSuffix(), DriverArgs, CC1Args))
+      break;
+  }
+}
Index: llvm-toolchain-7-7.0.1~+rc2/clang/lib/Driver/ToolChains/Hurd.h
===================================================================
--- llvm-toolchain-7-7.0.1~+rc2.orig/clang/lib/Driver/ToolChains/Hurd.h
+++ llvm-toolchain-7-7.0.1~+rc2/clang/lib/Driver/ToolChains/Hurd.h
@@ -25,6 +25,12 @@ public:
   void
   AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
                             llvm::opt::ArgStringList &CC1Args) const override;
+  void addLibCxxIncludePaths(
+      const llvm::opt::ArgList &DriverArgs,
+      llvm::opt::ArgStringList &CC1Args) const override;
+  void addLibStdCxxIncludePaths(
+      const llvm::opt::ArgList &DriverArgs,
+      llvm::opt::ArgStringList &CC1Args) const override;
 
   virtual std::string computeSysRoot() const;
 
Index: llvm-toolchain-7-7.0.1~+rc2/libcxx/src/filesystem/operations.cpp
===================================================================
--- llvm-toolchain-7-7.0.1~+rc2.orig/libcxx/src/filesystem/operations.cpp
+++ llvm-toolchain-7-7.0.1~+rc2/libcxx/src/filesystem/operations.cpp
@@ -526,6 +526,7 @@ path __absolute(const path& p, error_cod
   return __do_absolute(p, &cwd, ec);
 }
 
+#define PATH_MAX 4096
 path __canonical(path const& orig_p, error_code* ec) {
   path cwd;
   ErrorHandler<path> err("canonical", ec, &orig_p, &cwd);

Reply via email to