[cfe-commits] r143838 - in /cfe/trunk/lib/Driver: ToolChains.cpp ToolChains.h

Chandler Carruth chandlerc at gmail.com
Sat Nov 5 15:07:51 PDT 2011


Author: chandlerc
Date: Sat Nov  5 17:07:51 2011
New Revision: 143838

URL: http://llvm.org/viewvc/llvm-project?rev=143838&view=rev
Log:
Move the GCC installation detection helper a member of the Linux
toolchain instead of merely using it in the constructor. This will allow
us to query it when building include paths as well as the file search
paths built in the constructor. I've lifted as little of it as I could
into the header file.

Eventually this will likely sink down into some of the Generic
toolchains and be used on more platforms, but I'm starting on Linux so
I can work out all the APIs needed there, where it is easiest to test
and we have the most pressing need.

Modified:
    cfe/trunk/lib/Driver/ToolChains.cpp
    cfe/trunk/lib/Driver/ToolChains.h

Modified: cfe/trunk/lib/Driver/ToolChains.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/ToolChains.cpp?rev=143838&r1=143837&r2=143838&view=diff
==============================================================================
--- cfe/trunk/lib/Driver/ToolChains.cpp (original)
+++ cfe/trunk/lib/Driver/ToolChains.cpp Sat Nov  5 17:07:51 2011
@@ -1527,253 +1527,221 @@
   return false;
 }
 
-namespace {
-/// \brief This is a class to find a viable GCC installation for Clang to use.
+/// \brief Struct to store and manipulate GCC versions.
 ///
-/// This class tries to find a GCC installation on the system, and report
-/// information about it. It starts from the host information provided to the
-/// Driver, and has logic for fuzzing that where appropriate.
-class GCCInstallationDetector {
-  /// \brief Struct to store and manipulate GCC versions.
-  ///
-  /// We rely on assumptions about the form and structure of GCC version
-  /// numbers: they consist of at most three '.'-separated components, and each
-  /// component is a non-negative integer.
-  struct GCCVersion {
-    unsigned Major, Minor, Patch;
-
-    static GCCVersion Parse(StringRef VersionText) {
-      const GCCVersion BadVersion = {0, 0, 0};
-      std::pair<StringRef, StringRef> First = VersionText.split('.');
-      std::pair<StringRef, StringRef> Second = First.second.split('.');
-
-      GCCVersion GoodVersion = {0, 0, 0};
-      if (First.first.getAsInteger(10, GoodVersion.Major))
-        return BadVersion;
-      if (Second.first.getAsInteger(10, GoodVersion.Minor))
-        return BadVersion;
-      // We accept a number, or a string for the patch version, in case there
-      // is a strang suffix, or other mangling: '4.1.x', '4.1.2-rc3'. When it
-      // isn't a number, we just use '0' as the number but accept it.
-      if (Second.first.getAsInteger(10, GoodVersion.Patch))
-        GoodVersion.Patch = 0;
-      return GoodVersion;
-    }
-
-    bool operator<(const GCCVersion &RHS) const {
-      if (Major < RHS.Major) return true;
-      if (Major > RHS.Major) return false;
-      if (Minor < RHS.Minor) return true;
-      if (Minor > RHS.Minor) return false;
-      return Patch < RHS.Patch;
-    }
-    bool operator>(const GCCVersion &RHS) const { return RHS < *this; }
-    bool operator<=(const GCCVersion &RHS) const { return !(*this > RHS); }
-    bool operator>=(const GCCVersion &RHS) const { return !(*this < RHS); }
-  };
-
-  bool IsValid;
-  std::string GccTriple;
-
-  // FIXME: These might be better as path objects.
-  std::string GccInstallPath;
-  std::string GccParentLibPath;
-
-  llvm::SmallString<128> CxxIncludeRoot;
-
-public:
-  /// \brief Construct a GCCInstallationDetector from the driver.
-  ///
-  /// This performs all of the autodetection and sets up the various paths.
-  /// Once constructed, a GCCInstallation is esentially immutable.
-  GCCInstallationDetector(const Driver &D)
-    : IsValid(false),
-      GccTriple(D.DefaultHostTriple),
-      CxxIncludeRoot(CXX_INCLUDE_ROOT) {
-    // FIXME: Using CXX_INCLUDE_ROOT is here is a bit of a hack, but
-    // avoids adding yet another option to configure/cmake.
-    // It would probably be cleaner to break it in two variables
-    // CXX_GCC_ROOT with just /foo/bar
-    // CXX_GCC_VER with 4.5.2
-    // Then we would have
-    // CXX_INCLUDE_ROOT = CXX_GCC_ROOT/include/c++/CXX_GCC_VER
-    // and this function would return
-    // CXX_GCC_ROOT/lib/gcc/CXX_INCLUDE_ARCH/CXX_GCC_VER
-    if (CxxIncludeRoot != "") {
-      // This is of the form /foo/bar/include/c++/4.5.2/
-      if (CxxIncludeRoot.back() == '/')
-        llvm::sys::path::remove_filename(CxxIncludeRoot); // remove the /
-      StringRef Version = llvm::sys::path::filename(CxxIncludeRoot);
-      llvm::sys::path::remove_filename(CxxIncludeRoot); // remove the version
-      llvm::sys::path::remove_filename(CxxIncludeRoot); // remove the c++
-      llvm::sys::path::remove_filename(CxxIncludeRoot); // remove the include
-      GccInstallPath = CxxIncludeRoot.str();
-      GccInstallPath.append("/lib/gcc/");
-      GccInstallPath.append(CXX_INCLUDE_ARCH);
-      GccInstallPath.append("/");
-      GccInstallPath.append(Version);
-      GccParentLibPath = GccInstallPath + "/../../..";
-      IsValid = true;
-      return;
-    }
+/// We rely on assumptions about the form and structure of GCC version
+/// numbers: they consist of at most three '.'-separated components, and each
+/// component is a non-negative integer.
+struct Linux::GCCVersion {
+  unsigned Major, Minor, Patch;
+
+  static GCCVersion Parse(StringRef VersionText) {
+    const GCCVersion BadVersion = {0, 0, 0};
+    std::pair<StringRef, StringRef> First = VersionText.split('.');
+    std::pair<StringRef, StringRef> Second = First.second.split('.');
+
+    GCCVersion GoodVersion = {0, 0, 0};
+    if (First.first.getAsInteger(10, GoodVersion.Major))
+      return BadVersion;
+    if (Second.first.getAsInteger(10, GoodVersion.Minor))
+      return BadVersion;
+    // We accept a number, or a string for the patch version, in case there
+    // is a strang suffix, or other mangling: '4.1.x', '4.1.2-rc3'. When it
+    // isn't a number, we just use '0' as the number but accept it.
+    if (Second.first.getAsInteger(10, GoodVersion.Patch))
+      GoodVersion.Patch = 0;
+    return GoodVersion;
+  }
+
+  bool operator<(const GCCVersion &RHS) const {
+    if (Major < RHS.Major) return true;
+    if (Major > RHS.Major) return false;
+    if (Minor < RHS.Minor) return true;
+    if (Minor > RHS.Minor) return false;
+    return Patch < RHS.Patch;
+  }
+  bool operator>(const GCCVersion &RHS) const { return RHS < *this; }
+  bool operator<=(const GCCVersion &RHS) const { return !(*this > RHS); }
+  bool operator>=(const GCCVersion &RHS) const { return !(*this < RHS); }
+};
 
-    llvm::Triple::ArchType HostArch = llvm::Triple(GccTriple).getArch();
-    // The library directories which may contain GCC installations.
-    SmallVector<StringRef, 4> CandidateLibDirs;
-    // The compatible GCC triples for this particular architecture.
-    SmallVector<StringRef, 10> CandidateTriples;
-    CollectLibDirsAndTriples(HostArch, CandidateLibDirs, CandidateTriples);
-
-    // Always include the default host triple as the final fallback if no
-    // specific triple is detected.
-    CandidateTriples.push_back(D.DefaultHostTriple);
-
-    // Compute the set of prefixes for our search.
-    SmallVector<std::string, 8> Prefixes(D.PrefixDirs.begin(),
-                                         D.PrefixDirs.end());
-    Prefixes.push_back(D.SysRoot);
-    Prefixes.push_back(D.SysRoot + "/usr");
-    Prefixes.push_back(D.InstalledDir + "/..");
-
-    // Loop over the various components which exist and select the best GCC
-    // installation available. GCC installs are ranked by version number.
-    GCCVersion BestVersion = {0, 0, 0};
-    for (unsigned i = 0, ie = Prefixes.size(); i < ie; ++i) {
-      if (!PathExists(Prefixes[i]))
-        continue;
-      for (unsigned j = 0, je = CandidateLibDirs.size(); j < je; ++j) {
-        const std::string LibDir = Prefixes[i] + CandidateLibDirs[j].str();
-        if (!PathExists(LibDir))
-          continue;
-        for (unsigned k = 0, ke = CandidateTriples.size(); k < ke; ++k)
-          ScanLibDirForGCCTriple(LibDir, CandidateTriples[k], BestVersion);
-      }
-    }
+/// \brief Construct a GCCInstallationDetector from the driver.
+///
+/// This performs all of the autodetection and sets up the various paths.
+/// Once constructed, a GCCInstallation is esentially immutable.
+Linux::GCCInstallationDetector::GCCInstallationDetector(const Driver &D)
+  : IsValid(false),
+    GccTriple(D.DefaultHostTriple),
+    CxxIncludeRoot(CXX_INCLUDE_ROOT) {
+  // FIXME: Using CXX_INCLUDE_ROOT is here is a bit of a hack, but
+  // avoids adding yet another option to configure/cmake.
+  // It would probably be cleaner to break it in two variables
+  // CXX_GCC_ROOT with just /foo/bar
+  // CXX_GCC_VER with 4.5.2
+  // Then we would have
+  // CXX_INCLUDE_ROOT = CXX_GCC_ROOT/include/c++/CXX_GCC_VER
+  // and this function would return
+  // CXX_GCC_ROOT/lib/gcc/CXX_INCLUDE_ARCH/CXX_GCC_VER
+  if (CxxIncludeRoot != "") {
+    // This is of the form /foo/bar/include/c++/4.5.2/
+    if (CxxIncludeRoot.back() == '/')
+      llvm::sys::path::remove_filename(CxxIncludeRoot); // remove the /
+    StringRef Version = llvm::sys::path::filename(CxxIncludeRoot);
+    llvm::sys::path::remove_filename(CxxIncludeRoot); // remove the version
+    llvm::sys::path::remove_filename(CxxIncludeRoot); // remove the c++
+    llvm::sys::path::remove_filename(CxxIncludeRoot); // remove the include
+    GccInstallPath = CxxIncludeRoot.str();
+    GccInstallPath.append("/lib/gcc/");
+    GccInstallPath.append(CXX_INCLUDE_ARCH);
+    GccInstallPath.append("/");
+    GccInstallPath.append(Version);
+    GccParentLibPath = GccInstallPath + "/../../..";
+    IsValid = true;
+    return;
   }
 
-  /// \brief Check whether we detected a valid GCC install.
-  bool isValid() const { return IsValid; }
-
-  /// \brief Get the GCC triple for the detected install.
-  const std::string &getTriple() const { return GccTriple; }
-
-  /// \brief Get the detected GCC installation path.
-  const std::string &getInstallPath() const { return GccInstallPath; }
-
-  /// \brief Get the detected GCC parent lib path.
-  const std::string &getParentLibPath() const { return GccParentLibPath; }
-
-private:
-  static void CollectLibDirsAndTriples(llvm::Triple::ArchType HostArch,
-                                       SmallVectorImpl<StringRef> &LibDirs,
-                                       SmallVectorImpl<StringRef> &Triples) {
-    if (HostArch == llvm::Triple::arm || HostArch == llvm::Triple::thumb) {
-      static const char *const ARMLibDirs[] = { "/lib" };
-      static const char *const ARMTriples[] = { "arm-linux-gnueabi" };
-      LibDirs.append(ARMLibDirs, ARMLibDirs + llvm::array_lengthof(ARMLibDirs));
-      Triples.append(ARMTriples, ARMTriples + llvm::array_lengthof(ARMTriples));
-    } else if (HostArch == llvm::Triple::x86_64) {
-      static const char *const X86_64LibDirs[] = { "/lib64", "/lib" };
-      static const char *const X86_64Triples[] = {
-        "x86_64-linux-gnu",
-        "x86_64-unknown-linux-gnu",
-        "x86_64-pc-linux-gnu",
-        "x86_64-redhat-linux6E",
-        "x86_64-redhat-linux",
-        "x86_64-suse-linux",
-        "x86_64-manbo-linux-gnu",
-        "x86_64-linux-gnu",
-        "x86_64-slackware-linux"
-      };
-      LibDirs.append(X86_64LibDirs,
-                     X86_64LibDirs + llvm::array_lengthof(X86_64LibDirs));
-      Triples.append(X86_64Triples,
-                     X86_64Triples + llvm::array_lengthof(X86_64Triples));
-    } else if (HostArch == llvm::Triple::x86) {
-      static const char *const X86LibDirs[] = { "/lib32", "/lib" };
-      static const char *const X86Triples[] = {
-        "i686-linux-gnu",
-        "i386-linux-gnu",
-        "i686-pc-linux-gnu",
-        "i486-linux-gnu",
-        "i686-redhat-linux",
-        "i386-redhat-linux",
-        "i586-suse-linux",
-        "i486-slackware-linux"
-      };
-      LibDirs.append(X86LibDirs, X86LibDirs + llvm::array_lengthof(X86LibDirs));
-      Triples.append(X86Triples, X86Triples + llvm::array_lengthof(X86Triples));
-    } else if (HostArch == llvm::Triple::ppc) {
-      static const char *const PPCLibDirs[] = { "/lib32", "/lib" };
-      static const char *const PPCTriples[] = {
-        "powerpc-linux-gnu",
-        "powerpc-unknown-linux-gnu"
-      };
-      LibDirs.append(PPCLibDirs, PPCLibDirs + llvm::array_lengthof(PPCLibDirs));
-      Triples.append(PPCTriples, PPCTriples + llvm::array_lengthof(PPCTriples));
-    } else if (HostArch == llvm::Triple::ppc64) {
-      static const char *const PPC64LibDirs[] = { "/lib64", "/lib" };
-      static const char *const PPC64Triples[] = {
-        "powerpc64-unknown-linux-gnu"
-      };
-      LibDirs.append(PPC64LibDirs,
-                     PPC64LibDirs + llvm::array_lengthof(PPC64LibDirs));
-      Triples.append(PPC64Triples,
-                     PPC64Triples + llvm::array_lengthof(PPC64Triples));
+  llvm::Triple::ArchType HostArch = llvm::Triple(GccTriple).getArch();
+  // The library directories which may contain GCC installations.
+  SmallVector<StringRef, 4> CandidateLibDirs;
+  // The compatible GCC triples for this particular architecture.
+  SmallVector<StringRef, 10> CandidateTriples;
+  CollectLibDirsAndTriples(HostArch, CandidateLibDirs, CandidateTriples);
+
+  // Always include the default host triple as the final fallback if no
+  // specific triple is detected.
+  CandidateTriples.push_back(D.DefaultHostTriple);
+
+  // Compute the set of prefixes for our search.
+  SmallVector<std::string, 8> Prefixes(D.PrefixDirs.begin(),
+                                       D.PrefixDirs.end());
+  Prefixes.push_back(D.SysRoot);
+  Prefixes.push_back(D.SysRoot + "/usr");
+  Prefixes.push_back(D.InstalledDir + "/..");
+
+  // Loop over the various components which exist and select the best GCC
+  // installation available. GCC installs are ranked by version number.
+  GCCVersion BestVersion = {0, 0, 0};
+  for (unsigned i = 0, ie = Prefixes.size(); i < ie; ++i) {
+    if (!PathExists(Prefixes[i]))
+      continue;
+    for (unsigned j = 0, je = CandidateLibDirs.size(); j < je; ++j) {
+      const std::string LibDir = Prefixes[i] + CandidateLibDirs[j].str();
+      if (!PathExists(LibDir))
+        continue;
+      for (unsigned k = 0, ke = CandidateTriples.size(); k < ke; ++k)
+        ScanLibDirForGCCTriple(LibDir, CandidateTriples[k], BestVersion);
     }
   }
+}
 
-  void ScanLibDirForGCCTriple(const std::string &LibDir,
-                              StringRef CandidateTriple,
-                              GCCVersion &BestVersion) {
-    // There are various different suffixes involving the triple we
-    // check for. We also record what is necessary to walk from each back
-    // up to the lib directory.
-    const std::string Suffixes[] = {
-      "/gcc/" + CandidateTriple.str(),
-      "/" + CandidateTriple.str() + "/gcc/" + CandidateTriple.str(),
-
-      // Ubuntu has a strange mis-matched pair of triples that this happens to
-      // match.
-      // FIXME: It may be worthwhile to generalize this and look for a second
-      // triple.
-      "/" + CandidateTriple.str() + "/gcc/i686-linux-gnu"
+/*static*/ void Linux::GCCInstallationDetector::CollectLibDirsAndTriples(
+    llvm::Triple::ArchType HostArch, SmallVectorImpl<StringRef> &LibDirs,
+    SmallVectorImpl<StringRef> &Triples) {
+  if (HostArch == llvm::Triple::arm || HostArch == llvm::Triple::thumb) {
+    static const char *const ARMLibDirs[] = { "/lib" };
+    static const char *const ARMTriples[] = { "arm-linux-gnueabi" };
+    LibDirs.append(ARMLibDirs, ARMLibDirs + llvm::array_lengthof(ARMLibDirs));
+    Triples.append(ARMTriples, ARMTriples + llvm::array_lengthof(ARMTriples));
+  } else if (HostArch == llvm::Triple::x86_64) {
+    static const char *const X86_64LibDirs[] = { "/lib64", "/lib" };
+    static const char *const X86_64Triples[] = {
+      "x86_64-linux-gnu",
+      "x86_64-unknown-linux-gnu",
+      "x86_64-pc-linux-gnu",
+      "x86_64-redhat-linux6E",
+      "x86_64-redhat-linux",
+      "x86_64-suse-linux",
+      "x86_64-manbo-linux-gnu",
+      "x86_64-linux-gnu",
+      "x86_64-slackware-linux"
     };
-    const std::string InstallSuffixes[] = {
-      "/../../..",
-      "/../../../..",
-      "/../../../.."
+    LibDirs.append(X86_64LibDirs,
+                   X86_64LibDirs + llvm::array_lengthof(X86_64LibDirs));
+    Triples.append(X86_64Triples,
+                   X86_64Triples + llvm::array_lengthof(X86_64Triples));
+  } else if (HostArch == llvm::Triple::x86) {
+    static const char *const X86LibDirs[] = { "/lib32", "/lib" };
+    static const char *const X86Triples[] = {
+      "i686-linux-gnu",
+      "i386-linux-gnu",
+      "i686-pc-linux-gnu",
+      "i486-linux-gnu",
+      "i686-redhat-linux",
+      "i386-redhat-linux",
+      "i586-suse-linux",
+      "i486-slackware-linux"
     };
-    // Only look at the final, weird Ubuntu suffix for i386-linux-gnu.
-    const unsigned NumSuffixes = (llvm::array_lengthof(Suffixes) -
-                                  (CandidateTriple != "i386-linux-gnu"));
-    for (unsigned i = 0; i < NumSuffixes; ++i) {
-      StringRef Suffix = Suffixes[i];
-      llvm::error_code EC;
-      for (llvm::sys::fs::directory_iterator LI(LibDir + Suffix, EC), LE;
-           !EC && LI != LE; LI = LI.increment(EC)) {
-        StringRef VersionText = llvm::sys::path::filename(LI->path());
-        GCCVersion CandidateVersion = GCCVersion::Parse(VersionText);
-        static const GCCVersion MinVersion = { 4, 1, 1 };
-        if (CandidateVersion < MinVersion)
-          continue;
-        if (CandidateVersion <= BestVersion)
-          continue;
-        if (!PathExists(LI->path() + "/crtbegin.o"))
-          continue;
+    LibDirs.append(X86LibDirs, X86LibDirs + llvm::array_lengthof(X86LibDirs));
+    Triples.append(X86Triples, X86Triples + llvm::array_lengthof(X86Triples));
+  } else if (HostArch == llvm::Triple::ppc) {
+    static const char *const PPCLibDirs[] = { "/lib32", "/lib" };
+    static const char *const PPCTriples[] = {
+      "powerpc-linux-gnu",
+      "powerpc-unknown-linux-gnu"
+    };
+    LibDirs.append(PPCLibDirs, PPCLibDirs + llvm::array_lengthof(PPCLibDirs));
+    Triples.append(PPCTriples, PPCTriples + llvm::array_lengthof(PPCTriples));
+  } else if (HostArch == llvm::Triple::ppc64) {
+    static const char *const PPC64LibDirs[] = { "/lib64", "/lib" };
+    static const char *const PPC64Triples[] = {
+      "powerpc64-unknown-linux-gnu"
+    };
+    LibDirs.append(PPC64LibDirs,
+                   PPC64LibDirs + llvm::array_lengthof(PPC64LibDirs));
+    Triples.append(PPC64Triples,
+                   PPC64Triples + llvm::array_lengthof(PPC64Triples));
+  }
+}
 
-        BestVersion = CandidateVersion;
-        GccTriple = CandidateTriple.str();
-        // FIXME: We hack together the directory name here instead of
-        // using LI to ensure stable path separators across Windows and
-        // Linux.
-        GccInstallPath = LibDir + Suffixes[i] + "/" + VersionText.str();
-        GccParentLibPath = GccInstallPath + InstallSuffixes[i];
-        IsValid = true;
-      }
+void Linux::GCCInstallationDetector::ScanLibDirForGCCTriple(
+    const std::string &LibDir, StringRef CandidateTriple,
+    GCCVersion &BestVersion) {
+  // There are various different suffixes involving the triple we
+  // check for. We also record what is necessary to walk from each back
+  // up to the lib directory.
+  const std::string Suffixes[] = {
+    "/gcc/" + CandidateTriple.str(),
+    "/" + CandidateTriple.str() + "/gcc/" + CandidateTriple.str(),
+
+    // Ubuntu has a strange mis-matched pair of triples that this happens to
+    // match.
+    // FIXME: It may be worthwhile to generalize this and look for a second
+    // triple.
+    "/" + CandidateTriple.str() + "/gcc/i686-linux-gnu"
+  };
+  const std::string InstallSuffixes[] = {
+    "/../../..",
+    "/../../../..",
+    "/../../../.."
+  };
+  // Only look at the final, weird Ubuntu suffix for i386-linux-gnu.
+  const unsigned NumSuffixes = (llvm::array_lengthof(Suffixes) -
+                                (CandidateTriple != "i386-linux-gnu"));
+  for (unsigned i = 0; i < NumSuffixes; ++i) {
+    StringRef Suffix = Suffixes[i];
+    llvm::error_code EC;
+    for (llvm::sys::fs::directory_iterator LI(LibDir + Suffix, EC), LE;
+         !EC && LI != LE; LI = LI.increment(EC)) {
+      StringRef VersionText = llvm::sys::path::filename(LI->path());
+      GCCVersion CandidateVersion = GCCVersion::Parse(VersionText);
+      static const GCCVersion MinVersion = { 4, 1, 1 };
+      if (CandidateVersion < MinVersion)
+        continue;
+      if (CandidateVersion <= BestVersion)
+        continue;
+      if (!PathExists(LI->path() + "/crtbegin.o"))
+        continue;
+
+      BestVersion = CandidateVersion;
+      GccTriple = CandidateTriple.str();
+      // FIXME: We hack together the directory name here instead of
+      // using LI to ensure stable path separators across Windows and
+      // Linux.
+      GccInstallPath = LibDir + Suffixes[i] + "/" + VersionText.str();
+      GccParentLibPath = GccInstallPath + InstallSuffixes[i];
+      IsValid = true;
     }
   }
-};
 }
 
 static void addPathIfExists(const std::string &Path,
@@ -1811,11 +1779,10 @@
 }
 
 Linux::Linux(const HostInfo &Host, const llvm::Triple &Triple)
-  : Generic_ELF(Host, Triple) {
+  : Generic_ELF(Host, Triple), GCCInstallation(getDriver()) {
   llvm::Triple::ArchType Arch =
     llvm::Triple(getDriver().DefaultHostTriple).getArch();
   const std::string &SysRoot = getDriver().SysRoot;
-  GCCInstallationDetector GCCInstallation(getDriver());
 
   // OpenSuse stores the linker with the compiler, add that to the search
   // path.

Modified: cfe/trunk/lib/Driver/ToolChains.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/ToolChains.h?rev=143838&r1=143837&r2=143838&view=diff
==============================================================================
--- cfe/trunk/lib/Driver/ToolChains.h (original)
+++ cfe/trunk/lib/Driver/ToolChains.h Sat Nov  5 17:07:51 2011
@@ -372,6 +372,52 @@
 };
 
 class LLVM_LIBRARY_VISIBILITY Linux : public Generic_ELF {
+  struct GCCVersion;
+
+  /// \brief This is a class to find a viable GCC installation for Clang to
+  /// use.
+  ///
+  /// This class tries to find a GCC installation on the system, and report
+  /// information about it. It starts from the host information provided to the
+  /// Driver, and has logic for fuzzing that where appropriate.
+  class GCCInstallationDetector {
+
+    bool IsValid;
+    std::string GccTriple;
+
+    // FIXME: These might be better as path objects.
+    std::string GccInstallPath;
+    std::string GccParentLibPath;
+
+    llvm::SmallString<128> CxxIncludeRoot;
+
+  public:
+    GCCInstallationDetector(const Driver &D);
+
+    /// \brief Check whether we detected a valid GCC install.
+    bool isValid() const { return IsValid; }
+
+    /// \brief Get the GCC triple for the detected install.
+    const std::string &getTriple() const { return GccTriple; }
+
+    /// \brief Get the detected GCC installation path.
+    const std::string &getInstallPath() const { return GccInstallPath; }
+
+    /// \brief Get the detected GCC parent lib path.
+    const std::string &getParentLibPath() const { return GccParentLibPath; }
+
+  private:
+    static void CollectLibDirsAndTriples(llvm::Triple::ArchType HostArch,
+                                         SmallVectorImpl<StringRef> &LibDirs,
+                                         SmallVectorImpl<StringRef> &Triples);
+
+    void ScanLibDirForGCCTriple(const std::string &LibDir,
+                                StringRef CandidateTriple,
+                                GCCVersion &BestVersion);
+  };
+
+  GCCInstallationDetector GCCInstallation;
+
 public:
   Linux(const HostInfo &Host, const llvm::Triple& Triple);
 





More information about the cfe-commits mailing list