Problems adding a custom class using rootcling

Hello,

I want to add a custom class to ROOT, and I’m using the following tutorial by @eguiraud . I am using the rootcling way.

My problem is that, once I have used rootcling to make the dictionaries, I want to compile it with g++ using g++ -o TFeynman_readwrite TFeynman_readwrite.cpp $(root-config --libs --cflags) TFeynman.cxx TFeynman_dict.cpp . When I do this I get the following error:

/usr/bin/ld: /home/advait/rootbuild/lib/libGpad.so: undefined reference to symbol '_ZN6TLatexC1EddPKc'
/usr/bin/ld: /home/advait/rootbuild/lib/libGraf.so: error adding symbols: DSO missing from command line
collect2: error: ld returned 1 exit status

After doing some digging online, apparently I have to add -lpthread to the command line. Is this correct? And if yes, how do I do this? Here are my files:

UPDATE: When I use the cmake method I get this error:

/usr/bin/ld: CMakeFiles/TFeynman.dir/TFeynman.cxx.o: in function `__static_initialization_and_destruction_0(int, int)':
TFeynman.cxx:(.text+0x1958): undefined reference to `ROOT::GenerateInitInstance(TFeynmanEntry const*)'
/usr/bin/ld: TFeynman.cxx:(.text+0x197c): undefined reference to `ROOT::GenerateInitInstance(TFeynman const*)'
/usr/bin/ld: CMakeFiles/TFeynman.dir/TFeynman.cxx.o: in function `TFeynman::IsA() const':
TFeynman.cxx:(.text._ZNK8TFeynman3IsAEv[_ZNK8TFeynman3IsAEv]+0x11): undefined reference to `TFeynman::Class()'
/usr/bin/ld: CMakeFiles/TFeynman.dir/TFeynman.cxx.o: in function `TFeynman::ShowMembers(TMemberInspector&) const':
TFeynman.cxx:(.text._ZNK8TFeynman11ShowMembersER16TMemberInspector[_ZNK8TFeynman11ShowMembersER16TMemberInspector]+0x15): undefined reference to `TFeynman::Class()'
/usr/bin/ld: CMakeFiles/TFeynman.dir/TFeynman.cxx.o:(.data.rel.ro._ZTV8TFeynman[_ZTV8TFeynman]+0x90): undefined reference to `TFeynman::Streamer(TBuffer&)'
/usr/bin/ld: CMakeFiles/TFeynman.dir/TFeynman.cxx.o:(.data.rel.ro._ZTV8TFeynman[_ZTV8TFeynman]+0x288): undefined reference to `non-virtual thunk to TFeynman::Streamer(TBuffer&)'
collect2: error: ld returned 1 exit status
make[2]: *** [CMakeFiles/TFeynman.dir/build.make:110: TFeynman] Error 1
make[1]: *** [CMakeFiles/Makefile2:104: CMakeFiles/TFeynman.dir/all] Error 2

I have no clue what it means :sweat_smile:

Hi @AdvaitDhingra,

You are missing a -lGraf on the compiler command line, i.e. that shared object provides the TLatex::TLatex() constructor. It seems that it is not included by default in the list provided by root-config --libs; adding that option manually should fix your issue.

Cheers,
J.

1 Like

Ah okay, thanks. I’ll try it and let you know.

Actually root-config --libs should contain -lGraf, it might be an ordering problem.

E.g. you might need

g++ -o TFeynman_readwrite TFeynman_readwrite.cpp TFeynman.cxx TFeynman_dict.cpp $(root-config --libs --cflags) 

instead of

g++ -o TFeynman_readwrite TFeynman_readwrite.cpp $(root-config --libs --cflags) TFeynman.cxx TFeynman_dict.cpp

For the cmake version: does the example in the GitHub - eguiraud/root_dictionaries_tutorial: A tutorial on creating ROOT dictionaries to perform I/O of custom C++ classes repository work for you? If not, there might be something broken in your environment. If yes, you could investigate what you changed exactly from the original example that broke it.

Cheers,
Enrico

I tried this and I get another error:

/usr/bin/ld: /tmp/ccm9ljFH.o: in function `__static_initialization_and_destruction_0(int, int)':                        TFeynman.cxx:(.text+0x1958): undefined reference to `ROOT::GenerateInitInstance(TFeynmanEntry const*)'                  collect2: error: ld returned 1 exit status  

Try:

`root-config --cxx --cflags` -o TFeynman_readwrite TFeynman_readwrite.cpp TFeynman.cxx TFeynman_dict.cpp `root-config --libs`

This error means that the source file or library that defines ROOT::GenerateInitInstance(TFeynmanEntry const*) needs to be present in your compilation command and it needs to come after TFeynman.cxx, which needs that symbol.

I guess ROOT::GenerateInitInstance(TFeynmanEntry const*) should be defined in TFeynman_dict.cpp, is it there?

Yeah, it’s there. Here it is:

TGenericClassInfo *GenerateInitInstance(const ::TFeynman*){                                                                                                                          
    return GenerateInitInstanceLocal((::TFeynman*)nullptr);
}  
Unknown argument "--cflagsroot-config"! 
Usage: root-config [--prefix[=DIR]] [--exec-prefix[=DIR]] [--version] [--cflags] [--auxcflags] [--ldflags] [--new] [--nonew] [--libs] [--glibs] [--evelibs] [--bindir] [--libdir] [--incdir] [--etcdir] [--tutdir] [--srcdir] [--noauxcflags] [--noauxlibs] [--noldflags] [--has-<feature>] [--arch] [--platform] [--config] [--features] [--ncpu] [--git-revision] [--python-version] [--python2-version] [--python3-version] [--cc] [--cxx] [--f77] [--ld ] [--help]  

Copy and paste the line that I gave you as is without any modifications (and execute it in a bash shell).

I did, and I get the output above. I just accidentally deleted some of your solution when I was quoting it.

That is NOT the full line.

Is this not what you proposed above?
root-config --cxx --cflags` -o TFeynman_readwrite TFeynman_readwrite.cpp TFeynman.cxx TFeynman_dict.cpp `root-config --libs

That’s not the symbol that’s missing, the linker complains about GenerateInitInstance(TFeynmanEntry const*), not GenerateInitInstance(const TFeynman*).

Is TFeynmanEntry also in your LinkDef? If not maybe try adding it?

1 Like

As @eguiraud says, it is clear now that it is not a missing library but a missing entry in the dictionary.

1 Like

That worked! Thank you very much @eguiraud and @Wile_E_Coyote .

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