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)