ROOT Dict Generation: Solve Issues with Inline Headers
We have/had some issues with the generated ROOT dictionary for objects if the original source header files are not available anymore at runtime:
|05:48:44.488| (STATUS) Initialized PRNG with configured seed 0
Error in cling::AutoLoadingVisitor::InsertIntoAutoLoadingState:
Missing FileEntry for MCTrack.hpp
requested to autoload type allpix::MCTrack
Error in cling::AutoLoadingVisitor::InsertIntoAutoLoadingState:
Missing FileEntry for MCParticle.hpp
requested to autoload type allpix::MCParticle
Error in cling::AutoLoadingVisitor::InsertIntoAutoLoadingState:
Missing FileEntry for DepositedCharge.hpp
requested to autoload type allpix::DepositedCharge
Error in cling::AutoLoadingVisitor::InsertIntoAutoLoadingState:
Missing FileEntry for Pixel.hpp
requested to autoload type allpix::Pixel
Error in cling::AutoLoadingVisitor::InsertIntoAutoLoadingState:
Missing FileEntry for Pulse.hpp
requested to autoload type allpix::Pulse
There seem to be several small issues.
Issue with correct order of macro commands
We should be first defining the library target via ADD_LIBRARY(MyObjects <...>)
and the call the command to generate the dictionary:
ADD_LIBRARY(AllpixObjects <...>)
<...>
ROOT_GENERATE_DICTIONARY(
AllpixObjectsDictionary
${CMAKE_CURRENT_SOURCE_DIR}/MCTrack.hpp
${CMAKE_CURRENT_SOURCE_DIR}/MCParticle.hpp
${CMAKE_CURRENT_SOURCE_DIR}/Pixel.hpp
${CMAKE_CURRENT_SOURCE_DIR}/PixelHit.hpp
<...>
MODULE
AllpixObjects
LINKDEF
${CMAKE_CURRENT_SOURCE_DIR}/Linkdef.h
OPTIONS
-inlineInputHeader
-I${CMAKE_CURRENT_SOURCE_DIR})
I understand this order is the correct one as per here even though I cannot explicitly add the generated AllpixObjectsDictionary.cxx
to my library source files. It seems to be added automatically.
Issue with Linkdef order
The dictionary documentation states that the order in the Linkdef
file is important:
When using template classes, the order of the pragma statements matters.
We did not obey this so far, since the #pragma
definitions for the references between objects (PointerWrapper
) were bunched at the end of the file:
#pragma link C++ class allpix::MCTrack + ;
#pragma link C++ class allpix::MCParticle + ;
<...>
#pragma link C++ class allpix::Object::PointerWrapper < allpix::MCTrack> + ;
#pragma link C++ class allpix::Object::PointerWrapper < allpix::MCParticle> + ;
#pragma link C++ class allpix::Object::BaseWrapper < allpix::MCTrack> + ;
#pragma link C++ class allpix::Object::BaseWrapper < allpix::MCParticle> + ;
This means, at the time of processing MCParticle
, no proper dictionary (or header) for PointerWrapper<MCTrack>
can be found. To correct this, the order must be strictly following dependency patterns - classes that are used or included in other classes need to be placed first such that all dependencies can be resolved also when inlining these headers for dictionary generation:
#pragma link C++ class allpix::MCTrack + ;
#pragma link C++ class allpix::Object::PointerWrapper < allpix::MCTrack> + ;
#pragma link C++ class allpix::Object::BaseWrapper < allpix::MCTrack> + ;
#pragma link C++ class allpix::MCParticle + ;
#pragma link C++ class allpix::Object::PointerWrapper < allpix::MCParticle> + ;
#pragma link C++ class allpix::Object::BaseWrapper < allpix::MCParticle> + ;
<...>
Issue with inlined headers
ROOT dictionaries know two ways of referencing headers at runtime. Either
- They are included at runtime either from the place the original source files were at compile time or they are searched in
ROOT_INCLUDE_PATH
- They are inlined during dictionary generation and therefore do not need to be present separately on the file system.
We intend to do the latter by specifying the -inputHeaderInline
when generating the dictionary. This is also working, however, the headers are inlined in the order they are presented to the macro - and here we have the same problem as for the Linkdef
file - the order up till now was rather random, leading to the above error: rootcling
walks through them in order and tries to include everything that is missing from the file system. Hence, we need to first include dependent headers and then the ones referencing them.
Sorry, a bit tech-y, but now we should be able to properly run this on installations without having the source headers around and without specifying ROOT_INCLUDE_PATH
explicitly, pointing to the post-install header location.