mirror of
https://github.com/revng/revng
synced 2026-06-21 14:07:57 +00:00
f8ffe38687
Make the cache directory logic uniform in Python and C++, move the respective implementations under support since it's project-wide logic and not exclusive to debug-info.
166 lines
4.2 KiB
C++
166 lines
4.2 KiB
C++
//
|
|
// This file is distributed under the MIT License. See LICENSE.md for details.
|
|
//
|
|
|
|
extern "C" {
|
|
#include "dlfcn.h"
|
|
#include "link.h"
|
|
}
|
|
|
|
#include <map>
|
|
#include <set>
|
|
|
|
#include "llvm/ADT/StringRef.h"
|
|
#include "llvm/Support/FileSystem.h"
|
|
#include "llvm/Support/GlobPattern.h"
|
|
#include "llvm/Support/ManagedStatic.h"
|
|
#include "llvm/Support/MemoryBuffer.h"
|
|
#include "llvm/Support/Path.h"
|
|
#include "llvm/Support/Process.h"
|
|
|
|
#include "revng/Support/Assert.h"
|
|
#include "revng/Support/Debug.h"
|
|
#include "revng/Support/PathList.h"
|
|
|
|
static Logger<> Log("find-resources");
|
|
|
|
struct Resources {
|
|
bool FirstCall = true;
|
|
std::string CurrentRoot;
|
|
std::map<std::string, std::string> LibrariesFullPath;
|
|
};
|
|
|
|
llvm::ManagedStatic<Resources> Resources;
|
|
|
|
extern "C" {
|
|
static int
|
|
dlIteratePhdrCallback(struct dl_phdr_info *Info, size_t Size, void *Data) {
|
|
using llvm::StringRef;
|
|
|
|
if (Info->dlpi_name == nullptr)
|
|
return 0;
|
|
|
|
StringRef FullPath(Info->dlpi_name);
|
|
if (FullPath.size() == 0)
|
|
return 0;
|
|
|
|
StringRef Name = llvm::sys::path::filename(FullPath);
|
|
Resources->LibrariesFullPath[Name.rsplit(".so").first.str()] = FullPath.str();
|
|
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
static void initialize() {
|
|
if (not Resources->FirstCall)
|
|
return;
|
|
|
|
Resources->FirstCall = false;
|
|
|
|
dl_iterate_phdr(dlIteratePhdrCallback, nullptr);
|
|
|
|
using namespace llvm::sys::path;
|
|
constexpr const char *MainLibrary = "librevngSupport";
|
|
using llvm::StringRef;
|
|
StringRef MainLibraryFullPath = Resources->LibrariesFullPath.at(MainLibrary);
|
|
Resources->CurrentRoot = parent_path(parent_path(MainLibraryFullPath));
|
|
}
|
|
|
|
llvm::StringRef getCurrentRoot() {
|
|
initialize();
|
|
return Resources->CurrentRoot;
|
|
}
|
|
|
|
std::string getCacheDirectory() {
|
|
if (auto CacheEnv = llvm::sys::Process::GetEnv("REVNG_CACHE_DIR")) {
|
|
return *CacheEnv;
|
|
}
|
|
|
|
std::string BaseDir;
|
|
if (auto XDGDir = llvm::sys::Process::GetEnv("XDG_CACHE_HOME")) {
|
|
BaseDir = *XDGDir;
|
|
} else {
|
|
llvm::SmallString<64> PathHome;
|
|
llvm::sys::path::home_directory(PathHome);
|
|
BaseDir = joinPath(PathHome.str(), ".cache");
|
|
}
|
|
return joinPath(BaseDir, "revng");
|
|
}
|
|
|
|
const std::map<std::string, std::string> &getLibrariesFullPath() {
|
|
initialize();
|
|
return Resources->LibrariesFullPath;
|
|
}
|
|
|
|
static std::optional<std::string>
|
|
findFileInPaths(llvm::StringRef FileName,
|
|
const std::vector<std::string> &SearchPaths) {
|
|
|
|
std::optional<std::string> FoundFileName;
|
|
|
|
for (const auto &Path : SearchPaths) {
|
|
revng_log(Log, "Looking in path: " << Path);
|
|
llvm::SmallString<64> FullFileName;
|
|
llvm::sys::path::append(FullFileName, Path, FileName);
|
|
|
|
LoggerIndent<> Indent(Log);
|
|
|
|
if (not llvm::sys::fs::exists(FullFileName)) {
|
|
revng_log(Log, "File not found: " << FullFileName.str().str());
|
|
continue;
|
|
}
|
|
|
|
std::error_code
|
|
Err = llvm::sys::fs::access(FullFileName,
|
|
llvm::sys::fs::AccessMode::Exist);
|
|
if (Err) {
|
|
revng_log(Log, "Cannot access file: " << FullFileName.str().str());
|
|
} else {
|
|
revng_log(Log, "Found file: " << FullFileName.str().str());
|
|
FoundFileName = FullFileName.str().str();
|
|
break;
|
|
}
|
|
}
|
|
|
|
revng_assert(FoundFileName,
|
|
("failed to find '" + FileName + "'.").str().c_str());
|
|
|
|
return FoundFileName;
|
|
}
|
|
|
|
std::optional<std::string> PathList::findFile(llvm::StringRef FileName) const {
|
|
return findFileInPaths(FileName, SearchPaths);
|
|
}
|
|
|
|
std::vector<std::string> PathList::list(llvm::StringRef Path,
|
|
llvm::StringRef Suffix) const {
|
|
using namespace llvm;
|
|
using namespace sys;
|
|
using namespace fs;
|
|
using std::string;
|
|
|
|
std::set<string> Visited;
|
|
std::vector<string> Result;
|
|
for (const string &SearchPath : SearchPaths) {
|
|
SmallString<16> FullPath(SearchPath);
|
|
path::append(FullPath, Path);
|
|
|
|
if (is_directory(FullPath)) {
|
|
std::error_code EC;
|
|
for (directory_iterator File(FullPath, EC), FileEnd;
|
|
File != FileEnd && !EC;
|
|
File.increment(EC)) {
|
|
if (llvm::StringRef(File->path()).endswith(Suffix)) {
|
|
bool New = Visited.insert(path::filename(File->path()).str()).second;
|
|
if (New)
|
|
Result.push_back(File->path());
|
|
}
|
|
}
|
|
|
|
revng_assert(!EC);
|
|
}
|
|
}
|
|
|
|
return Result;
|
|
}
|