Skip to content

Link errors for tbb and xxhash libraries #21991

@rhauser

Description

@rhauser

Check duplicate issues.

  • Checked for duplicates

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.

Metadata

Metadata

Type

No type

Projects

Status

No status

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions