Problem with rootcint (or cling?) while porting to root 6

Hi,

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:

  private:
    bool b_trigger_enabled, b_crystal_enabled, b_veto_enabled, b_mctruth_enabled;
    int total_skipped_events;
    std::map<int, std::map<std::string, int> > skipped_events; // index are trigger type and module_name
    std::vector<int> disabled_channels_v;
    std::vector<int> user_disabled_channels_v;
    std::vector<std::string> disabled_crystal_channel_properties_v;
    std::vector<std::string> disabled_veto_channel_properties_v;

#if !defined (__CINT__) && !defined (_CHIMERA_ROOTLIB_)
    bool check_crystal_property (const std::string& p);
    bool check_veto_property    (const std::string& p);
    bool check_vector_property  (const std::string& p, const std::vector<std::string> &v);
    bool check_crystal_property (const std::string& p, const std::vector<std::string> &v);
    bool check_veto_property    (const std::string& p, const std::vector<std::string> &v);
    void compute_disabled_channels (int run_number);
    void disable_lg (int, const std::string&);
    int last_evnum_read, next_evnum_to_read;
    float scaling_factor;
    bool use_db;
#endif

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?

Thanks for help
Davide

Hi Davide,

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 :slight_smile: 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.

Cheers,
D

Dear Danilo, thanks for your help

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() {}

as if __ROOTCLING__ was not defined

I also get these warnings for every class in the dictionary:

Warning in cling::IncrementalParser::CheckABICompatibility():
  C++ ABI mismatch, compiled with __GLIBCXX__ v20140911 running with v20150623

not sure what it is

Hi Davide,

  • 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.)

Let me know if there’s anything still unclear!

Cheers, Axel.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.

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() {}
....
};

Cheers,
Philippe.