Private shared library do not load in ROOT v5.15.04

Hello,

This is certainly a known feature, but loading private shared library changed between 5.12 and 5.15 (didn’t try 5.14)

I’m compiling my shared library with a rootcint-gnerated dictionnary.
Then in 5.12 I could do :

root -l root [0] .L libs/libJetCore.so root [1]

With 5.15 I have :

root -l root [0] .L libs/libJetCore.so dlopen error: /home/delsart/stuff/new/./libs/libJetCore.so: undefined symbol: _ZN5TFileC1EPKcS1_S1_i Load Error: Failed to load Dynamic link library /home/delsart/stuff/new/./libs/libJetCore.so *** Interpreter error recovered *** root [1]

I now need to do gSystem->Load(“libTree.so”) before loading my lib.

Is there a way to compile my lib so that ROOT automatically loads what is need when I try to load it ?

Thanks for your help,

P.A.

Maybe help ROOT utility rlibmap ? (man rlibmap) [ul] rlibmap -f -r .rootmap -l pathToLib/libJetCore.so -d libTree -c pathToInclude/LinkDef.h[/ul] Now, you dont need .L libs/libJetCore.so, nor libTree.so root [0] jet = new JetCore() Jan

Hi,
with current CVS the recommended rootmap name for libName.so is libName.rootmap, i.e. rlibmap -f -o pathToLib/libJetCore.rootmap -l pathToLib/libJetCore.so -d libTree -c pathToInclude/LinkDef.hMakes it a bit more modular. If you have LD_LIBRARY_PATH set to include pathToLib root will be able to load libJetCore when you access the JetCore class.
Axel.

Hi rooters,
I have a similar problem: I have private shared library with many classes + dictionaries that I was used to load with

.L /directory/mylibrary.so
(if you need the compilation details just ask)

and now, with root 5.15, it doesn’t work anymore, since it complains for missing symbols (that are present in some of the ROOT libs).
How can I fix the problem? do you have a usage example for rlibmap?

Regards
Luigi

Hi,

you might need to load a ROOT lib before loading your lib. Alternatively, as you said, you can run rlibmap. See my example of how to call it in me previous posting. Don’t forget to set LD_LIBRARY_PATH so it also includes the directory that your library is in - otherwise ROOT cannot find the rootmap file.

Axel.

Hi Axel,
I have the following questions:

  1. should I manually guess which are the needed ROOT libraries (-d option of rlibmap)? by trial and error? :open_mouth:
  2. if I run:
    rlibmap -f -o mylib.rootmap -l mylib.so -d DUMMY -c mylibLinkDef.h
    it produces
    Library.mylib: mylib.so DUMMY
    so rlibmap does not check whether DUMMY is a real library or not. is it correct?
  3. what is the meaning of the " -f "option of rlibmap?

BTW, I don’t need the “automatic load” feature, but only a working
.L mylib.so :smiley:

Regards
Luigi

Hi Luigi,

You can check by looking at the output of

symbols=`nm -C mylib.so | grep -E ' U T[[:alnum:]_]+::' | sed 's,^.* U \([[:alnum:]_]\+\)::.*$,(\1),'| sort | uniq | tr '\n' '|'`; (for so in $ROOTSYS/lib/*.so; do nm -C -D --defined-only $so | grep -E 'T ('$symbols')::' > /dev/null && echo $so; done )| sort | uniq

[quote=“luigi”]2) if I run:
rlibmap -f -o mylib.rootmap -l mylib.so -d DUMMY -c mylibLinkDef.h
it produces
Library.mylib: mylib.so DUMMY
so rlibmap does not check whether DUMMY is a real library or not. is it correct?[/quote]
Yes, we trust you :slight_smile:

From $ROOTSYS/utils/src/rlibmap.cxx[quote]// This program generates a map between class name and shared library.
// Its output is in TEnv format.
// Usage: rlibmap [-f] [-o ] -l -d
// -c
// -f: output full library path name (not needed when ROOT library
// search path is used)
// -o: write output to specified file, otherwise to stdout
// -r: replace existing entries in the specified file
// -l: library containing the classes in the specified linkdef files
// -d: libraries on which the -l library depends
// -c: linkdef files containing the list of classes defined in the -l library[/quote]

[quote=“luigi”]BTW, I don’t need the “automatic load” feature, but only a working
.L mylib.so :D[/quote]
Either load the dependent libs before, or create a rootmap file.

Axel.

Dear Axel,
thank you for the reply and for the (black) magic 8)
Anyway I am still not able to load my library…

I have reduced the problem to the following minimal class that uses root:

// myclass.h
#include <TObject.h>
#include <TH1.h>


class myclass: public TObject{
 public:
  myclass(int a, int b);

  ClassDef(myclass,2);
};
// myclass.cxx
#include <myclass.h>

ClassImp(myclass);

myclass::myclass(int a, int b)
{
  printf("useless ctor %d %d\n",a,b);
  TH1F *h=new TH1F("h1","h1",100,a,b);
  h->Draw();
}
//myclassLinkDef.h
#ifdef __CINT__

#pragma link off all globals;
#pragma link off all classes;
#pragma link off all functions;

#pragma link C++ class myclass+;
#endif

that I compile (under Linux gcc version 4.1.2 Debian 4.1.1-21) with:

rm *Dict* *.o

$ROOTSYS/bin/rootcint myclassDict.cxx -c -p myclass.h myclassLinkDef.h

g++ -c -I. -I$ROOTSYS/include myclass.cxx -o myclass.o
g++ -c -I. -I$ROOTSYS/include myclassDict.cxx -o myclassDict.o

g++ -shared myclass.o myclassDict.o -o myclass.so

.L myclass.so works nicely in root 5.13.04, but I have problems in root 5.15:

root
.L myclass.so
dlopen error: ./myclass.so: undefined symbol: _ZN4TH1FC1EPKcS1_idd

your script says:

/usr/local/root_v5.15/lib/libCore.so
/usr/local/root_v5.15/lib/libHist.so

so I type:

root
.L /usr/local/root_v5.15/lib/libCore.so
.L /usr/local/root_v5.15/lib/libHist.so
dlopen error: /usr/local/root_v5.15/lib/libHist.so: undefined symbol: _ZN8TVectorTIdE4DrawEPKc

if I use a myclass.rootmap like

Library.myclass:                            myclass.so libCore
Library.myclass:                            myclass.so libHist

it says:

.L myclass.so
Note: File "/usr/local/root_v5.15/lib/libCore.so" already loaded
Note: File "/usr/local/root_v5.15/lib/libCore.so" already loaded
Note: File "/usr/local/root_v5.15/lib/libCore.so" already loaded
Error in <TCint::AutoLoad>: failure loading library myclass.so for class myclass
dlopen error: /home/bardelli/rootfiles/classi515/./myclass.so: undefined symbol: _ZN4TH1FC1EPKcS1_idd
Load Error: Failed to load Dynamic link library /home/bardelli/rootfiles/classi515/./myclass.so
Error in <TCint::AutoLoad>: failure loading library myclass.so for class myclass

and an infinite loop starts…

Any help is appreciated (and sorry for the giant post :unamused: )
Luigi

Hi,

Keep only the line:Library.myclass: myclass.so libHist
Cheers,
Philippe.

Dear Philippe,
that does not seem to work…:

root [0] .L myclass.so  
Note: File "/usr/local/root_v5.15/lib/libHist.so" already loaded
Note: File "/usr/local/root_v5.15/lib/libHist.so" already loaded
Note: File "/usr/local/root_v5.15/lib/libHist.so" already loaded
Note: File "/usr/local/root_v5.15/lib/libHist.so" already loaded
....

infinite loop again… :frowning:

Luigi

What aboutLibrary.myclass: myclass.so libHist.so?
Philippe

Hi Philippe,
here are the results:

root
 .L myclass.so
Error: cannot open file "/home/bardelli/rootfiles/classi515/./myclass.so"  myclass.so:1:
Error in <TCint::AutoLoad>: failure loading library myclass.so for class myclass
Error in <TCint::AutoLoad>: failure loading library myclass.so for class myclass
Error in <TCint::AutoLoad>: failure loading library myclass.so for class myclass

and, again, infinite loop…

BTW, are you able to reproduce my problems?
Regards
Luigi

Hi,

Yes I can reproduce your problem. The ‘issue’ comes from the fact that you library and class have the same name. As a work around you should name your library libclass.so.

Cheers,
Philippe

Dear all,
now it works… I summarize here my findings, just in case someone is interested:

ROOT pre 5.15
if you have some classes Class1 Class2 etc in a file mylib.so (compiled as in my previous post) you have to type:

.L mylib.so

and you are done.

ROOT 5.15
after compilation you have to do:

  1. build a mylib.rootmap file. In order to figure out the needed libraries I use the following script (that uses Axel’s black magic):
#!/bin/bash

CLASS=$1
USERLIB=$2


#from Axel: http://root.cern.ch/phpBB2/viewtopic.php?t=4778
SYMBOLS=$(symbols=`nm -C $USERLIB.so | grep -E ' U T[[:alnum:]_]+::' | sed 's,^.* U \([[:alnum:]_]\+\)::.*$,(\1),'| sort | uniq | tr '\n' '|'`; (for so in $ROOTSYS/lib/*.so; do nm -C -D --defined-only $so | grep -E 'T ('$symbols')::' > /dev/null && echo $so; done )| sort | uniq )

#remove $ROOTSYS
SSYMBOLS=$(echo $SYMBOLS | sed s="$ROOTSYS/lib/"==g)

#now output rootmap
echo -n "Library.$CLASS:       $USERLIB.so "
for ROOTLIB in $SSYMBOLS ; do
    echo -n "$ROOTLIB "
done
echo ""

with a command like

./do_map Class1 mylib >   mylib.rootmap
./do_map Class2 mylib >> mylib.rootmap
....

it produces a file mylib.rootmap like

Library.Class1:       mylib.so libCore.so libGpad.so libGraf.so libGui.so libHist.so libMatrix.so libPhysics.so libRIO.so libTree.so 
Library.Class2:       mylib.so libCore.so libGpad.so libGraf.so libGui.so libHist.so libMatrix.so libPhysics.so libRIO.so libTree.so 
  1. add the directory where your library resides to the LD_LIBRARY_PATH environment variable

  2. if now you type

root
c1=new Class1()

it works :smiley:

  1. if instead you write (like for root <5.15)
root
.L /home/users/....../mylib.so

it complains for missing symbols… ok, I will use method 3) for root >=5.15

I don’t know if this is the smartest way to have the job done (probably not) but at least it works in an automatic way with my “real-life” library (about 30 classes that use many features of ROOT).

Thank you for the help!!
Luigi

Hi,

Please note that the original limitation:[quote]The ‘issue’ comes from the fact that you library and class have the same name. As a work around you should name your library libclass.so.[/quote]is now lifted/removed in the CVS repository.

Cheers,
Philippe

Dear ROOT devs,

Could you please verify me if this issue still exist in the ROOT v.5.21.xx as well?

I am experiancing the same problem as mentioned by the previous uses.

Thanks,
Jaliya

Hi,

Humm suprising, Can you provide a complete running example showing the problem in ROOT 5.21?

Thanks,
Philippe

Hi Philippe,

I tried to use the attached shared library using ROOT v 5.21.02 and I got the following error. It was working fine with ROOT v 5.12.00e that I have earlier.
(Compilation works fine in ROOT v.5.21.02)

root -l
root [0] .L libnbROOT.so 
dlopen error: /home/jaliya/projects/cppworkspace/rootnb/samples/./libnbROOT.so: undefined symbol: _ZTI9TPaveText
Load Error: Failed to load Dynamic link library /home/jaliya/projects/cppworkspace/rootnb/samples/./libnbROOT.so
*** Interpreter error recovered ***

Thanks,
Jaliya
rootnb.tar (1.4 MB)

Hi,

This is due to the finer grainer library layout in ROOT 5.21. You now must either explicit load libGPad (on which you library depends) or write a rootmap file for your library:# File libnbROOT.rootmap Library.MyClassName: libnbROOT.so libGpad.so

Cheers,
Philippe.

Hi Philippe,

Yes, that was the problem. Now it works when I load the libGpad.so first.
Thank you very much!

Jaliya