Problem migrating to rootcling from rootcint

Hi ROOT team,

I’m currently trying to port my code over to support ROOT6. I’m currently using boost build to build all my reusable libraries; however, I ran into an issue with generating the dictionaries for ROOT. In order to facilitate a discussion, I’ve created a simple use case that illustrates the issue I’m having.

Consider the following code:

hello.h:

namespace rwk { void hello(); }

hello.cpp

#include <iostream>

namespace rwk
{
    void hello()
    {
        std::cout << "hello 1" << std::endl;
        return;
    }
}

And the associated linkdef.h:

[code]#ifdef CINT

#pragma link off all globals;
#pragma link off all classes;
#pragma link off all functions;
#pragma link C++ nestedclasses;

#pragma link C++ namespace rwk;
#pragma link C++ function rwk::hello;

#endif[/code]

When I compiled this using ROOT 5.34.00.patches with the following commands, it worked as expected:

[rwk7t@tensor-3 5.34]$  ./build.sh 
rootcint -v3 -f hello_dict.cpp -c -p -I. hello.h linkdef.h
clang++ -c -o hello.o -m64 -std=c++11 -stdlib=libc++ -pipe -W -Woverloaded-virtual -fsigned-char -fno-common -pthread -I. hello.cpp
clang++ -c -o hello_dict.o -m64 -std=c++11 -stdlib=libc++ -pipe -W -Woverloaded-virtual -fsigned-char -fno-common -pthread -pthread -stdlib=libc++ -m64 -I/usr/local/root/5.34.00.patches/include -I. hello_dict.cpp
clang++ -dynamiclib -single_module -Wl,-dead_strip_dylibs -O2 -DNDEBUG -m64 -mmacosx-version-min=10.9 -stdlib=libc+ -o libhello.so -L/usr/local/root/5.34.00.patches/lib -lCore -lCint -lRIO -lNet -lHist -lGraf -lGraf3d -lGpad -lTree -lRint -lPostscript -lMatrix -lPhysics -lMathCore -lThread -lpthread -Wl,-rpath,/usr/local/root/5.34.00.patches/lib -stdlib=libc++ -lm -ldl hello.o hello_dict.o
[rwk7t@tensor-3 5.34]$  root
root [0] gROOT->GetVersion()
(const char* 0x107d9acb1)"5.34/33"
root [1] .L libhello.so 
root [2] rwk::hello()
hello 1

Now, I’m attempting to do the equivalent in root 6.04.00.patches. The changes occur in the linkdef.h (replace CINT with ROOTCLING):

#ifdef __ROOTCLING__

#pragma link off all globals;
#pragma link off all classes;
#pragma link off all functions;
#pragma link C++ nestedclasses;

#pragma link C++ namespace rwk;
#pragma link C++ function rwk::hello;

#endif

And now, I build as before using rootcling; however, It seems that the dictionaries were not understood by the interpreter.

[rwk7t@tensor-3 6.04]$  ./build.sh 
rootcling -v3 -f hello_dict.cpp -c -p -I. hello.h linkdef.h
clang++ -c -o hello.o -m64 -std=c++11 -stdlib=libc++ -pipe -W -Woverloaded-virtual -fsigned-char -fno-common -pthread -I. hello.cpp
clang++ -c -o hello_dict.o -m64 -std=c++11 -stdlib=libc++ -pipe -W -Woverloaded-virtual -fsigned-char -fno-common -pthread -pthread -stdlib=libc++ -std=c++11 -m64 -I/usr/local/root/6.04.00.patches/include -I. hello_dict.cpp
clang++ -dynamiclib -single_module -Wl,-dead_strip_dylibs -O2 -DNDEBUG -m64 -mmacosx-version-min=10.9 -stdlib=libc+ -o libhello.so -L/usr/local/root/6.04.00.patches/lib -lCore -lRIO -lNet -lHist -lGraf -lGraf3d -lGpad -lTree -lRint -lPostscript -lMatrix -lPhysics -lMathCore -lThread -lpthread -Wl,-rpath,/usr/local/root/6.04.00.patches/lib -stdlib=libc++ -lm -ldl hello.o hello_dict.o
[rwk7t@tensor-3 6.04]$  root
root [0] gROOT->GetVersion()
(const char *) "6.04/01"
root [1] .L libhello.so 
root [2] rwk::hello()
ROOT_prompt_2:1:1: error: 'rwk' is not a class, namespace, or enumeration
rwk::hello()
^
ROOT_prompt_2:1:1: note: 'rwk' declared here

I’ve looked through the docs and forums and I haven’t found a solution. I’ve attached this test code. Can someone pinpoint where I’m going wrong?

Thanks,
Ryan
rootcling_test.tgz (27.5 KB)

Hi Ryan,

currently the functions cannot be treated as you do in your example: the situation dramatically improved when pcms are supported.
An easy way out for the moment is to include the hello.h header.

Cheers,
Danilo

Include hello.h where?

I included it in the hello.cpp:

#include <iostream>
#include "hello.h"

namespace rwk
{
    void hello()
    {
        std::cout << "hello 1" << std::endl;
        return;
    }
}

No change in behavior:

[rwk7t@tensor-3 6.04]$  ./build.sh 
rootcling -v3 -f hello_dict.cpp -c -p -I. hello.h linkdef.h
clang++ -c -o hello.o -m64 -std=c++11 -stdlib=libc++ -pipe -W -Woverloaded-virtual -fsigned-char -fno-common -pthread -I. hello.cpp
clang++ -c -o hello_dict.o -m64 -std=c++11 -stdlib=libc++ -pipe -W -Woverloaded-virtual -fsigned-char -fno-common -pthread -pthread -stdlib=libc++ -std=c++11 -m64 -I/usr/local/root/6.04.00.patches/include -I. hello_dict.cpp
clang++ -dynamiclib -single_module -Wl,-dead_strip_dylibs -O2 -DNDEBUG -m64 -mmacosx-version-min=10.9 -stdlib=libc+ -o libhello.so -L/usr/local/root/6.04.00.patches/lib -lCore -lRIO -lNet -lHist -lGraf -lGraf3d -lGpad -lTree -lRint -lPostscript -lMatrix -lPhysics -lMathCore -lThread -lpthread -Wl,-rpath,/usr/local/root/6.04.00.patches/lib -stdlib=libc++ -lm -ldl hello.o hello_dict.o
[rwk7t@tensor-3 6.04]$  root
root [0] .L libhello.so 
root [1] rwk::hello()
ROOT_prompt_1:1:1: error: 'rwk' is not a class, namespace, or enumeration
rwk::hello()
^
ROOT_prompt_1:1:1: note: 'rwk' declared here

Hi Ryan,

apologies: at the interpreter prompt.

Cheers,
Danilo

Hi Danilo,

I’m not following – can you be more specific?

I tried this:

root [2] .include hello.h
root [3] .L libhello.so 
root [4] rwk::hello()
ROOT_prompt_5:1:1: error: 'rwk' is not a class, namespace, or enumeration
rwk::hello()
^
ROOT_prompt_5:1:1: note: 'rwk' declared here

-Ryan

Hi,

#include "hello.h"
.L libhello.so
rwk::hello()

Cheers,
Danilo

yep – that was it!

[rwk7t@tensor-3 6.04]$  root
root [0] #include "hello.h"
root [1] .L libhello.so 
root [2] rwk::hello()
hello 1

Is this a “feature” of ROOT6 or something that will eventually resemble the ROOT5 behavior? It would be inconvenient to have to always add a user defined lib in two steps.

Hi Ryan,

for simple functions (non templated, only PODs as arguments) the feature could well appear already in 6.06.

Cheers,
Danilo