Dear ROOTers,
I found one problem in adapting our cmake build system to ROOT 6.
Our software is split into several libraries, and correspondingly incorporates several dictionaries /rootmaps / PCMs.
We use a slightly adapted version of the ROOTNewMacros-cmake macros (to adapt to our file naming conventions).
One case seems to be broken in dependency generation, and I believe it is also broken in ROOTNewMacros. Imagine the following situation:
- A “base” library which incorporates something as basic as CBTObject (something inheriting TObject). It ends up in something like libcbbase.so, cbbaseDict_rdict.pcm, libcbbase.rootmap.
- Several “addons” libraries, e.g. “tracking”, which include these basic headers and derive from such objects, so you get e.g. libbgotracking.so, bgotrackingDict_rdict.pcm, libbgotracking.rootmap.
Now, the PCM for the “base” only depends on the headers which go into the “base” library. This means it will only be rebuilt if e.g. “CBTObject.h” changes.
The PCM for “tracking” will be rebuilt ONLY if the headers taking part in the “clustering” library were changed.
Now, I observe something like the following sometimes (please ignore the strange markup, we have our own error-printer):
<ERROR> 2015-11-23 15:05:02 <ROOT-TProtoClass::Fi>(not set ) data member with index 20 is not found in class BTAbstractTrackFitter
<ERROR> 2015-11-23 15:05:02 < ROOT-CreateRealData>(not set ) Cannot find data member # 20 of class BTAbstractTrackFitter for parent BTGFTrackFitting!
I investigated a bit and it seems to me that this happens if:
- The datamembers of a basic class such as “CBTObject.h” are changed.
- The PCM for “base” is regenerated, but the PCM e.g. for “tracking” is not recreated, since the direct headers for “tracking” did not change. Only headers included in headers which are part of the “tracking” library did change.
Note this also holds for Class-version=0 classes.
So my question, finally, is: How do I express the PCM regeneration rule correctly?
Depending on the headers which go into the libraries is not correct, since “rootcling” is of course clever and also looks at the included headers. The PCM then remembers the data-layout of the base-classes, and is not recreated if the base-class layout changes, since cmake “does not parse the headers”.
I believe this is also wrong in ROOTNewMacros itself, but probably does not show up since TObject (or something else which is basic) is not changed significantly often.
Of course, possible solutions are:
- “IMPLICIT_DEPENDS CXX” of cmake. This might work (I guess?), but is not ninja-compatible and a very recent feature (ROOT also does not use it).
- Rerunning rootcling each time. This is slow, and I have also not yet figured out how to instruct cmake to always revisit a target even if the output files are still there.
- Using “rootcling -m cbbaseDict_rdict.pcm” and so on, but I am unsure that this will help, and PCM-dependencies are unclear to cmake, and I also think “-m” is not even effective yet.
Any other suggestions on how to solve this?
At the moment I am still considering the option of always rerunning rootcling (i.e. forcibly deleting the in-build-tree PCMs) since that seems to be the only viable (but expensive) option.
It would already be helpful if ROOT / Cling could check at runtime whether the related PCMs are incompatible with the parsed headers in a more clear way than “data member with index 20 is not found in class BTAbstractTrackFitter”, then I could at least instruct the user in case this happens (or have a post-build PCM-checking functionality).
Cheers (and I am really looking forward to real C++ modules ),
Oliver