Skip to content

Commit 65fe1cd

Browse files
committed
[core] Generalize TROOT::GetSharedLibDir() also on Windows
This follows up on 47caba5, also generalizing the function on Windows by dynamically finding `libCore.dll` (or `Core.dll` depending on the toolchain). The goal is to avoid using `TROOT::GetRootSys()` in the implementation of this method, with the overarching goal of not having to rely on environment variables like `ROOTSYS` one day, which might not be set in some environments like the Python wheels.
1 parent bec6eb3 commit 65fe1cd

1 file changed

Lines changed: 58 additions & 16 deletions

File tree

core/base/src/TROOT.cxx

Lines changed: 58 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3017,6 +3017,33 @@ const TString& TROOT::GetBinDir() {
30173017
////////////////////////////////////////////////////////////////////////////////
30183018
/// Get the library directory in the installation. Static utility function.
30193019
///
3020+
/// By default, this is just an alias for TROOT::GetSharedLibDir(), which
3021+
/// returns the directory containing the ROOT shared libraries.
3022+
///
3023+
/// On Windows, the behavior is different. In that case, this function doesn't
3024+
/// return the directory of the **shared libraries** (like `libCore.dll`), but
3025+
/// the **import libraries**, which are used at link time (like `libCore.lib`).
3026+
3027+
const TString &TROOT::GetLibDir()
3028+
{
3029+
#if defined(R__WIN32)
3030+
static bool initialized = false;
3031+
static TString rootlibdir;
3032+
if (initialized)
3033+
return rootlibdir;
3034+
3035+
initialized = true;
3036+
rootlibdir = "lib";
3037+
gSystem->PrependPathName(GetRootSys(), rootlibdir);
3038+
return rootlibdir;
3039+
#else
3040+
return TROOT::GetSharedLibDir();
3041+
#endif
3042+
}
3043+
3044+
////////////////////////////////////////////////////////////////////////////////
3045+
/// Get the shared libraries directory in the installation. Static utility function.
3046+
///
30203047
/// This function inspects the libraries currently loaded in the process to
30213048
/// locate the ROOT Core library. Once found, it extracts and returns the
30223049
/// directory containing that library. If the ROOT Core library was not found,
@@ -3025,9 +3052,9 @@ const TString& TROOT::GetBinDir() {
30253052
/// The result is cached in a static variable so the lookup is only performed
30263053
/// once per process, and the implementation is platform-specific.
30273054
///
3028-
/// \return The directory path (as a `TString`) containing the ROOT core library.
3055+
/// \return The directory path (as a `TString`) containing the ROOT shared libraries.
30293056

3030-
const TString &TROOT::GetLibDir()
3057+
const TString &TROOT::GetSharedLibDir()
30313058
{
30323059
static bool haveLooked = false;
30333060
static TString rootlibdir;
@@ -3057,9 +3084,35 @@ const TString &TROOT::GetLibDir()
30573084

30583085
#elif defined(_WIN32)
30593086

3060-
// Or Windows, the original hardcoded path is kept for now.
3061-
rootlibdir = "lib";
3062-
gSystem->PrependPathName(GetRootSys(), rootlibdir);
3087+
HMODULE modules[1024];
3088+
DWORD needed = 0;
3089+
3090+
HANDLE process = GetCurrentProcess();
3091+
if (EnumProcessModules(process, modules, sizeof(modules), &needed)) {
3092+
const unsigned int count = needed / sizeof(HMODULE);
3093+
3094+
for (unsigned int i = 0; i < count; ++i) {
3095+
wchar_t wpath[MAX_PATH];
3096+
DWORD len = GetModuleFileNameW(modules[i], wpath, MAX_PATH);
3097+
if (!len)
3098+
continue;
3099+
3100+
fs::path p(wpath);
3101+
if (p.filename() == TO_LITERAL(LIB_CORE_NAME)) {
3102+
3103+
// Convert UTF-16 to UTF-8 explicitly
3104+
const std::wstring wdir = p.parent_path().wstring();
3105+
3106+
int utf8len = WideCharToMultiByte(CP_UTF8, 0, wdir.c_str(), -1, nullptr, 0, nullptr, nullptr);
3107+
3108+
std::string utf8dir(utf8len - 1, '\0');
3109+
WideCharToMultiByte(CP_UTF8, 0, wdir.c_str(), -1, utf8dir.data(), utf8len, nullptr, nullptr);
3110+
3111+
rootlibdir = utf8dir.c_str();
3112+
break;
3113+
}
3114+
}
3115+
}
30633116

30643117
#else
30653118

@@ -3083,17 +3136,6 @@ const TString &TROOT::GetLibDir()
30833136
return rootlibdir;
30843137
}
30853138

3086-
////////////////////////////////////////////////////////////////////////////////
3087-
/// Get the shared libraries directory in the installation. Static utility function.
3088-
3089-
const TString& TROOT::GetSharedLibDir() {
3090-
#if defined(R__WIN32)
3091-
return TROOT::GetBinDir();
3092-
#else
3093-
return TROOT::GetLibDir();
3094-
#endif
3095-
}
3096-
30973139
////////////////////////////////////////////////////////////////////////////////
30983140
/// Get the include directory in the installation. Static utility function.
30993141

0 commit comments

Comments
 (0)