From 4f22e1831dc89334a9dab5dd5d5c1e3bc583b1b5 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Wed, 16 Sep 2026 15:26:34 +0200 Subject: [PATCH] Get rid of wrapper script for creating ROOT dictionaries The sole need for the wrapper was to properly handle warnings and complain on missing options. Since long rootcling is now gracefully handling both, so we remove the wrapper. --- cmake/AddRootDictionary.cmake | 43 +++++++---- cmake/RunRootcling.cmake | 49 ++++++++++++ cmake/rootcling_wrapper.sh.in | 138 ---------------------------------- packaging/CMakeLists.txt | 11 +-- 4 files changed, 77 insertions(+), 164 deletions(-) create mode 100644 cmake/RunRootcling.cmake delete mode 100755 cmake/rootcling_wrapper.sh.in diff --git a/cmake/AddRootDictionary.cmake b/cmake/AddRootDictionary.cmake index 16cbdec222043..84c479c3c2463 100644 --- a/cmake/AddRootDictionary.cmake +++ b/cmake/AddRootDictionary.cmake @@ -11,8 +11,7 @@ include_guard() -configure_file(${CMAKE_CURRENT_LIST_DIR}/rootcling_wrapper.sh.in - ${CMAKE_BINARY_DIR}/rootcling_wrapper.sh @ONLY) +set(O2_RUN_ROOTCLING_SCRIPT ${CMAKE_CURRENT_LIST_DIR}/RunRootcling.cmake) # # add_root_dictionary generates one dictionary to be added to a target. @@ -132,25 +131,37 @@ function(add_root_dictionary target) set(includeDirs $) set(includeDirs $) - list(LENGTH A_EXTRA_PATCH hasExtraPatch) - # add a custom command to generate the dictionary using rootcling + # the pcm dependencies (-m) are only meaningful where the modules are actually + # loaded from disk, which is not the case on macOS + set(pcmDeps $>) + if(APPLE) + set(pcmDeps) + endif() + + if(A_EXTRA_PATCH) + set(extraPatch -DPATCH=${CMAKE_CURRENT_LIST_DIR}/${A_EXTRA_PATCH}) + else() + set(extraPatch) + endif() + + # the arguments are joined with | so that they reach the script as a single + # argument, see RunRootcling.cmake # cmake-format: off + set(rootclingArgs + -f|${dictionaryFile}|-inlineInputHeader|-noGlobalUsingStd|-rmf|${rootmapFile}|-rml|$|-I$$<$:|-D$>$<$:|-m|$>|$) + + # add a custom command to generate the dictionary using rootcling add_custom_command( OUTPUT ${dictionaryFile} ${pcmFile} ${rootmapFile} VERBATIM COMMAND - ${CMAKE_BINARY_DIR}/rootcling_wrapper.sh - --rootmap_file ${rootmapFile} - --dictionary_file ${dictionaryFile} - --ld_library_path ${LD_LIBRARY_PATH} - --rootmap_library_name $ - --include_dirs -I$-I> - $<$:--compile_defs> - $<$:-D$-D>> - $<$:--extra-patch> - $<$:${CMAKE_CURRENT_LIST_DIR}/${A_EXTRA_PATCH}> - --pcmdeps "$>" - --headers "${headers}" + ${CMAKE_COMMAND} -E env LD_LIBRARY_PATH=${LD_LIBRARY_PATH} + ${CMAKE_COMMAND} + -DROOTCLING=${ROOT_rootcling_CMD} + -DDICTIONARY=${dictionaryFile} + ${extraPatch} + "-DARGS=${rootclingArgs}" + -P ${O2_RUN_ROOTCLING_SCRIPT} COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_CURRENT_BINARY_DIR}/${pcmBase} ${pcmFile} DEPENDS ${headers} "$>" ${A_EXTRA_PATCH}) diff --git a/cmake/RunRootcling.cmake b/cmake/RunRootcling.cmake new file mode 100644 index 0000000000000..7df914d31f54f --- /dev/null +++ b/cmake/RunRootcling.cmake @@ -0,0 +1,49 @@ +# Copyright 2019-2020 CERN and copyright holders of ALICE O2. +# See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +# All rights not expressly granted are reserved. +# +# This software is distributed under the terms of the GNU General Public +# License v3 (GPL Version 3), copied verbatim in the file "COPYING". +# +# In applying this license CERN does not waive the privileges and immunities +# granted to it by virtue of its status as an Intergovernmental Organization +# or submit itself to any jurisdiction. + +# Runs rootcling, optionally appends PATCH to the generated dictionary, and +# turns the "Unused class rule" warning into an error. +# +# rootcling only offers -failOnWarnings, which is all or nothing, so the +# output still has to be inspected to single out that one warning. +# +# ARGS is separated by | rather than ; so that it survives as a single +# argument through add_custom_command. + +if(NOT ROOTCLING OR NOT ARGS OR NOT DICTIONARY) + message(FATAL_ERROR "ROOTCLING, ARGS and DICTIONARY must all be given") +endif() + +string(REPLACE "|" ";" rootclingArgs "${ARGS}") + +execute_process(COMMAND ${ROOTCLING} ${rootclingArgs} + OUTPUT_VARIABLE output + ERROR_VARIABLE output + RESULT_VARIABLE status) + +if(output) + message("${output}") +endif() + +if(NOT status EQUAL 0) + file(REMOVE ${DICTIONARY}) + message(FATAL_ERROR "rootcling failed for ${DICTIONARY} with error code ${status}") +endif() + +if(output MATCHES "Warning: Unused class rule") + file(REMOVE ${DICTIONARY}) + message(FATAL_ERROR "please fix the warnings above about unused class rule") +endif() + +if(PATCH) + file(READ ${PATCH} patchContent) + file(APPEND ${DICTIONARY} "${patchContent}") +endif() diff --git a/cmake/rootcling_wrapper.sh.in b/cmake/rootcling_wrapper.sh.in deleted file mode 100755 index d5417c867bc38..0000000000000 --- a/cmake/rootcling_wrapper.sh.in +++ /dev/null @@ -1,138 +0,0 @@ -#!/bin/bash -e - -# rootcling_wrapper.sh -- wrap call to rootcling to trap some warnings -# we want to treat as errors : -# -# Warning: Unused class rule -# -# - -while [[ $# -gt 0 ]]; do - case "$1" in - --rootmap_library_name) - ROOTMAP_LIBRARY_NAME="$2" - shift 2 - ;; - --include_dirs) - INCLUDE_DIRS="$2" - shift 2 - ;; - --compile_defs) - COMPILE_DEFINITIONS="$2" - shift 2 - ;; - --headers) - HEADERS="$2" - shift 2 - ;; - --ld_library_path) - libpath="$2" - shift 2 - ;; - --dictionary_file) - DICTIONARY_FILE="$2" - shift 2 - ;; - --rootmap_file) - ROOTMAP_FILE="$2" - shift 2 - ;; - --pcmdeps) - PCMDEPS="$2" - shift 2 - ;; - --extra-patch) - EXTRA_PATCH="$2" - shift 2 - ;; - *) - if [[ -z "$1" ]]; then - shift - else - echo "Parameter unknown: $1" >&2 - exit 1 - fi - ;; - esac -done - -if [[ ! $ROOTMAP_LIBRARY_NAME ]]; then - echo "--rootmap_library_name option is mandatory but was not given" >&2 - exit 1 -fi - -if [[ ! $INCLUDE_DIRS ]]; then - echo "--include_dirs option is mandatory but was not given" >&2 - exit 1 -fi - -if [[ ! $DICTIONARY_FILE ]]; then - echo "--dictionary_file option is mandatory but was not given" >&2 - exit 1 -fi - -if [[ ! $ROOTMAP_FILE ]]; then - echo "--rootmap_file option is mandatory but was not given" >&2 - exit 1 -fi - -case $OSTYPE in - darwin*) - unset PCMDEPS - ;; - *) - ;; -esac - -LOGFILE=${DICTIONARY_FILE}.log - -echo @CMAKE_COMMAND@ -E env "LD_LIBRARY_PATH=$libpath" @ROOT_rootcling_CMD@ \ - -f $DICTIONARY_FILE \ - -inlineInputHeader \ - -noGlobalUsingStd \ - -rmf ${ROOTMAP_FILE} \ - -rml ${ROOTMAP_LIBRARY_NAME} \ - ${INCLUDE_DIRS//;/ } \ - ${COMPILE_DEFINITIONS//;/ } \ - ${PCMDEPS:+-m }${PCMDEPS//;/ -m } \ - ${HEADERS//;/ } \ - > ${LOGFILE} 2>&1 || ROOTCLINGRETVAL=$? - -@CMAKE_COMMAND@ -E env "LD_LIBRARY_PATH=$libpath" @ROOT_rootcling_CMD@ \ - -f $DICTIONARY_FILE \ - -inlineInputHeader \ - -noGlobalUsingStd \ - -rmf ${ROOTMAP_FILE} \ - -rml ${ROOTMAP_LIBRARY_NAME} \ - ${INCLUDE_DIRS//;/ } \ - ${COMPILE_DEFINITIONS//;/ } \ - ${PCMDEPS:+-m }${PCMDEPS//;/ -m } \ - ${HEADERS//;/ } \ - > ${LOGFILE} 2>&1 || ROOTCLINGRETVAL=$? - -# Add the extra patch file at the end of the generated dictionary. -# This is needed to inject custom streamers (e.g. for std::vector) -# to our dictionary. -if [ ! X"${EXTRA_PATCH}" = X ]; then - cat $EXTRA_PATCH >> ${DICTIONARY_FILE} -fi - -if [[ ${ROOTCLINGRETVAL:-0} != "0" ]]; then - cat ${LOGFILE} >&2 - rm -f $DICTIONARY_FILE - echo "ROOT CLING Dictionary generation of $DICTIONARY_FILE failed with error code $ROOTCLINGRETVAL" - exit 1 -fi - -MSG="Warning: Unused class rule" -if [[ -s ${LOGFILE} ]]; then - WARNINGS=$(grep -c "${MSG}" ${LOGFILE} || :) - if [[ ! $WARNINGS == 0 ]]; then - echo "ERROR: please fix the warnings below about unused class rule" >&2 - grep "$MSG" ${LOGFILE} >&2 - rm $DICTIONARY_FILE - exit 1 - fi -fi - -exit 0 diff --git a/packaging/CMakeLists.txt b/packaging/CMakeLists.txt index 628f9e895f6ef..c1d5058f7b090 100644 --- a/packaging/CMakeLists.txt +++ b/packaging/CMakeLists.txt @@ -17,16 +17,7 @@ install(EXPORT O2Targets FILE O2Targets.cmake) install(FILES O2Config.cmake ../cmake/AddRootDictionary.cmake + ../cmake/RunRootcling.cmake DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/O2) -install(FILES ../cmake/rootcling_wrapper.sh.in - DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/O2 - PERMISSIONS OWNER_READ - OWNER_WRITE - OWNER_EXECUTE - GROUP_READ - GROUP_EXECUTE - WORLD_READ - WORLD_EXECUTE) - install(DIRECTORY ../dependencies/ DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/O2)