Managing built-in and dnf versions of XRootD in CMake project

Short description

Hello!
I have a problem with location of headers like XrdCl/XrdClFileSystem.hh: they are in ${ROOTSYS}/include with built-in XRootD and elsewhere with external XRootD installation.
How to deal with both cases in CMake?

I am asking this here because I think this is more ROOT-specific question.

Long Description

I am working on a CMake project which depends in particular on XRootD.
There are two setups to deal with: one with ROOT built from source and the other with ROOT installed via dnf.

On machines with ROOT built from source the project compiles normally.
I’ve started experimenting with ROOT shipped via dnf and discovered that project doesn’t compile with it, showing errors like this:

/usr/include/root/TNetXNGFile.h:27:10: fatal error: XrdCl/XrdClFileSystem.hh: No such file or directory
   27 | #include <XrdCl/XrdClFileSystem.hh>

Apparently, this is because ROOT from dnf requires external XRootD (see setup descriptions in the end of message).
I have fixed this by adding following lines to CMakeFiles.txt:

find_package(XRootD REQUIRED)
if (NOT XROOTD_FOUND)
    message(SEND_ERROR "Failed to find XRootD")
    return()
endif()
include_directories(${XROOTD_INCLUDE_DIRS})

However, it breaks compilation with ROOT built from source, featuring built-in XRootD:

CMake Error at CMakeLists.txt:7 (find_package):
  By not providing "FindXRootD.cmake" in CMAKE_MODULE_PATH this project has
  asked CMake to find a package configuration file provided by "XRootD", but
  CMake did not find one.

  Could not find a package configuration file provided by "XRootD" with any
  of the following names:

    XRootDConfig.cmake
    xrootd-config.cmake

  Add the installation prefix of "XRootD" to CMAKE_PREFIX_PATH or set
  "XRootD_DIR" to a directory containing one of the above files.  If "XRootD"
  provides a separate development package or SDK, be sure it has been
  installed.

So in order to handle both cases, it seems that I have to check if XRootD is built-in.
I couldn’t find any information on this.

Or is there another approach?

Setup built from source

ROOT built from source on AlmaLinux 9.
root-config --features yields both builtin_xrootd and xrootd.

ROOT v6.30/06
Built for linuxx8664gcc on May 14 2024, 12:41:16
From tags/v6.30.06-0-g4f4e716372@v6.30.06-0-g4f4e716372
With c++ (GCC) 11.4.1 20231218 (Red Hat 11.4.1-3)
Binary directory: /usr/local/bin

Setup via dnf

ROOT installed on AlmaLinux 9 via dnf install root xrootd (I don’t remember exact command).
root-config --features yields only xrootd.

ROOT v6.30/06
Built for linuxx8664gcc on Apr 25 2024, 00:00:00
From heads/master@tags/v6-30-06
With g++ (GCC) 11.4.1 20230605 (Red Hat 11.4.1-2)
Binary directory: /usr/bin

Adding @bellenot in the loop.

So root-config --features is correct in both cases and you can use it to determine if Xrootd used by ROOT is builtin or not. Note also that ROOTConfig.cmake contains this information. I don’t think this can be handled in ROOT itself, but I can try if you want, though I would need some time to set-up a Virtual Machine with the full environment and make some tests…

1 Like

P.S. I think you can use if(ROOT_builtin_xrootd_FOUND) in your CMakeLists.txt

1 Like

That works, thank you! I’ve ended up with

if (NOT ROOT_builtin_xrootd_FOUND)
    find_package(XRootD REQUIRED)
    if (NOT XROOTD_FOUND)
        message(SEND_ERROR "Failed to find XRootD")
        return()
    endif()
endif()
include_directories(${XROOTD_INCLUDE_DIRS})

Also I’ve looked into ROOTConfig.cmake, and then in ROOTConfig.cmake.in. I’ve found

foreach(_opt ${_root_enabled_options})
  set(ROOT_${_opt}_FOUND TRUE)
endforeach()

So clause like if(ROOT_${_opt}_FOUND) should be applicable for any enabled ROOT build option. Thanks for the insight!

1 Like

You’re very welcome!

1 Like