Check duplicate issues.
Description
This is for the specific ROOT build configuration used in LCG's dev3 nightly where recently more and more of the builtins are turned off. Last week we encountered link errors because xxhash is now coming from a place external to ROOT (but still from the LCG cvmfs area, not the system).
ATLAS sees this issue in both online and offline software and has worked around similar issues with vdt and tbb in the past. However, it seems this should be fixed on the ROOT side instead.
In the reproducer a minimal environment is setup that I would expect to work. The creation of a shared library linking against ROOT::Core and ROOT::Hist succeeds, while linking an executable against the same two libraries fails, complaining about not finding the tbb and xxhash libraries.
[ 75%] Linking CXX executable example
/cvmfs/sft.cern.ch/lcg/releases/binutils/2.40-acaab/x86_64-el9/bin/ld: warning: libtbb.so.12, needed by /cvmfs/sft-nightlies.cern.ch/lcg/nightlies/dev3/Mon/ROOT/HEAD/x86_64-el9-gcc14-opt/lib/libThread.so, not found (try using -rpath or -rpath-link)
/cvmfs/sft.cern.ch/lcg/releases/binutils/2.40-acaab/x86_64-el9/bin/ld: warning: libxxhash.so.0, needed by /cvmfs/sft-nightlies.cern.ch/lcg/nightlies/dev3/Mon/ROOT/HEAD/x86_64-el9-gcc14-opt/lib/libCore.so, not found (try using -rpath or -rpath-link)
[...]
I assume tbb and xxhash are considered internal implementation details of ROOT, that's why they do not appear anywhere in the ROOT-targets*.cmake files as dependencies, and no find_dependency() call is made. That sounds logical as a client never references any symbols from these libraries directly. And indeed this is fine for a shared library as the reproducer shows.
However, the standard Linux linker (but not mold/gold/... it seems) has a unique behaviour where it tries to resolve symbols even in indirectly referenced libraries when the final executable is linked. The exact search is described under --rpath-link option in the ld man page.
A simple test is to add the tbb and xxhash library paths to LD_LIBRARY_PATH : the linking now succeeds. However, this is not something we do: LD_LIBRARY_PATH is a variable for the run-time dynamic linker and should not be needed at link time.
Shouldn't ROOT have both TBB::tbb and xxHash::xxHash in the INTERFACE_LINK_LIBRARIES of the exported targets, where relevant, together with the find_depency() calls in the case where these libraries are external to ROOT ?
The alternative is that every client who links an executable has to know what libraries are ROOT builtins or not and has to modify their own CMakeLists.txt file accordingly.
Having to set LD_LIBRARY_PATH is similar cumbersome - for a bootstrap build we generate our run-time setup script at the end of the build where we know what is needed, and it is not straightforward to inject environment variables into the build environment from cmake itself (i.e. not having the user do it explicitly by sourcing some file etc.). Never mind that this is a variable meant to be used at run-time.
Reproducer
On an Alma 9 host with cvmfs:
. ./setup.sh
cmake -B build
cmake --build build
setup.sh
. /cvmfs/sft-nightlies.cern.ch/lcg/contrib/gcc/14.2.0/x86_64-el9/setup.sh
export CMAKE_PREFIX_PATH=/cvmfs/sft-nightlies.cern.ch/lcg/nightlies/dev3/Mon/xxHash/0.8.3/x86_64-el9-gcc14-opt:/cvmfs/sft-nightlies.cern.ch/lcg/nightlies/dev3/Mon/vdt/0.4.4/x86_64-el9-gcc14-
opt:/cvmfs/sft-nightlies.cern.ch/lcg/nightlies/dev3/Mon/tbb/2022.2.0/x86_64-el9-gcc14-opt:/cvmfs/sft-nightlies.cern.ch/lcg/nightlies/dev3/Mon/ROOT/HEAD/x86_64-el9-gcc14-opt
CMakeLists.txt
cmake_minimum_required(VERSION 3.26)
project(rootTest LANGUAGES CXX)
find_package(ROOT REQUIRED COMPONENTS Core Hist)
add_library(libexample SHARED libexample.cxx)
target_link_libraries(libexample PRIVATE ROOT::Core ROOT::Hist)
add_executable(example example.cxx)
target_link_libraries(example PRIVATE ROOT::Core ROOT::Hist)
libexample.cxx
#include "TH1F.h"
void f()
{
auto h = new TH1F("t", "t", 100, 0.0, 100.0);
delete h;
}
example.cxx
#include "TH1F.h"
int main()
{
auto h = new TH1F("Test", "Test", 100, 0.0, 100.0);
}
ROOT version
------------------------------------------------------------------
| Welcome to ROOT 6.39.01 https://root.cern |
| (c) 1995-2025, The ROOT Team; conception: R. Brun, F. Rademakers |
| Built for linuxx8664gcc on Apr 19 2026, 22:52:36 |
| From heads/master@0481b1d8 |
| With g++ (GCC) 14.3.0 std202002 |
| Try '.help'/'.?', '.demo', '.license', '.credits', '.quit'/'.q' |
------------------------------------------------------------------
Installation method
Pre-built by SFT/LCG team on /cvmfs/sft-nightlies.cern.ch/lcg/nightlies/dev3/Mon/ROOT
Operating system
Linux Alma 9
Additional context
Was discussed in yesterday's LIM meeting and we were asked to open a ticket directly here.
Check duplicate issues.
Description
This is for the specific ROOT build configuration used in LCG's dev3 nightly where recently more and more of the builtins are turned off. Last week we encountered link errors because
xxhashis now coming from a place external to ROOT (but still from the LCG cvmfs area, not the system).ATLAS sees this issue in both online and offline software and has worked around similar issues with vdt and tbb in the past. However, it seems this should be fixed on the ROOT side instead.
In the reproducer a minimal environment is setup that I would expect to work. The creation of a shared library linking against ROOT::Core and ROOT::Hist succeeds, while linking an executable against the same two libraries fails, complaining about not finding the tbb and xxhash libraries.
I assume
tbbandxxhashare considered internal implementation details of ROOT, that's why they do not appear anywhere in theROOT-targets*.cmakefiles as dependencies, and nofind_dependency()call is made. That sounds logical as a client never references any symbols from these libraries directly. And indeed this is fine for a shared library as the reproducer shows.However, the standard Linux linker (but not mold/gold/... it seems) has a unique behaviour where it tries to resolve symbols even in indirectly referenced libraries when the final executable is linked. The exact search is described under
--rpath-linkoption in theldman page.A simple test is to add the
tbbandxxhashlibrary paths toLD_LIBRARY_PATH: the linking now succeeds. However, this is not something we do:LD_LIBRARY_PATHis a variable for the run-time dynamic linker and should not be needed at link time.Shouldn't ROOT have both
TBB::tbbandxxHash::xxHashin theINTERFACE_LINK_LIBRARIESof the exported targets, where relevant, together with thefind_depency()calls in the case where these libraries are external to ROOT ?The alternative is that every client who links an executable has to know what libraries are ROOT builtins or not and has to modify their own
CMakeLists.txtfile accordingly.Having to set
LD_LIBRARY_PATHis similar cumbersome - for a bootstrap build we generate our run-time setup script at the end of the build where we know what is needed, and it is not straightforward to inject environment variables into the build environment from cmake itself (i.e. not having the user do it explicitly by sourcing some file etc.). Never mind that this is a variable meant to be used at run-time.Reproducer
On an Alma 9 host with cvmfs:
. ./setup.sh cmake -B build cmake --build buildsetup.sh
CMakeLists.txt
libexample.cxx
example.cxx
ROOT version
Installation method
Pre-built by SFT/LCG team on /cvmfs/sft-nightlies.cern.ch/lcg/nightlies/dev3/Mon/ROOT
Operating system
Linux Alma 9
Additional context
Was discussed in yesterday's LIM meeting and we were asked to open a ticket directly here.