From 5ae825936d5c0c266c9e795a1354c22e9c020d43 Mon Sep 17 00:00:00 2001 From: Jonas Rembser Date: Mon, 26 Jan 2026 19:23:20 +0100 Subject: [PATCH] [core] Follow symlinks in `TROOT::GetSharedLibDir()` The idea is to find the actual ROOT install directory, so we have to follow symlinks. The `info->dlpi_name` doesn't do that, so we need to do that ourselves with `fs::canonical()`. Closes #21031. --- core/base/src/TROOT.cxx | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/core/base/src/TROOT.cxx b/core/base/src/TROOT.cxx index a9d9bb5cdc189..57f56133d00cb 100644 --- a/core/base/src/TROOT.cxx +++ b/core/base/src/TROOT.cxx @@ -3159,7 +3159,26 @@ const TString &TROOT::GetSharedLibDir() fs::path p = info->dlpi_name; if (p.filename() == _R_QUOTEVAL_(LIB_CORE_NAME)) { - libdir = p.parent_path().c_str(); + std::error_code ec; + + // Resolve symlinks: critical for environments like CMSSW, where the + // ROOT libraries are loaded via symlinks that point to the actual + // install directory + fs::path resolved = fs::canonical(p, ec); + if (ec) { + ::Error("TROOT", + "Failed to canonicalize detected ROOT shared library path:\n" + "%s\n" + "Error code: %d (%s)\n" + "Error category: %s\n" + "This is an unexpected internal error and ROOT might not work.\n" + "Please report this issue on GitHub: https://github.com/root-project/root/issues", + p.string().c_str(), ec.value(), ec.message().c_str(), ec.category().name()); + // Fall back to the loader path if canonicalization fails. The path + // will likely be wrong, but at least not garbage + resolved = p; + } + libdir = resolved.parent_path().c_str(); return 1; // stop iteration } return 0; // continue