@@ -71,6 +71,7 @@ of a main program creating an interactive version is shown below:
7171#include < ROOT/RVersion.hxx>
7272#include " RConfigure.h"
7373#include " RConfigOptions.h"
74+ #include < filesystem>
7475#include < string>
7576#include < map>
7677#include < set>
@@ -109,7 +110,10 @@ FARPROC dlsym(void *library, const char *function_name)
109110 return ::GetProcAddress ((HMODULE)library, function_name);
110111 }
111112}
113+ #elif defined(__APPLE__)
114+ #include < mach-o/dyld.h>
112115#else
116+ #include < link.h>
113117#include < dlfcn.h>
114118#endif
115119
@@ -3007,23 +3011,86 @@ const TString& TROOT::GetBinDir() {
30073011
30083012// //////////////////////////////////////////////////////////////////////////////
30093013// / Get the library directory in the installation. Static utility function.
3014+ // /
3015+ // / This function inspects the libraries currently loaded in the process
3016+ // / to locate the ROOT core library (`libCore`). Once found, it extracts
3017+ // / and returns the directory containing that library.
3018+ // /
3019+ // / The implementation is platform-specific:
3020+ // / - **Linux**: Uses `dl_iterate_phdr()` to iterate over all loaded
3021+ // / ELF objects. When `libCore.so` is found, its parent directory is returned.
3022+ // / - **macOS**: Iterates over all Mach-O images via `_dyld_image_count()`
3023+ // / and `_dyld_get_image_name()`, looking for `libCore.dylib`
3024+ // / (or `libCore.so` for compatibility).
3025+ // / - **Windows**: Uses `EnumProcessModules()` and `GetModuleFileNameA()`
3026+ // / to inspect loaded DLLs, looking for `libCore.dll`.
3027+ // /
3028+ // / The result is cached in a static variable so the lookup is only
3029+ // / performed once per process.
3030+ // /
3031+ // / \return The directory path (as a `TString`) containing the ROOT core library.
30103032
3011- const TString& TROOT::GetLibDir () {
3012- #ifdef ROOTLIBDIR
3013- if (IgnorePrefix ()) {
3014- #endif
3015- static TString rootlibdir;
3016- if (rootlibdir.IsNull ()) {
3017- rootlibdir = " lib" ;
3018- gSystem ->PrependPathName (GetRootSys (), rootlibdir);
3019- }
3020- return rootlibdir;
3021- #ifdef ROOTLIBDIR
3022- } else {
3023- const static TString rootlibdir = ROOTLIBDIR;
3033+ const TString &TROOT::GetLibDir ()
3034+ {
3035+ static TString rootlibdir;
3036+ if (!rootlibdir.IsNull ())
30243037 return rootlibdir;
3038+
3039+ namespace fs = std::filesystem;
3040+
3041+ #ifdef __linux__
3042+
3043+ auto callback = +[](struct dl_phdr_info *info, size_t /* size*/ , void *data) -> int {
3044+ TString &libdir = *static_cast <TString *>(data);
3045+ if (!info->dlpi_name )
3046+ return 0 ;
3047+
3048+ fs::path p = info->dlpi_name ;
3049+ if (p.filename () == " libCore.so" ) {
3050+ libdir = p.parent_path ().c_str ();
3051+ return 1 ; // stop iteration
3052+ }
3053+ return 0 ; // continue
3054+ };
3055+
3056+ dl_iterate_phdr (callback, &rootlibdir);
3057+
3058+ #elif defined(__APPLE__)
3059+
3060+ uint32_t count = _dyld_image_count ();
3061+ for (uint32_t i = 0 ; i < count; i++) {
3062+ const char *path = _dyld_get_image_name (i);
3063+ if (!path)
3064+ continue ;
3065+
3066+ fs::path p (path);
3067+ if (p.filename () == " libCore.dylib" || p.filename () == " libCore.so" ) {
3068+ rootlibdir = p.parent_path ().c_str ();
3069+ break ;
3070+ }
30253071 }
3072+
3073+ #elif defined(_WIN32)
3074+
3075+ HMODULE hMods[1024 ];
3076+ DWORD cbNeeded;
3077+
3078+ if (EnumProcessModules (::GetCurrentProcess (), hMods, sizeof (hMods), &cbNeeded)) {
3079+ for (unsigned int i = 0 ; i < (cbNeeded / sizeof (HMODULE)); i++) {
3080+ char szModName[MAX_PATH];
3081+ if (GetModuleFileNameA (hMods[i], szModName, sizeof (szModName) / sizeof (char ))) {
3082+ fs::path p (szModName);
3083+ if (p.filename () == " libCore.dll" ) { // ROOT Windows build
3084+ rootlibdir = p.parent_path ().string ().c_str ();
3085+ break ;
3086+ }
3087+ }
3088+ }
3089+ }
3090+
30263091#endif
3092+
3093+ return rootlibdir;
30273094}
30283095
30293096// //////////////////////////////////////////////////////////////////////////////
0 commit comments