Skip to content

[RF][CMake] Allow building RooBatchCompute_CUDA standalone - #23212

Open
guitargeek wants to merge 1 commit into
root-project:masterfrom
guitargeek:issue-18641
Open

[RF][CMake] Allow building RooBatchCompute_CUDA standalone#23212
guitargeek wants to merge 1 commit into
root-project:masterfrom
guitargeek:issue-18641

Conversation

@guitargeek

Copy link
Copy Markdown
Contributor

The CUDA backend of RooBatchCompute is the only part of ROOT that needs the CUDA toolkit, and it is a plugin: libRooBatchCompute never links against it, it loads it by name at runtime from RooBatchCompute::initCUDA() with gSystem->Load("libRooBatchCompute_CUDA"). There is therefore no technical reason why it has to be built together with the rest of ROOT, and packagers (conda-forge in particular) would like to ship a CUDA-free ROOT plus a separate package that only provides the GPU kernels. So far that required carrying a hand-written CMakeLists.txt downstream.

roofit/batchcompute/CMakeLists.txt now doubles as the top-level CMakeLists.txt of a standalone project that builds nothing but libRooBatchCompute_CUDA:

  cmake -S <root-src>/roofit/batchcompute -B build \
        -DCMAKE_PREFIX_PATH=<root-prefix>
  cmake --build build
  cmake --install build

When the file is processed as the top-level list file it sets up its own project(), finds the installed ROOT, enables the CUDA language and skips the part that defines libRooBatchCompute and the CPU backends. The definition of the CUDA target itself is shared between the two modes, so the list of source files exists only once. In standalone mode the target is created with a plain add_library() rather than ROOT_LINKER_LIBRARY(), because the latter relies on variables that only exist inside a ROOT build tree; it links against the imported ROOT::RooBatchCompute target, which owns the dispatchCUDA pointer that the library overwrites when it is loaded, and it takes the private headers straight from the source tree since res/ is not part of the ROOT installation. Like ROOT_LINKER_LIBRARY() it forces the "lib" prefix, which on Windows is not what CMake would pick by default but is the name gSystem->Load() asks for, and like the ROOT build it defaults CMAKE_BUILD_TYPE to Release. A ROOT installation that has no RooFit is rejected with an explicit error, and one that already ships libRooBatchCompute_CUDA gets a warning that the default install destination would overwrite it.

By default the library is installed into the library directory of the ROOT installation it was configured against, which is where the dispatcher looks for it; RooBatchCompute_CUDA_INSTALL_LIBDIR overrides that and accepts a relative path so that the usual CMAKE_INSTALL_PREFIX/DESTDIR staging works.

The regular ROOT build is unaffected: -Dcuda=ON still builds the CUDA backend exactly as before.

Closes #18641

🤖 Done with the help of AI

The CUDA backend of RooBatchCompute is the only part of ROOT that needs the
CUDA toolkit, and it is a plugin: libRooBatchCompute never links against it,
it loads it by name at runtime from RooBatchCompute::initCUDA() with
gSystem->Load("libRooBatchCompute_CUDA"). There is therefore no technical
reason why it has to be built together with the rest of ROOT, and packagers
(conda-forge in particular) would like to ship a CUDA-free ROOT plus a
separate package that only provides the GPU kernels. So far that required
carrying a hand-written CMakeLists.txt downstream.

roofit/batchcompute/CMakeLists.txt now doubles as the top-level CMakeLists.txt
of a standalone project that builds nothing but libRooBatchCompute_CUDA:

  cmake -S <root-src>/roofit/batchcompute -B build \
        -DCMAKE_PREFIX_PATH=<root-prefix>
  cmake --build build
  cmake --install build

When the file is processed as the top-level list file it sets up its own
project(), finds the installed ROOT, enables the CUDA language and skips the
part that defines libRooBatchCompute and the CPU backends. The definition of
the CUDA target itself is shared between the two modes, so the list of source
files exists only once. In standalone mode the target is created with a plain
add_library() rather than ROOT_LINKER_LIBRARY(), because the latter relies on
variables that only exist inside a ROOT build tree; it links against the
imported ROOT::RooBatchCompute target, which owns the dispatchCUDA pointer that
the library overwrites when it is loaded, and it takes the private headers
straight from the source tree since res/ is not part of the ROOT installation.
Like ROOT_LINKER_LIBRARY() it forces the "lib" prefix, which on Windows is not
what CMake would pick by default but is the name gSystem->Load() asks for, and
like the ROOT build it defaults CMAKE_BUILD_TYPE to Release. A ROOT
installation that has no RooFit is rejected with an explicit error, and one
that already ships libRooBatchCompute_CUDA gets a warning that the default
install destination would overwrite it.

By default the library is installed into the library directory of the ROOT
installation it was configured against, which is where the dispatcher looks for
it; RooBatchCompute_CUDA_INSTALL_LIBDIR overrides that and accepts a relative
path so that the usual CMAKE_INSTALL_PREFIX/DESTDIR staging works.

The regular ROOT build is unaffected: -Dcuda=ON still builds the CUDA backend
exactly as before.

Closes root-project#18641

🤖 Done with the help of AI

@hageboeck hageboeck left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good idea! I might have found a few improvements.


cmake_minimum_required(VERSION 3.20 FATAL_ERROR)

project(RooBatchComputeCUDA LANGUAGES CXX)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
project(RooBatchComputeCUDA LANGUAGES CXX)
project(RooBatchComputeCUDA LANGUAGES CXX CUDA)

Comment on lines +32 to +35
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
set(CMAKE_BUILD_TYPE Release CACHE STRING
"Specifies the build type on single-configuration generators" FORCE)
endif()

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not good to CACHE ... FORCE. Maybe it's better to warn?

Some packagers unset the build type and put compiler flags in CMAKE_CXX_FLAGS, so your strategy would clash with theirs.

set(CMAKE_CUDA_STANDARD ${CMAKE_CXX_STANDARD})
endif()

enable_language(CUDA)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This might be unnecessary if you enable it from the beginning.

@github-actions

github-actions Bot commented Sep 1, 2026

Copy link
Copy Markdown

Test Results

    22 files      22 suites   3d 13h 17m 33s ⏱️
 3 862 tests  3 861 ✅ 0 💤 1 ❌
75 843 runs  75 842 ✅ 0 💤 1 ❌

For more details on these failures, see this check.

Results for commit 66cdea1.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[RF][CMake] Make it possible to build RooBatchCompute_CUDA standalone without custom CMake lists file

3 participants