Repository navigation
[core] Add test for ROOT_LIBRARY_PATH. #23123
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
f82a6b0
423c74e
a0b5b78
155e4b7
2a522a2
dcf6b4f
c8b9dd9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -4552,19 +4552,33 @@ int TUnixSystem::UnixSend(int sock, const void *buffer, int length, int flag) | |
| /// path" | sed 's/.*=//g' | awk '//{print $1}')` This might be useful in scenarios, where ROOT is instantiated many | ||
| /// times. | ||
|
|
||
| static const char *DynamicPath(const char *newpath = nullptr, Bool_t reset = kFALSE) | ||
| static const char *DynamicPath(const char *newpath = nullptr, Bool_t reset = kFALSE, | ||
| const char *addpath = nullptr) | ||
| { | ||
| static TString dynpath_full; | ||
| static std::atomic<bool> initialized(kFALSE); | ||
| static std::atomic<bool> seenCling(kFALSE); | ||
|
|
||
| // If we have not seen Cling but the result has been initialized and gCling | ||
| // is still nullptr, the result won't change. | ||
| if (newpath == nullptr && !reset && (seenCling || (initialized && gCling == nullptr))) | ||
| if (newpath == nullptr && addpath == nullptr && !reset && | ||
| (seenCling || (initialized && gCling == nullptr))) | ||
| return dynpath_full; | ||
|
|
||
| R__LOCKGUARD2(gSystemMutex); | ||
|
|
||
| // Directories appended via `addpath` (TUnixSystem::AddDynamicPath). They are | ||
| // kept separately from the automatically assembled part so that they survive | ||
| // a re-assembly (e.g. the deferred insertion of the Cling provided parts). | ||
| static TString addedPaths; | ||
|
|
||
| if (reset) { | ||
| addedPaths = ""; | ||
| // Re-arm the deferred insertion of the Cling provided parts (it is set | ||
| // again below if gCling is already available). | ||
| seenCling = kFALSE; | ||
| } | ||
|
|
||
| if (newpath) { | ||
| dynpath_full = newpath; | ||
| // Don't erase the user given path at the next call. | ||
|
|
@@ -4579,6 +4593,23 @@ static const char *DynamicPath(const char *newpath = nullptr, Bool_t reset = kFA | |
| return dynpath_full; | ||
| } | ||
|
|
||
| if (addpath && *addpath) { | ||
| // Record the extra directory and append it to the current value. Contrary | ||
| // to a path set explicitly via SetDynamicPath (`newpath`), this must not | ||
| // set seenCling: the automatically assembled part can still be updated | ||
| // (to insert the Cling provided parts) and the extra directories are then | ||
| // re-appended below. | ||
| addedPaths += ":"; | ||
| addedPaths += addpath; | ||
| if (initialized) { | ||
| if (!dynpath_full.EndsWith(":")) | ||
| dynpath_full += ":"; | ||
| dynpath_full += addpath; | ||
| } | ||
| // Fall through: if the path was not yet assembled, or if the Cling | ||
| // provided parts can now be inserted, do it now (extrapath included). | ||
| } | ||
|
|
||
| // Another thread might have updated this. Even-though this is executed at the | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. How can another thread have updated this? We are in a mutex-protected region. |
||
| // start of the process, we might get there if the user is explicitly | ||
| // 'resetting' the value. | ||
|
|
@@ -4668,7 +4699,7 @@ static const char *DynamicPath(const char *newpath = nullptr, Bool_t reset = kFA | |
| #endif | ||
| } | ||
|
|
||
| if (!initialized || (!seenCling && gCling)) { | ||
| if (reset || !initialized || (!seenCling && gCling)) { | ||
| dynpath_full = dynpath_envpart; | ||
| if (!dynpath_full.EndsWith(":")) dynpath_full += ":"; | ||
| if (gCling) { | ||
|
|
@@ -4678,6 +4709,7 @@ static const char *DynamicPath(const char *newpath = nullptr, Bool_t reset = kFA | |
| seenCling = kTRUE; | ||
| } | ||
| dynpath_full += dynpath_syspart; | ||
| dynpath_full += addedPaths; // entries carry a leading ':' | ||
| initialized = kTRUE; | ||
|
|
||
| if (gDebug > 0) std::cout << "dynpath = " << dynpath_full.Data() << std::endl; | ||
|
|
@@ -4692,10 +4724,7 @@ static const char *DynamicPath(const char *newpath = nullptr, Bool_t reset = kFA | |
| void TUnixSystem::AddDynamicPath(const char *path) | ||
| { | ||
| if (path) { | ||
| TString oldpath = DynamicPath(nullptr, kFALSE); | ||
| oldpath.Append(":"); | ||
| oldpath.Append(path); | ||
| DynamicPath(oldpath); | ||
| DynamicPath(nullptr, kFALSE, path); | ||
| } | ||
| } | ||
|
|
||
|
|
||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Merge the changes to TWinNTSystem with previous commit. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -356,17 +356,45 @@ namespace { | |
|
|
||
| ///////////////////////////////////////////////////////////////////////////// | ||
| /// Get shared library search path. | ||
|
|
||
| static const char *DynamicPath(const char *newpath = 0, Bool_t reset = kFALSE) | ||
| /// The path is assembled from the ROOT_LIBRARY_PATH environment variable, | ||
| /// the PATH environment variable, the `Root.DynamicPath` resource of | ||
| /// .rootrc and the ROOT library directory. Directories can be appended via | ||
| /// `addpath` (used by TWinNTSystem::AddDynamicPath). The path may first be | ||
| /// assembled before gEnv is available (TWinNTSystem::Init() adds the | ||
| /// directory of libCore.dll); in that case it is re-assembled - keeping the | ||
| /// appended directories - as soon as gEnv exists, so that the | ||
| /// `Root.DynamicPath` resource is taken into account. | ||
| /// A path set explicitly through `newpath` (TWinNTSystem::SetDynamicPath) | ||
| /// is used verbatim and is never amended. | ||
|
|
||
| static const char *DynamicPath(const char *newpath = 0, Bool_t reset = kFALSE, | ||
| const char *addpath = 0) | ||
|
Comment on lines
+368
to
+369
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This signature seems more complicated that it needs to be. The newpath and addpath parameters are mutually exclusive, which is not explicitly checked. How about a single path parameter and an enum to distinguish "new, fixed user path (includes reset)" from "add to path". |
||
| { | ||
| static TString dynpath; | ||
| static TString addedPaths; // directories appended via `addpath` | ||
| static Bool_t userpath = kFALSE; // dynpath explicitly set via SetDynamicPath() | ||
| static Bool_t sawEnv = kFALSE; // dynpath was assembled with gEnv available | ||
|
|
||
| if (reset || newpath) { | ||
| if (reset) { | ||
| dynpath = ""; | ||
| addedPaths = ""; | ||
| userpath = kFALSE; | ||
| sawEnv = kFALSE; | ||
| } | ||
| if (newpath) { | ||
| dynpath = newpath; | ||
| } else if (dynpath == "") { | ||
| userpath = kTRUE; | ||
| } else if (addpath && *addpath) { | ||
| if (!dynpath.IsNull()) { | ||
| dynpath += ";"; dynpath += addpath; | ||
| } | ||
| addedPaths += ";"; addedPaths += addpath; | ||
| } | ||
| if (!userpath && (dynpath.IsNull() || (!sawEnv && gEnv))) { | ||
| // (Re)assemble the path. A path assembled while gEnv was not yet | ||
| // available misses the Root.DynamicPath resource, so it is rebuilt | ||
| // here once gEnv exists. | ||
| sawEnv = (gEnv != nullptr); | ||
| dynpath = gSystem->Getenv("ROOT_LIBRARY_PATH"); | ||
| TString rdynpath = gEnv ? gEnv->GetValue("Root.DynamicPath", (char*)0) : ""; | ||
| rdynpath.ReplaceAll("; ", ";"); // in case DynamicPath was extended | ||
|
|
@@ -384,9 +412,10 @@ namespace { | |
| dynpath += ";"; | ||
| dynpath += rdynpath; | ||
| } | ||
| } | ||
| if (!dynpath.Contains(TROOT::GetLibDir())) { | ||
| dynpath += ";"; dynpath += TROOT::GetLibDir(); | ||
| if (!dynpath.Contains(TROOT::GetLibDir())) { | ||
| dynpath += ";"; dynpath += TROOT::GetLibDir(); | ||
| } | ||
| dynpath += addedPaths; // entries carry a leading ';' | ||
| } | ||
|
|
||
| return dynpath; | ||
|
|
@@ -4073,10 +4102,7 @@ Int_t TWinNTSystem::RedirectOutput(const char *file, const char *mode, | |
| void TWinNTSystem::AddDynamicPath(const char *dir) | ||
| { | ||
| if (dir) { | ||
| TString oldpath = DynamicPath(0, kFALSE); | ||
| oldpath.Append(";"); | ||
| oldpath.Append(dir); | ||
| DynamicPath(oldpath); | ||
| DynamicPath(0, kFALSE, dir); | ||
| } | ||
| } | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| # Check the way the dynamic (shared library) search path is assembled from | ||
| # ROOT_LIBRARY_PATH, the system loader path and the .rootrc resource. | ||
| # | ||
| # This used to be implemented by the shell script `test_dynpath_setup.sh`; it | ||
| # is now driven by the CMake script `dynamicPathSetup.cmake` so that the test | ||
| # also runs on Windows. | ||
|
|
||
| ROOTTEST_ADD_TEST(DynPathSetup | ||
| COMMAND ${CMAKE_COMMAND} | ||
| -DROOT_EXE=${ROOT_root_CMD} | ||
| -DWORKDIR=${CMAKE_CURRENT_BINARY_DIR}/rootlibpath_test | ||
| -P ${CMAKE_CURRENT_SOURCE_DIR}/dynamicPathSetup.cmake | ||
| ENVIRONMENT ROOTENV_NO_HOME=1) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What if the initial
newpathwas empty?