ROOT6: interpreter include path & rootcling

Hello
I am using the latest version of git branch v6-02-00-patches on Ubuntu14.10, updated & recompiled this morning. This is a cmake build, installation directory is completely different from source directory.
The environment is setup by running $ROOTSYS/bin/thisroot.csh.

Sorry for the long and winding post, I’ve tried to detail as much as I can, the basic problem
is the way cling seems to store and use information on the include paths needed to load classes
from .so libraries. There is a work-around, which is to give the runtime install path as an include
directive to rootcling, but this seems a bit dangerous (headers from an out-of-date installation could
get mixed into the compilation), and in general there seems to be a strange mix of source & installation
include paths even for stand-alone ROOT.

When I run ROOT and look at the interpreter include paths at start-up I see:

TString syspath = gSystem->GetIncludePath()
(TString &) “[color=#0000FF]-I$ROOTSYS/include -I/home/john/software/build/root-v6-02-00/etc -I/home/john/software/build/root-v6-02-00/include[/color] -I/usr/include/c++/4.9 -I/usr/include/x86_64-linux-gnu/c++/4.9 -I/usr/include/c++/4.9/backward [color=#FF0000]-I/home/john/software/sources/root/root.git/interpreter/cling/include -I/home/john/software/sources/root/root.git/CMakeBuild-v6-02-00-patches/interpreter/cling/include[/color] [color=#0000FF]-I/home/john/software/build/root-v6-02-00/etc/cling[/color] -I. [color=#FF0000]-I/home/john/software/sources/root/root.git -I/home/john/software/sources/root/root.git/CMakeBuild-v6-02-00-patches/include -I/home/john/software/sources/root/root.git/graf3d/g3d/inc -I/home/john/software/sources/root/root.git/gui/gui/inc -I/home/john/software/sources/root/root.git/io/io/inc -I/home/john/software/sources/root/root.git/core/base/…/textinput/src -I/home/john/software/sources/root/root.git/CMakeBuild-v6-02-00-patches/core/base/ -I/home/john/software/sources/root/root.git/CMakeBuild-v6-02-00-patches/core/rint/ -I/home/john/software/sources/root/root.git/CMakeBuild-v6-02-00-patches/core/thread/ -I/home/john/software/sources/root/root.git/CMakeBuild-v6-02-00-patches/io/io/ -I/home/john/software/sources/root/root.git/hist/hist/inc -I/home/john/software/sources/root/root.git/CMakeBuild-v6-02-00-patches/math/mathcore/[/color]”[1272]

In blue are paths in the installation, in red are paths in the source.
I am a little surprised to see a mix of source and installation directories in the include paths.

Similar behaviour also occurs if I load my own .so, for which the dictionaries/rootmaps were generated using rootcling as follows:

rootcling -v -f KVMultiDetbaseDict.cpp -rml libKVMultiDetbase.so -rmf libKVMultiDetbase.rootmap -c -p -Ibase -DWITH_OPENGL -I/home/john/software/sources/kaliveda/1.9_major_rearrangements base/KVMemoryPool.h base/KVIntegerList.h [....] base/KVParameterList.h base/KVSystemFile.h base/KVMultiDetbaseLinkDef.h

root [0] gSystem->Load(“libKVMultiDetbase”)
root [1] TString syspath = gSystem->GetIncludePath()
(TString &) “-I$ROOTSYS/include -I/home/john/software/build/root-v6-02-00/etc [… all the stuff from above …] [color=#FF0000]-I/home/john/software/sources/root/root.git/CMakeBuild-v6-02-00-patches/math/matrix/ -I/home/john/software/sources/root/root.git/CMakeBuild-v6-02-00-patches/hist/hist/ -I/home/john/software/sources/root/root.git/CMakeBuild-v6-02-00-patches/graf2d/graf/ -I/home/john/software/sources/root/root.git/CMakeBuild-v6-02-00-patches/graf2d/gpad/ -I/home/john/software/sources/root/root.git/gui/ged/inc -I/home/john/software/sources/root/root.git/CMakeBuild-v6-02-00-patches/gui/gui/ -I/home/john/software/sources/root/root.git/CMakeBuild-v6-02-00-patches/net/net/ -I/home/john/software/sources/root/root.git/CMakeBuild-v6-02-00-patches/tree/tree/ -I/home/john/software/sources/root/root.git/CMakeBuild-v6-02-00-patches/gui/ged/ -I/home/john/software/sources/root/root.git/proof/proofplayer/inc -I/home/john/software/sources/root/root.git/CMakeBuild-v6-02-00-patches/proof/proof/ -I/home/john/software/sources/root/root.git/CMakeBuild-v6-02-00-patches/proof/proofplayer/ -I/home/john/software/sources/root/root.git/CMakeBuild-v6-02-00-patches/hist/spectrum/ -I/home/john/software/sources/root/root.git/CMakeBuild-v6-02-00-patches/geom/geom/ -I/home/john/software/sources/root/root.git/CMakeBuild-v6-02-00-patches/graf3d/g3d/ -I/home/john/software/sources/root/root.git/graf3d/ftgl/inc -I/usr/include/freetype2 -I/home/john/software/sources/root/root.git/CMakeBuild-v6-02-00-patches/graf3d/gl/ -I/home/john/software/sources/root/root.git/CMakeBuild-v6-02-00-patches/math/physics/ -I/home/john/software/sources/root/root.git/CMakeBuild-v6-02-00-patches/graf2d/postscript/[/color] [color=#008000]-Ibase -I/home/john/software/sources/kaliveda/1.9_major_rearrangements -I/home/john/software/sources/kaliveda/1.9_major_rearrangements/KVMultiDet/[/color]”[2980]

Now I have, in red, a lot of extra include paths inside the ROOT source directory (these seem to correspond, at least in part, to the ROOT libraries with which I link my .so), and, in green, include paths in the source directories of my .so. These seem to correspond to the directives given to rootcling when the dictionary is generated. The correct include path, -I/home/john/.kvroot-1.9-rearranged_gcc-4.9.1_x86_64_root-6.02.02/include, corresponding to the installed header files, is missing: note that it was not given in the call to rootcling. However, everything seems to work fine, and I can use all of the classes in my .so at the ROOT prompt:

root [0] KVString toto = "a list of words"
(KVString &) "a list of words"[15]
root [1] toto.Begin(" ")
root [2] toto.Next()
(KVString) "a"[1]
root [3] toto.Next()
(KVString) "list"[4]
root [4] toto.Next()
(KVString) "of"[2]
root [5] toto.Next()
(KVString) "words"[5]
root [6] toto.Next()
(KVString) ""[0]

So far, so good. Now I try to load a second .so which contains classes from a second subdirectory of my project, “particles/”, which only depend on the code (.h & .cpp) in “particles/” or on the base-class definitions (.h) in “base/”. For this .so, the dictionary is generated like so:

rootcling -v -f KVMultiDetparticlesDict.cpp -rml libKVMultiDetparticles.so -rmf libKVMultiDetparticles.rootmap -c -p -Iparticles -Ibase -DWITH_OPENGL -I/home/john/software/sources/kaliveda/1.9_major_rearrangements particles/KVMassExcessTable.h particles/KVElementDensityTable.h particles/KVNucleus.h [.....] particles/KVMultiDetparticlesLinkDef.h
and the .so is linked with the base class library at creation:

Now if I load this library into ROOT and try to instantiate one of the classes it contains, I get:

root [0] gSystem->Load("libKVMultiDetparticles") (int) 0 root [1] KVNucleus n In file included from input_line_54:16: In file included from /home/john/software/sources/kaliveda/1.9_major_rearrangements/KVMultiDet/particles/KVMassExcessTable.h:7: /home/john/software/sources/kaliveda/1.9_major_rearrangements/KVMultiDet/particles/KVNuclDataTable.h:13:10: fatal error: 'KVString.h' file not found #include "KVString.h" ^ root.exe: /home/john/software/sources/root/root.git/interpreter/cling/lib/Interpreter/IncrementalParser.cpp:615: void cling::IncrementalParser::rollbackTransaction(cling::Transaction*): Assertion `T == getLastTransaction() && "We always must revert the last T"' failed. ganp115:~% [exit from ROOT]
Note that KVString was used in the previous example i.e. it works. If I instantiate a KVString object before attempting to instantiate the KVNucleus object, the result is exactly the same (no problem with the KVString instantiation). If I attempt to use autocompletion in order to see the list of available KVNucleus constructors before trying to use one, I get:

root [2] KVNucleus n(<TAB>
In file included from input_line_57:16:
In file included from /home/john/software/sources/kaliveda/1.9_major_rearrangements/KVMultiDet/particles/KVMassExcessTable.h:7:
/home/john/software/sources/kaliveda/1.9_major_rearrangements/KVMultiDet/particles/KVNuclDataTable.h:13:10: fatal error: 'KVString.h' file not found
#include "KVString.h"
         ^
Error in <TInterpreter::AutoParse>: Error parsing payload code for class KVNucleus with content:


#ifndef G__VECTOR_HAS_CLASS_ITERATOR
  #define G__VECTOR_HAS_CLASS_ITERATOR 1
#endif
#ifndef WITH_OPENGL
  #define WITH_OPENGL 1
#endif

#define _BACKWARD_BACKWARD_WARNING_H
#include "particles/KVMassExcessTable.h"
#include "particles/KVElementDensityTable.h"
#include "particles/KVNucleus.h"
#include "particles/KVNuclData.h"
#include "particles/KVParticleCondition.h"
#include "particles/KVMassExcess.h"
#include "particles/KVNDTManager.h"
#include "particles/KVElementDensity.h"
#include "particles/KVNuclDataTable.h"
#include "particles/KVChargeRadius.h"
#include "particles/KVLifeTime.h"
#include "particles/KVLifeTimeTable.h"
#include "particles/KVAbundance.h"
#include "particles/KVAbundanceTable.h"
#include "particles/KVParticle.h"
#include "particles/KVChargeRadiusTable.h"
#include "particles/KVSimNucleus.h"

#undef  _BACKWARD_BACKWARD_WARNING_H

In file included from input_line_58:16:
In file included from /home/john/software/sources/kaliveda/1.9_major_rearrangements/KVMultiDet/particles/KVMassExcessTable.h:7:
/home/john/software/sources/kaliveda/1.9_major_rearrangements/KVMultiDet/particles/KVNuclDataTable.h:13:10: fatal error: 'KVString.h' file not found
#include "KVString.h"
         ^
Error in <TInterpreter::AutoParse>: Error parsing payload code for class KVParticle with content:


#ifndef G__VECTOR_HAS_CLASS_ITERATOR
  #define G__VECTOR_HAS_CLASS_ITERATOR 1
#endif
#ifndef WITH_OPENGL
  #define WITH_OPENGL 1
#endif

#define _BACKWARD_BACKWARD_WARNING_H
#include "particles/KVMassExcessTable.h"
#include "particles/KVElementDensityTable.h"
#include "particles/KVNucleus.h"
#include "particles/KVNuclData.h"
#include "particles/KVParticleCondition.h"
#include "particles/KVMassExcess.h"
#include "particles/KVNDTManager.h"
#include "particles/KVElementDensity.h"
#include "particles/KVNuclDataTable.h"
#include "particles/KVChargeRadius.h"
#include "particles/KVLifeTime.h"
#include "particles/KVLifeTimeTable.h"
#include "particles/KVAbundance.h"
#include "particles/KVAbundanceTable.h"
#include "particles/KVParticle.h"
#include "particles/KVChargeRadiusTable.h"
#include "particles/KVSimNucleus.h"

#undef  _BACKWARD_BACKWARD_WARNING_H


ROOT_prompt_2:1:11: error: variable has incomplete type 'KVNucleus'
KVNucleus n
          ^
input_line_49:7:153: note: forward declaration of 'KVNucleus'
  ...describing atomic nuclei)ATTRDUMP"))) __attribute__((annotate("$clingAutoload$particles/KVNucleus.h")))  KVNucleus;
                                                                                                              ^

The interpreter/system include path in this case is the same as before, with the addition of “-Iparticles”.
If I try to add the correct include path to both/either gSystem or gInterpreter, it does not improve/change anything:

root [0] gSystem->AddIncludePath("-I/home/john/.kvroot-1.9-rearranged_gcc-4.9.1_x86_64_root-6.02.02/include/")
root [1] gInterpreter->AddIncludePath("-I/home/john/.kvroot-1.9-rearranged_gcc-4.9.1_x86_64_root-6.02.02/include/")
root [2] KVNucleus n
In file included from input_line_60:16:
In file included from /home/john/software/sources/kaliveda/1.9_major_rearrangements/KVMultiDet/particles/KVMassExcessTable.h:7:
/home/john/software/sources/kaliveda/1.9_major_rearrangements/KVMultiDet/particles/KVNuclDataTable.h:13:10: fatal error: 'KVString.h' file not found
#include "KVString.h"
         ^
root.exe: /home/john/software/sources/root/root.git/interpreter/cling/lib/Interpreter/IncrementalParser.cpp:615: void cling::IncrementalParser::rollbackTransaction(cling::Transaction*): Assertion `T == getLastTransaction() && "We always must revert the last T"' failed.
ganp115:~% [exit from ROOT]

The “solution”, for the time being, is to add the run-time include path to the rootcling directive,
i.e.
rootcling -v -f KVMultiDetparticlesDict.cpp -rml libKVMultiDetparticles.so -rmf libKVMultiDetparticles.rootmap -c -p -Iparticles -Ibase -DWITH_OPENGL -I/home/john/software/sources/kaliveda/1.9_major_rearrangements -I/home/john/.kvroot-1.9-rearranged_gcc-4.9.1_x86_64_root-6.02.02/include particles/KVMassExcessTable.h particles/KVElementDensityTable.h particles/KVNucleus.h […] particles/KVMultiDetparticlesLinkDef.h

and in this case all is well:

ganp115:~% root -l -n
root [0] KVNucleus n(

KVNucleus KVNucleus()
KVNucleus KVNucleus(Int_t z, Double_t t, TVector3& p)
KVNucleus KVNucleus(Int_t z, Int_t a = 0, Double_t ekin = 0)
KVNucleus KVNucleus(Int_t z, Int_t a, TVector3 p)
KVNucleus KVNucleus(const Char_t*, Double_t EperA = 0)
KVNucleus KVNucleus(const KVNucleus&)
root [0] KVNucleus n(54)
Info in <KVBase::InitEnvironment>: Initialising KaliVeda environment...
Info in <KVBase::InitEnvironment>: Using KaliVeda version 1.9.2 built on 2014-12-01
Info in <KVBase::InitEnvironment>: (BZR branch : bzr+ssh://bazaar.launchpad.net/+branch/kaliveda/1.9/ revision#1073 (clean=0) date : 2014-11-18 13:38:44 +0100)
(KVNucleus &) @0x7f712bc7b018

As I said at the beginning (about 5000 lines ago…) this seems to me to be a dangerous kludge…

Cheers
John

Hello John,

I understand that from your long post that what you are missing is finding your headers at runtime (please correct me if I am wrong).
In order for ROOT to find your headers at runtime what you can do is to set up a ROOT_INCLUDE_PATH env variable, which is formatted as a LD_LIBRARY_PATH one: path1:path2:…:pathN.

Best,
Danilo

Hi Danilo
That works great!
Thanks a lot
Cheers
John