I have a code which compiles with v5.34 but not with v6.04, not written by me for the part that matters here.
The peculiarity is that some classes are defined differently for executable compilation and for root library compilation. In particular my understanding is that part of the private part of the class is not included in the library with conditional compilation.
Here’s a sample:
So with v5.34 the part within the #ifndef is skipped both by rootcint (due to CINT) and by the following compilation of the dictionary (due to CHIMERA_ROOTLIB) and everything is smooth.
With v6.04 instead rootcint produces a .cc file with contains in the TStreamer also the variables which should not be there and its compilation fails.
g++ -c event/sbr_detector_dict.cc -o event/sbr_detector_dict_root.lo -Ievent -Imoduleswork -Iinterface -I. -Wall -Wno-non-virtual-dtor -pthread -std=c++11 -Wno-deprecated-declarations -m64 -I/usr/local/rde -g -fPIC
event/sbr_detector_dict.cc: In member function ‘virtual void sbr_detector::Streamer(TBuffer&)’:
event/sbr_detector_dict.cc:196:15: error: ‘last_evnum_read’ was not declared in this scope
R__b >> last_evnum_read;
I’m not familiar with how this whole process has changed in root 6 but I understand it’s kinda different. I learn now about cling but rootcint still exist though it makes something different (a .pcm file!?) so I guess it’s an alias for cling or something else now? I’m surprised though that CINT seems to be not defined any longer during its execution, is it really the case? If not why do those variables end up in my _cint.cc file?
if you want to exclude that portion of code from the dictionaries, you should use the __ROOTCLING__ preprocessor variable rather than __CINT__.
Yes, ROOT6 still provides an executable called rootcint for backward compatibility only: that is nothing else than an alias for rootcling (type rootcling -h for more information). The dictionary generator creates some C++ code and a ROOT-PCM, a special ROOT file which contains the information necessary for performing IO of the selected classes. That file must be located next to the library where the C++ code is compiled: it is read when the library is loaded and registers itself.
Note that ROOT6 and its dictionary generator is able to digest the lines which were excluded for ROOT5. For example the methods do not even leave a trace in the v6 dictionaries. As for the Ansatz about the TStreamer, I am not sure I get your argument but this is not strictly related to the porting to ROOT6 I guess We can treat it later.
ROOT 6.04 is a very old release. I would go for 6.10/02: given that you are porting your software to the 6 series, it’s worth picking a very recent one.
concerning replacement of __CINT__ with __ROOTCLING__ I tried that but it doesn’t work: the compilation of the dictionary still fails because the dictionary source code is generated wrongly.
For example this class is given a ctor which should be public only in the root dictionary and private in the actual program, so after the replacement the code reads like this:
class sbr_detector: public TObject {
#ifndef __ROOTCLING__
private: // This way db_detector can not be istantiated in Chimera
friend class detector_interface;
#else
public:
#endif
sbr_detector (): TObject() {}
but when I compile it I get:
g++ -c event/sbr_detector_dict.cc -o event/sbr_detector_dict.lo -Ievent -Imodules -Iframework -Iinterface -I. -Wall -Wno-non-virtual-dtor -pthread -std=c++11 -Wno-deprecated-declarations -m64 -I/usr/local/root/include -g -fPIC
In file included from event/sbr_detector_dict.cc:41:0:
./event/sbr_detector.hh: In function ‘void* ROOT::new_sbr_detector(void*)’:
./event/sbr_detector.hh:47:5: error: ‘sbr_detector::sbr_detector()’ is private
sbr_detector (): TObject() {}
Please do not hide data members from rootcling. That changes the object layout, rendering the “interpreted” object incompatible with what the lbvrary expects. In general, in first approximation, do not hide anything in ROOT 6 dictionaries.
__ROOTCLING__ is defined when running rootcling or genreflex. The source it creates does not define __ROOTCLING__ - which explains the compilation error you see. You could reword this as
#if !defined(__ROOTCLING__) && !defined(R__DICTIONARY)
private: // This way db_detector can not be istantiated in Chimera
friend class detector_interface;
#else
public:
#endif
R__DICTIONARY is defined inside dictionary sources.
The ABI mismatch is a symptom of ROOT built with a different std library version (and thus GCC version) than what you are currently using. I will remove the warning at some point. (This has side-effects on our caching of the content of the standard library headers.)
private: // This way db_detector can not be istantiated in Chimera
friend class detector_interface;
...
sbr_detector (): TObject() {}
Alternatively you can use the following pattern (and not use any#ifdef at all.
class TRootIOCtor; // Special type (that is never actually declared) to mark the I/O constructor.
class sbr_detector: public TObject {
...
public:
// if need be:
// sbr_detector() = delete;
sbr_detector(TRootIOCtor *) : TObject() {}
....
};