diff options
author | Michal Gorny <mgorny@gentoo.org> | 2016-11-28 21:11:14 +0000 |
---|---|---|
committer | Michal Gorny <mgorny@gentoo.org> | 2016-11-28 21:11:14 +0000 |
commit | 67e199eb32633f9f8dfd5e982063156c98d2358b (patch) | |
tree | 0d78590653fb6eccb07b88d4e329855c6c898c3b /clang/lib/Driver/Distro.cpp | |
parent | 08ebbcebb984b115ad1feb5984306f46cacdc616 (diff) | |
download | bcm5719-llvm-67e199eb32633f9f8dfd5e982063156c98d2358b.tar.gz bcm5719-llvm-67e199eb32633f9f8dfd5e982063156c98d2358b.zip |
[Driver] Refactor distro detection & classification as a separate API
Refactor the Distro enum along with helper functions into a full-fledged
Distro class, inspired by llvm::Triple, and make it a public API.
The new class wraps the enum with necessary comparison operators, adding
the convenience Is*() methods and a constructor performing
the detection. The public API is needed to run the unit tests (D25869).
Differential Revision: https://reviews.llvm.org/D25949
llvm-svn: 288060
Diffstat (limited to 'clang/lib/Driver/Distro.cpp')
-rw-r--r-- | clang/lib/Driver/Distro.cpp | 131 |
1 files changed, 131 insertions, 0 deletions
diff --git a/clang/lib/Driver/Distro.cpp b/clang/lib/Driver/Distro.cpp new file mode 100644 index 00000000000..7a12643405d --- /dev/null +++ b/clang/lib/Driver/Distro.cpp @@ -0,0 +1,131 @@ +//===--- Distro.cpp - Linux distribution detection support ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "clang/Driver/Distro.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/StringSwitch.h" +#include "llvm/Support/ErrorOr.h" +#include "llvm/Support/MemoryBuffer.h" + +using namespace clang::driver; +using namespace clang; + +static Distro::DistroType DetectDistro(vfs::FileSystem &VFS) { + llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> File = + VFS.getBufferForFile("/etc/lsb-release"); + if (File) { + StringRef Data = File.get()->getBuffer(); + SmallVector<StringRef, 16> Lines; + Data.split(Lines, "\n"); + Distro::DistroType Version = Distro::UnknownDistro; + for (StringRef Line : Lines) + if (Version == Distro::UnknownDistro && Line.startswith("DISTRIB_CODENAME=")) + Version = llvm::StringSwitch<Distro::DistroType>(Line.substr(17)) + .Case("hardy", Distro::UbuntuHardy) + .Case("intrepid", Distro::UbuntuIntrepid) + .Case("jaunty", Distro::UbuntuJaunty) + .Case("karmic", Distro::UbuntuKarmic) + .Case("lucid", Distro::UbuntuLucid) + .Case("maverick", Distro::UbuntuMaverick) + .Case("natty", Distro::UbuntuNatty) + .Case("oneiric", Distro::UbuntuOneiric) + .Case("precise", Distro::UbuntuPrecise) + .Case("quantal", Distro::UbuntuQuantal) + .Case("raring", Distro::UbuntuRaring) + .Case("saucy", Distro::UbuntuSaucy) + .Case("trusty", Distro::UbuntuTrusty) + .Case("utopic", Distro::UbuntuUtopic) + .Case("vivid", Distro::UbuntuVivid) + .Case("wily", Distro::UbuntuWily) + .Case("xenial", Distro::UbuntuXenial) + .Case("yakkety", Distro::UbuntuYakkety) + .Case("zesty", Distro::UbuntuZesty) + .Default(Distro::UnknownDistro); + if (Version != Distro::UnknownDistro) + return Version; + } + + File = VFS.getBufferForFile("/etc/redhat-release"); + if (File) { + StringRef Data = File.get()->getBuffer(); + if (Data.startswith("Fedora release")) + return Distro::Fedora; + if (Data.startswith("Red Hat Enterprise Linux") || + Data.startswith("CentOS") || + Data.startswith("Scientific Linux")) { + if (Data.find("release 7") != StringRef::npos) + return Distro::RHEL7; + else if (Data.find("release 6") != StringRef::npos) + return Distro::RHEL6; + else if (Data.find("release 5") != StringRef::npos) + return Distro::RHEL5; + } + return Distro::UnknownDistro; + } + + File = VFS.getBufferForFile("/etc/debian_version"); + if (File) { + StringRef Data = File.get()->getBuffer(); + // Contents: < major.minor > or < codename/sid > + int MajorVersion; + if (!Data.split('.').first.getAsInteger(10, MajorVersion)) { + switch (MajorVersion) { + case 5: + return Distro::DebianLenny; + case 6: + return Distro::DebianSqueeze; + case 7: + return Distro::DebianWheezy; + case 8: + return Distro::DebianJessie; + case 9: + return Distro::DebianStretch; + default: + return Distro::UnknownDistro; + } + } + return llvm::StringSwitch<Distro::DistroType>(Data.split("\n").first) + .Case("squeeze/sid", Distro::DebianSqueeze) + .Case("wheezy/sid", Distro::DebianWheezy) + .Case("jessie/sid", Distro::DebianJessie) + .Case("stretch/sid", Distro::DebianStretch) + .Default(Distro::UnknownDistro); + } + + File = VFS.getBufferForFile("/etc/SuSE-release"); + if (File) { + StringRef Data = File.get()->getBuffer(); + SmallVector<StringRef, 8> Lines; + Data.split(Lines, "\n"); + for (const StringRef& Line : Lines) { + if (!Line.trim().startswith("VERSION")) + continue; + std::pair<StringRef, StringRef> SplitLine = Line.split('='); + int Version; + // OpenSUSE/SLES 10 and older are not supported and not compatible + // with our rules, so just treat them as Distro::UnknownDistro. + if (!SplitLine.second.trim().getAsInteger(10, Version) && + Version > 10) + return Distro::OpenSUSE; + return Distro::UnknownDistro; + } + return Distro::UnknownDistro; + } + + if (VFS.exists("/etc/exherbo-release")) + return Distro::Exherbo; + + if (VFS.exists("/etc/arch-release")) + return Distro::ArchLinux; + + return Distro::UnknownDistro; +} + +Distro::Distro(vfs::FileSystem &VFS) : DistroVal(DetectDistro(VFS)) {} |