Cannot generate rootmap for functions

Hi!

I’m struggling to understand how to generate rootmaps for functions. Here a short example: I have my test.h

int testFunction(int g) {
  return g+1;
}
namespace testNamespace {
class testClass {
public:
  int a;
  int b;
};
}

and my LinkDef.h:

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


#pragma link C++ namespace testNamespace;
#pragma link C++ function testFunction;
#pragma link C++ class testNamespace::testClass;

#endif

running

rootcling libtest.so test.h LinkDef.h  -rmf test.rootmap

(v6.24.00) results in the following test.rootmap:

 { decls }
namespace testNamespace {  }

[  ]
# List of selected classes
class testNamespace::testClass
header test.h
# List of selected namespaces
namespace testNamespace

No trace of testFunction, and it is available on the interpreter only after explicitly loading libtest.so, also after trying different signatures like #pragma link C++ function testFunction(int);

What am I doing wrong?

What’s adding to my confusion is that none of the rootmaps of the root libraries themselves contain any functions (at least in my installation), even though they are there in the LinkDefs (https://github.com/root-project/root/blob/master/math/mathcore/inc/LinkDef_Func.h) – things like ROOT::Math::erf are still available in the interpreter, but I’d be curious to know how that works.

Reproducer for those who prefer CMake: https://github.com/vvolkl/rootmap_functions

Ultimately I’d like to be able to use defined_in without explicitly stating all methods in the header in LinkDef.h, but I’m already happy if the explicit way works.
Thanks for looking into this.
Valentin

We don’t generate anything for function anymore - ignoring the corresponding LinkDef entries gives us backward compatibility with CINT.

What do you need these entries for? If it’s auto-loading: you have two options.

  1. use C++ modules: they will inject the function when needed
  2. move the functions into a namespace, and declare the namespace (as a class) in the Linkdef.

Would any of that work?

Thanks a lot for these explanations – it is indeed auto-loading I need it for.

1.) Even though it would be interesting to try out, we still use compilers without modules support.

2.) What do you mean by “declare the namespace (as a class)”? #pragma link class testNamespace;? This does not work for me.

However, it seems like autoloading any class in the shared library also loads the functions, even if they are not in the same namespace:

~/r/rootmap_functions/build (master *)$ root
root [0] testFunction(1)
input_line_9:2:3: error: use of undeclared identifier 'testFunction'
 (testFunction(1))
  ^
Error in <HandleInterpreterException>: Error evaluating expression (testFunction(1)).
Execution of your code was aborted.
root [1] .q
~/r/rootmap_functions/build (master *)$ root
root [0] testNamespace::testClass()
(testNamespace::testClass) @0x21bbe90
root [1] testFunction(1)
(int) 2
root [2] 


It’s a bit surprising, but that works for my usecase!

Good! Regarding option 1: you don’t need to build with modules, you can - as a first step - enable modules for ROOT’s dictionaries, even without compiler support. Let me know if that sounds interesting!

And

How does it not work? With namesp::func() you should be able to pragma declare namesp and then any call to namesp::func() should automatically load the corresponding library.

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