Commit d2cd7c59 authored by Bill Wendling's avatar Bill Wendling
Browse files

Merging r216531:

------------------------------------------------------------------------
r216531 | chandlerc | 2014-08-27 01:41:41 -0700 (Wed, 27 Aug 2014) | 22 lines

Significantly fix Clang's header search for Ubuntu (and possibly other
modern Debian-based distributions) due to on-going multiarch madness.

It appears that when the multiarch heeader search support went into the
clang driver, it went in in a quite bad state. The order of includes
completely failed to match the order exhibited by GCC, and in a specific
case -- when the GCC triple and the multiarch triple don't match as with
i686-linux-gnu and i386-linux-gnu -- we would absolutely fail to find
the libstdc++ target-specific header files.

I assume that folks who have been using Clang on Ubuntu 32-bit systems
have been applying weird patches to hack around this. I can't imagine
how else it could have worked. This was originally reported by a 64-bit
operating system user who had a 32-bit crosscompiler installed. We tried
to use that rather than the bi-arch support of the 64-bit compiler, but
failed due to the triple differences.

I've corrected all the wrong orderings in the existing tests and added
a specific test for the multiarch triple strings that are different in
a significant way. This should significantly improve the usability of
Clang when checked out vanilla from upstream onto Ubuntu machines with
an i686 GCC installation for whatever reason.
------------------------------------------------------------------------

llvm-svn: 216587
parent 76d25814
Loading
Loading
Loading
Loading
+40 −24
Original line number Diff line number Diff line
@@ -3386,32 +3386,39 @@ void Linux::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
  addExternCSystemInclude(DriverArgs, CC1Args, SysRoot + "/usr/include");
}

/// \brief Helper to add the three variant paths for a libstdc++ installation.
/*static*/ bool Linux::addLibStdCXXIncludePaths(Twine Base, Twine TargetArchDir,
                                                const ArgList &DriverArgs,
                                                ArgStringList &CC1Args) {
  if (!llvm::sys::fs::exists(Base))
    return false;
  addSystemInclude(DriverArgs, CC1Args, Base);
  addSystemInclude(DriverArgs, CC1Args, Base + "/" + TargetArchDir);
  addSystemInclude(DriverArgs, CC1Args, Base + "/backward");
  return true;
}

/// \brief Helper to add an extra variant path for an (Ubuntu) multilib
/// libstdc++ installation.
/// \brief Helper to add the variant paths of a libstdc++ installation.
/*static*/ bool Linux::addLibStdCXXIncludePaths(Twine Base, Twine Suffix,
                                                Twine TargetArchDir,
                                                StringRef GCCTriple,
                                                StringRef GCCMultiarchTriple,
                                                StringRef TargetMultiarchTriple,
                                                Twine IncludeSuffix,
                                                const ArgList &DriverArgs,
                                                ArgStringList &CC1Args) {
  if (!addLibStdCXXIncludePaths(Base + Suffix,
                                TargetArchDir + IncludeSuffix,
                                DriverArgs, CC1Args))
  if (!llvm::sys::fs::exists(Base))
    return false;

  addSystemInclude(DriverArgs, CC1Args, Base + "/" + TargetArchDir + Suffix
                   + IncludeSuffix);
  addSystemInclude(DriverArgs, CC1Args, Base + Suffix);

  // The vanilla GCC layout of libstdc++ headers uses a triple subdirectory. If
  // that path exists or we have neither a GCC nor target multiarch triple, use
  // this vanilla search path.
  if ((GCCMultiarchTriple.empty() && TargetMultiarchTriple.empty()) ||
      llvm::sys::fs::exists(Base + Suffix + "/" + GCCTriple + IncludeSuffix)) {
    addSystemInclude(DriverArgs, CC1Args,
                     Base + Suffix + "/" + GCCTriple + IncludeSuffix);
  } else {
    // Otherwise try to use multiarch naming schemes which have normalized the
    // triples and put the triple before the suffix.
    //
    // GCC surprisingly uses *both* the GCC triple with a multilib suffix and
    // the target triple, so we support that here.
    addSystemInclude(DriverArgs, CC1Args,
                     Base + "/" + GCCMultiarchTriple + Suffix + IncludeSuffix);
    addSystemInclude(DriverArgs, CC1Args,
                     Base + "/" + TargetMultiarchTriple + Suffix);
  }

  addSystemInclude(DriverArgs, CC1Args, Base + Suffix + "/backward");
  return true;
}

@@ -3455,13 +3462,21 @@ void Linux::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
  StringRef InstallDir = GCCInstallation.getInstallPath();
  StringRef TripleStr = GCCInstallation.getTriple().str();
  const Multilib &Multilib = GCCInstallation.getMultilib();
  const std::string GCCMultiarchTriple =
      getMultiarchTriple(GCCInstallation.getTriple(), getDriver().SysRoot);
  const std::string TargetMultiarchTriple =
      getMultiarchTriple(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,
                               "/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.
@@ -3476,9 +3491,10 @@ void Linux::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
  };

  for (const auto &IncludePath : LibStdCXXIncludePathCandidates) {
    if (addLibStdCXXIncludePaths(IncludePath,
                                 TripleStr + Multilib.includeSuffix(),
                                 DriverArgs, CC1Args))
    if (addLibStdCXXIncludePaths(IncludePath, /*Suffix*/ "", TripleStr,
                                 /*GCCMultiarchTriple*/ "",
                                 /*TargetMultiarchTriple*/ "",
                                 Multilib.includeSuffix(), DriverArgs, CC1Args))
      break;
  }
}
+4 −4
Original line number Diff line number Diff line
@@ -678,10 +678,10 @@ protected:

private:
  static bool addLibStdCXXIncludePaths(Twine Base, Twine Suffix,
                                       Twine TargetArchDir, Twine IncludeSuffix,
                                       const llvm::opt::ArgList &DriverArgs,
                                       llvm::opt::ArgStringList &CC1Args);
  static bool addLibStdCXXIncludePaths(Twine Base, Twine TargetArchDir,
                                       StringRef GCCTriple,
                                       StringRef GCCMultiarchTriple,
                                       StringRef TargetMultiarchTriple,
                                       Twine IncludeSuffix,
                                       const llvm::opt::ArgList &DriverArgs,
                                       llvm::opt::ArgStringList &CC1Args);

+0 −0

Empty file added.

+0 −0

Empty file added.

Loading