LUMIERA.clone/src/lib/searchpath.cpp
2025-06-07 23:59:57 +02:00

96 lines
2.7 KiB
C++
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
Searchpath - helpers for searching directory lists and locating modules
Copyright (C)
2011, Hermann Vosseler <Ichthyostega@web.de>
  **Lumiera** is free software; you can redistribute it and/or modify it
  under the terms of the GNU General Public License as published by the
  Free Software Foundation; either version 2 of the License, or (at your
  option) any later version. See the file COPYING for further details.
* *****************************************************************/
/** @file searchpath.cpp
** Implementation of helpers to handle directory search paths.
*/
#include "lib/error.hpp"
#include "lib/searchpath.hpp"
#include "lib/format-string.hpp"
#include "lib/symbol.hpp"
/** how to retrieve the absolute path of the currently running executable
* on a Linux system: read the link provided by the kernel through /proc
*/
#define GET_PATH_TO_EXECUTABLE "/proc/self/exe"
namespace lib {
using util::_Fmt;
using std::regex;
using std::regex_replace;
const regex SearchPathSplitter::ACCEPT_PATHELEMENT{"(^|:)\\s*([^:]+)", regex::optimize};
/** @internal helper to figure out the installation directory,
* as given by the absolute path of the currently executing program
* @warning this is Linux specific code */
fs::path
findExePath()
{
fs::path selfExe{GET_PATH_TO_EXECUTABLE};
if (not fs::exists (selfExe))
throw error::Fatal ("unable to discover path of running executable");
return fs::canonical (selfExe);
}
/** @internal helper to replace all $ORIGIN prefixes in a given string
* by the directory holding the current executable
* @note also picks ORIGIN, $ORIGIN/, ORIGIN/
*/
string
replaceMagicLinkerTokens (string const& src)
{
static const regex PICK_ORIGIN_TOKEN{"\\$?ORIGIN/?", regex::optimize};
static const string expandedOriginDir
= findExePath().parent_path().generic_string() + "/";
return regex_replace (src, PICK_ORIGIN_TOKEN, expandedOriginDir);
}
string
resolveModulePath (fs::path moduleName, string searchPath)
{
fs::path modulePathName (moduleName);
SearchPathSplitter searchLocation(searchPath);
while (not fs::exists (modulePathName))
{
// try / continue search path
if (not searchLocation)
throw error::Config{_Fmt{"Module %s not found%s"}
% moduleName
%(searchPath.empty()? ".":" in search path: "+searchPath)};
modulePathName = *searchLocation / moduleName;
++searchLocation;
}
TRACE (config, "found module %s", cStr(modulePathName.generic_string()));
return modulePathName.generic_string();
}
} // namespace lib