Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 58 additions & 16 deletions core/base/src/TROOT.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -3017,6 +3017,33 @@ const TString& TROOT::GetBinDir() {
////////////////////////////////////////////////////////////////////////////////
/// Get the library directory in the installation. Static utility function.
///
/// By default, this is just an alias for TROOT::GetSharedLibDir(), which
/// returns the directory containing the ROOT shared libraries.
///
/// On Windows, the behavior is different. In that case, this function doesn't
/// return the directory of the **shared libraries** (like `libCore.dll`), but
/// the **import libraries**, which are used at link time (like `libCore.lib`).

const TString &TROOT::GetLibDir()
{
#if defined(R__WIN32)
static bool initialized = false;
static TString rootlibdir;
if (initialized)
return rootlibdir;

initialized = true;
rootlibdir = "lib";
gSystem->PrependPathName(GetRootSys(), rootlibdir);
return rootlibdir;
#else
return TROOT::GetSharedLibDir();
#endif
}

////////////////////////////////////////////////////////////////////////////////
/// Get the shared libraries directory in the installation. Static utility function.
///
/// This function inspects the libraries currently loaded in the process to
/// locate the ROOT Core library. Once found, it extracts and returns the
/// directory containing that library. If the ROOT Core library was not found,
Expand All @@ -3025,9 +3052,9 @@ const TString& TROOT::GetBinDir() {
/// The result is cached in a static variable so the lookup is only performed
/// once per process, and the implementation is platform-specific.
///
/// \return The directory path (as a `TString`) containing the ROOT core library.
/// \return The directory path (as a `TString`) containing the ROOT shared libraries.

const TString &TROOT::GetLibDir()
const TString &TROOT::GetSharedLibDir()
{
static bool haveLooked = false;
static TString rootlibdir;
Expand Down Expand Up @@ -3057,9 +3084,35 @@ const TString &TROOT::GetLibDir()

#elif defined(_WIN32)

// Or Windows, the original hardcoded path is kept for now.
rootlibdir = "lib";
gSystem->PrependPathName(GetRootSys(), rootlibdir);
HMODULE modules[1024];
DWORD needed = 0;

HANDLE process = GetCurrentProcess();
if (EnumProcessModules(process, modules, sizeof(modules), &needed)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we handle and/or warn about the failure case (eg. if there are more than 1024 libraries or any other error)? Right now, it seems that in the failure case the return value is 'empty'.

const unsigned int count = needed / sizeof(HMODULE);

for (unsigned int i = 0; i < count; ++i) {
wchar_t wpath[MAX_PATH];
DWORD len = GetModuleFileNameW(modules[i], wpath, MAX_PATH);
if (!len)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is probably okay to ignore arbitrary library (for which the path is too long) ... but one of them might be libCore resulting in return an empty string. Can we do better and/or can we warn the user in the case libCore was not found?

continue;

fs::path p(wpath);
if (p.filename() == TO_LITERAL(LIB_CORE_NAME)) {

// Convert UTF-16 to UTF-8 explicitly
const std::wstring wdir = p.parent_path().wstring();

int utf8len = WideCharToMultiByte(CP_UTF8, 0, wdir.c_str(), -1, nullptr, 0, nullptr, nullptr);

std::string utf8dir(utf8len - 1, '\0');
WideCharToMultiByte(CP_UTF8, 0, wdir.c_str(), -1, utf8dir.data(), utf8len, nullptr, nullptr);

rootlibdir = utf8dir.c_str();
break;
}
}
}

#else

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

////////////////////////////////////////////////////////////////////////////////
/// Get the shared libraries directory in the installation. Static utility function.

const TString& TROOT::GetSharedLibDir() {
#if defined(R__WIN32)
return TROOT::GetBinDir();
#else
return TROOT::GetLibDir();
#endif
}

////////////////////////////////////////////////////////////////////////////////
/// Get the include directory in the installation. Static utility function.

Expand Down
Loading