diff --git a/DataFormats/Detectors/TPC/CMakeLists.txt b/DataFormats/Detectors/TPC/CMakeLists.txt index 2cc69e16001a6..5aed01a9772c1 100644 --- a/DataFormats/Detectors/TPC/CMakeLists.txt +++ b/DataFormats/Detectors/TPC/CMakeLists.txt @@ -40,6 +40,7 @@ o2_add_library( o2_target_root_dictionary( DataFormatsTPC + EXTRA_PATCH src/VectorPadflagsCustomStreamer.cxx HEADERS include/DataFormatsTPC/ClusterGroupAttribute.h include/DataFormatsTPC/ClusterNative.h include/DataFormatsTPC/ClusterNativeHelper.h diff --git a/DataFormats/Detectors/TPC/src/DataFormatsTPCLinkDef.h b/DataFormats/Detectors/TPC/src/DataFormatsTPCLinkDef.h index fd5abca99cb0f..8659e6a2e43eb 100644 --- a/DataFormats/Detectors/TPC/src/DataFormatsTPCLinkDef.h +++ b/DataFormats/Detectors/TPC/src/DataFormatsTPCLinkDef.h @@ -22,6 +22,7 @@ #pragma link C++ class o2::tpc::ClusterHardwareContainerFixedSize < 8192> + ; #pragma link C++ class o2::tpc::ClusterNativeContainer + ; #pragma link C++ class o2::tpc::Digit + ; +// pragma link C++ enum o2::tpc::PadFlags +; // enum itself #pragma link C++ class o2::tpc::ZeroSuppressedContainer8kb + ; #pragma link C++ class std::vector < o2::tpc::ClusterNative> + ; #pragma link C++ class std::vector < o2::tpc::ClusterNativeContainer> + ; @@ -29,6 +30,7 @@ #pragma link C++ class std::vector < o2::tpc::ClusterHardwareContainerFixedSize < 8192>> + ; #pragma link C++ class std::vector < o2::tpc::ClusterHardwareContainer8kb> + ; #pragma link C++ class std::vector < o2::tpc::Digit> + ; +// pragma link C++ class std::vector < o2::tpc::PadFlags> + ; #pragma link C++ class std::vector < o2::tpc::ZeroSuppressedContainer8kb> + ; #pragma link C++ class o2::tpc::TrackTPC + ; #pragma link C++ class o2::tpc::LaserTrack + ; diff --git a/DataFormats/Detectors/TPC/src/VectorPadflagsCustomStreamer.cxx b/DataFormats/Detectors/TPC/src/VectorPadflagsCustomStreamer.cxx new file mode 100644 index 0000000000000..f7cb9285b8884 --- /dev/null +++ b/DataFormats/Detectors/TPC/src/VectorPadflagsCustomStreamer.cxx @@ -0,0 +1,56 @@ +// Copyright 2019-2025 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. + +using std::vector; + +void VectorPadFlagsStreamer(TBuffer& R__b, void* objp) +{ + std::vector* obj = static_cast*>(objp); + if (R__b.IsReading()) { + std::vector R__stl; + R__stl.clear(); + int R__n; + R__b >> R__n; + R__stl.reserve(R__n); + for (int R__i = 0; R__i < R__n; R__i++) { + Int_t readtemp; + R__b >> readtemp; + R__stl.push_back(readtemp); + } + auto data = reinterpret_cast(R__stl.data()); + for (int i = 0; i < R__n; ++i) { + obj->push_back(static_cast(data[i])); + } + } else { + // We always save things with the old format. + R__b << (int)obj->size() / 2; + for (size_t i = 0; i < obj->size(); i++) { + R__b << (short)obj->at(i); + } + } +} + +#define RootStreamerLocal(name, STREAMER) \ + namespace ROOT \ + { \ + \ + /** \cond HIDDEN_SYMBOLS */ \ + static auto _R__UNIQUE_(R__dummyStreamer) = \ + []() { TClass::GetClass()->SetStreamerFunc(STREAMER); return 0; }(); \ + /** \endcond */ \ + R__UseDummy(_R__UNIQUE_(R__dummyStreamer)); \ + } + +// Let's not try to fix the old ROOT version, so that we can build +// the new ROOT with the patched code in the CI. +#if ROOT_VERSION_CODE >= ROOT_VERSION(6, 33, 00) +RootStreamerLocal(vector, VectorPadFlagsStreamer); +#endif diff --git a/cmake/AddRootDictionary.cmake b/cmake/AddRootDictionary.cmake index 0dd68a352d1ce..17fdd2bd286c0 100644 --- a/cmake/AddRootDictionary.cmake +++ b/cmake/AddRootDictionary.cmake @@ -51,7 +51,7 @@ function(add_root_dictionary target) 1 A "" - "LINKDEF" + "LINKDEF;EXTRA_PATCH" "HEADERS;BASENAME") if(A_UNPARSED_ARGUMENTS) message( @@ -112,7 +112,7 @@ function(add_root_dictionary target) set(pcmBase ${dictionary}_rdict.pcm) set(pcmFile ${lib_output_dir}/${pcmBase}) set(rootmapFile ${lib_output_dir}/lib${basename}.rootmap) - + set(O2_TARGETPCMMAP_TARGET "${O2_TARGETPCMMAP_TARGET};${target}" CACHE INTERNAL "target/PCM map (target)") set(O2_TARGETPCMMAP_PCM "${O2_TARGETPCMMAP_PCM};${pcmFile}" CACHE INTERNAL "target/PCM map (pcm)") @@ -132,6 +132,7 @@ 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 # cmake-format: off add_custom_command( @@ -146,11 +147,13 @@ function(add_root_dictionary target) --include_dirs -I$-I> $<$:--compile_defs> $<$:-D$-D>> + $<$:--extra-patch> + $<$:${CMAKE_CURRENT_LIST_DIR}/${A_EXTRA_PATCH}> --pcmdeps "$" --headers "${headers}" COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_CURRENT_BINARY_DIR}/${pcmBase} ${pcmFile} - DEPENDS ${headers} "$") + DEPENDS ${headers} "$" ${A_EXTRA_PATCH}) # cmake-format: on # add dictionary source to the target sources diff --git a/cmake/O2TargetRootDictionary.cmake b/cmake/O2TargetRootDictionary.cmake index f5d630dd10569..0b91d751a4802 100644 --- a/cmake/O2TargetRootDictionary.cmake +++ b/cmake/O2TargetRootDictionary.cmake @@ -55,14 +55,9 @@ function(o2_target_root_dictionary baseTargetName) 1 A "" - "LINKDEF" + "LINKDEF;EXTRA_PATCH" "HEADERS") - if(A_UNPARSED_ARGUMENTS) - message( - FATAL_ERROR "Unexpected unparsed arguments: ${A_UNPARSED_ARGUMENTS}") - endif() - if(${ARGC} LESS 1) message( FATAL_ERROR @@ -96,6 +91,13 @@ function(o2_target_root_dictionary baseTargetName) # now that we have the O2 specific stuff computed, delegate the actual work to # the add_root_dictionary function - add_root_dictionary(${target} HEADERS ${A_HEADERS} LINKDEF ${A_LINKDEF}) +if(NOT A_EXTRA_PATCH) + add_root_dictionary(${target} HEADERS ${A_HEADERS} LINKDEF ${A_LINKDEF}) +else() + add_root_dictionary(${target} + EXTRA_PATCH ${A_EXTRA_PATCH} + HEADERS ${A_HEADERS} + LINKDEF ${A_LINKDEF}) +endif() endfunction() diff --git a/cmake/rootcling_wrapper.sh.in b/cmake/rootcling_wrapper.sh.in index 76ce8c8115ca9..d5417c867bc38 100755 --- a/cmake/rootcling_wrapper.sh.in +++ b/cmake/rootcling_wrapper.sh.in @@ -41,6 +41,10 @@ while [[ $# -gt 0 ]]; do PCMDEPS="$2" shift 2 ;; + --extra-patch) + EXTRA_PATCH="$2" + shift 2 + ;; *) if [[ -z "$1" ]]; then shift @@ -82,6 +86,18 @@ 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 \ @@ -94,6 +110,13 @@ LOGFILE=${DICTIONARY_FILE}.log ${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