dmantipov created this revision. dmantipov added reviewers: mgorny, aganea. dmantipov added a project: clang. Herald added a subscriber: cfe-commits. dmantipov requested review of this revision.
When running regular ('clang++ foo.cc') native compilation on Linux target in a typical configuration, an attempt to detect distribution type is performed 4 times at least: - during an attempt to detect CUDA installation in clang::driver::CudaInstallationDetector::CudaInstallationDetector(); - during an instantiation of Linux-specific toolchain driver (clang::driver::toolchains::Linux::Linux()); - when special handling of '-faddrsig' is performed in clang::driver::tools::Clang::ConstructJob(); - finally when constructing a linker job in clang::driver::toolchains::Linux::getDynamicLinker(). Since distribution detection involves VFS, filesystem I/O and even parsing of file(s) contents, it looks desirable to cache the result and perform the whole procedure just once. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D87187 Files: clang/include/clang/Driver/Distro.h clang/lib/Driver/Distro.cpp Index: clang/lib/Driver/Distro.cpp =================================================================== --- clang/lib/Driver/Distro.cpp +++ clang/lib/Driver/Distro.cpp @@ -21,20 +21,10 @@ static Distro::DistroType DetectDistro(llvm::vfs::FileSystem &VFS, const llvm::Triple &TargetOrHost) { - // If we don't target Linux, no need to check the distro. This saves a few - // OS calls. - if (!TargetOrHost.isOSLinux()) - return Distro::UnknownDistro; - - // If the host is not running Linux, and we're backed by a real file system, - // no need to check the distro. This is the case where someone is - // cross-compiling from BSD or Windows to Linux, and it would be meaningless - // to try to figure out the "distro" of the non-Linux host. - IntrusiveRefCntPtr<llvm::vfs::FileSystem> RealFS = - llvm::vfs::getRealFileSystem(); - llvm::Triple HostTriple(llvm::sys::getProcessTriple()); - if (!HostTriple.isOSLinux() && &VFS == RealFS.get()) - return Distro::UnknownDistro; + // We're definitely on Linux, so start looking for the filesystem artifacts. + // TODO: adjust this to match modern freedesktop.org's compilant system + // with /etc/os-release and/or /usr/lib/os-release. For the details, + // see https://www.freedesktop.org/software/systemd/man/os-release.html. llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> File = VFS.getBufferForFile("/etc/lsb-release"); @@ -168,5 +158,36 @@ return Distro::UnknownDistro; } +static Distro::DistroType GetDistro(llvm::vfs::FileSystem &VFS, + const llvm::Triple &TargetOrHost) { + static Distro::DistroType Type = Distro::UninitializedDistro; + + // If we don't target Linux, no need to check the distro. This saves a few + // OS calls. + if (!TargetOrHost.isOSLinux()) + return Distro::UnknownDistro; + + // If we perform the detection already, return the result. This saves a few + // more OS calls assuming there was no underlying on-the fly distro change. + if (Type != Distro::UninitializedDistro) + return Type; + + // If the host is not running Linux, and we're backed by a real file system, + // no need to check the distro. This is the case where someone is + // cross-compiling from BSD or Windows to Linux, and it would be meaningless + // to try to figure out the "distro" of the non-Linux host. + IntrusiveRefCntPtr<llvm::vfs::FileSystem> RealFS = + llvm::vfs::getRealFileSystem(); + llvm::Triple HostTriple(llvm::sys::getProcessTriple()); + + if (!HostTriple.isOSLinux() && &VFS == RealFS.get()) + Type = Distro::UnknownDistro; + else + // Perform the detection and save the result. + Type = DetectDistro(VFS, TargetOrHost); + + return Type; +} + Distro::Distro(llvm::vfs::FileSystem &VFS, const llvm::Triple &TargetOrHost) - : DistroVal(DetectDistro(VFS, TargetOrHost)) {} + : DistroVal(GetDistro(VFS, TargetOrHost)) {} Index: clang/include/clang/Driver/Distro.h =================================================================== --- clang/include/clang/Driver/Distro.h +++ clang/include/clang/Driver/Distro.h @@ -23,6 +23,8 @@ class Distro { public: enum DistroType { + // Special value means that no detection was performed yet. + UninitializedDistro = -1, // NB: Releases of a particular Linux distro should be kept together // in this enum, because some tests are done by integer comparison against // the first and last known member in the family, e.g. IsRedHat().
Index: clang/lib/Driver/Distro.cpp =================================================================== --- clang/lib/Driver/Distro.cpp +++ clang/lib/Driver/Distro.cpp @@ -21,20 +21,10 @@ static Distro::DistroType DetectDistro(llvm::vfs::FileSystem &VFS, const llvm::Triple &TargetOrHost) { - // If we don't target Linux, no need to check the distro. This saves a few - // OS calls. - if (!TargetOrHost.isOSLinux()) - return Distro::UnknownDistro; - - // If the host is not running Linux, and we're backed by a real file system, - // no need to check the distro. This is the case where someone is - // cross-compiling from BSD or Windows to Linux, and it would be meaningless - // to try to figure out the "distro" of the non-Linux host. - IntrusiveRefCntPtr<llvm::vfs::FileSystem> RealFS = - llvm::vfs::getRealFileSystem(); - llvm::Triple HostTriple(llvm::sys::getProcessTriple()); - if (!HostTriple.isOSLinux() && &VFS == RealFS.get()) - return Distro::UnknownDistro; + // We're definitely on Linux, so start looking for the filesystem artifacts. + // TODO: adjust this to match modern freedesktop.org's compilant system + // with /etc/os-release and/or /usr/lib/os-release. For the details, + // see https://www.freedesktop.org/software/systemd/man/os-release.html. llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> File = VFS.getBufferForFile("/etc/lsb-release"); @@ -168,5 +158,36 @@ return Distro::UnknownDistro; } +static Distro::DistroType GetDistro(llvm::vfs::FileSystem &VFS, + const llvm::Triple &TargetOrHost) { + static Distro::DistroType Type = Distro::UninitializedDistro; + + // If we don't target Linux, no need to check the distro. This saves a few + // OS calls. + if (!TargetOrHost.isOSLinux()) + return Distro::UnknownDistro; + + // If we perform the detection already, return the result. This saves a few + // more OS calls assuming there was no underlying on-the fly distro change. + if (Type != Distro::UninitializedDistro) + return Type; + + // If the host is not running Linux, and we're backed by a real file system, + // no need to check the distro. This is the case where someone is + // cross-compiling from BSD or Windows to Linux, and it would be meaningless + // to try to figure out the "distro" of the non-Linux host. + IntrusiveRefCntPtr<llvm::vfs::FileSystem> RealFS = + llvm::vfs::getRealFileSystem(); + llvm::Triple HostTriple(llvm::sys::getProcessTriple()); + + if (!HostTriple.isOSLinux() && &VFS == RealFS.get()) + Type = Distro::UnknownDistro; + else + // Perform the detection and save the result. + Type = DetectDistro(VFS, TargetOrHost); + + return Type; +} + Distro::Distro(llvm::vfs::FileSystem &VFS, const llvm::Triple &TargetOrHost) - : DistroVal(DetectDistro(VFS, TargetOrHost)) {} + : DistroVal(GetDistro(VFS, TargetOrHost)) {} Index: clang/include/clang/Driver/Distro.h =================================================================== --- clang/include/clang/Driver/Distro.h +++ clang/include/clang/Driver/Distro.h @@ -23,6 +23,8 @@ class Distro { public: enum DistroType { + // Special value means that no detection was performed yet. + UninitializedDistro = -1, // NB: Releases of a particular Linux distro should be kept together // in this enum, because some tests are done by integer comparison against // the first and last known member in the family, e.g. IsRedHat().
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits