Loading a library from a script

Hi,

Continuing along the lines of extending ROOT functionality with external libraries I have run into another issue that I am hoping someone here can help resolve. If I make a library containing a class foo and write a script bar1.C that calls the the class:

void bar1() {
   foo f;
}

I can call this from root with no issues as follows:

[0] .L libFoo.dylib
[1] .x bar1.C

If I then try to have the script bar2.C do the library loading using gSystem::Load as follows:

void bar2() {'
   gSystem->Load("libFoo.dylib");
   foo f;
}

I get the following error message:

bar2.C:3:4: error: unknown type name 'foo'

I can resolve this by adding the appropriate include to bar3.C

#include "foo.h"
void bar2() {'
   gSystem->Load("libFoo.dylib");
   foo f;
}

but now receive the following error message:

IncrementalExecutor::executeFunction: symbol '_ZN11fooC1Ev' unresolved while linking [cling interface function]!
You are probably missing the definition of foo::foo()
Maybe you need to load the corresponding shared library?

Any ideas? What is the ‘proper’ way to load an external library for use like this?

1 Like

Hi,

As the first step of interpreting, cling “compiles” that script before running it. For that it cannot resolve the foo constructor. I.e. things are out of sequence. Simply use

R__ADD_LIBRARY_PATH($FOODIR) // if needed
R__LOAD_LIBRARY(libFoo.dylib)

right after the #include and it should work.

Cheers, Axel.

2 Likes

Hi,

the interpreter of ROOT6 is based on a real compiler and, as such, it looks for all symbols before running the code. So it is somehow “too late” to load the library at runtime since the symbols inside it are needed at compile time.
Now, there are several ways out. The first one, which is the one I recommend, is to use rootmpafiles. These allow ROOT to autoload the libraries needed for running the code and to parse the necessary headers. Creating a rootmapfile is very easy: just use the -rmf switch or --rootmap in rootcling or genreflex respectively.
In case libFoo is a library you did not build and you want to use it interactively I think the best option is to

  1. Include the header (as you correctly did)
  2. Use the R__LOAD_LIBRARY(libFoo.dylib) macro: this will trigger the loading of the library at parsing time, therefore in time for letting cling finding the symbols necessary for the compilation

In ROOT5 your code was working since the interpreter, CINT, was interpreting the code line by line.

Cheers

2 Likes

Hi,

did not see the post which appeared while I was writing :slight_smile: @Axel is of course right. This is what I describe in my points 1) and 2).

Cheers,
D

This worked nicely. The only downside was that the entire absolute path needed to be added. Does ROOT following environment variable for where to find headers and libraries? Something similar to gcc’s INCLUDE_PATH, CPLUS_INCLUDE_PATH and LIBRARY_PATH?

I am generating the rootmap files as I am using the cmake macro ROOT_GENERATE_LIBRARY (which I have an issue with, but will not discuss here). I’m not sure how to use these files, it seems they need to be placed somewhere in particular? Remember I am trying to develop this for others to use so the idea is that a cmake file would properly place all the files in the correct places and the user would have to do very little to get it working.

Thanks for the responses so far, they are helpful.

Also, what do I need to do so that I can recall the same macro multiple times? Currently it crashes with warning of ‘unknown types’ when calling it more than once:

[0] .x macro.C
Success!
[1] .x macro.C
... error: unknown type name 'foo' ...

EDIT: I tried wrapping the library loading in a header guard, but that didn’t resolve the issue.

Hi,

They need to be in the LD_LIBRARY_PATH. Usually the best place is right next to the libraries as we do in ROOT or as the LHC experiments do.

Cheers,
D

Hi,

this looks like a different question related to unloading: do you mind opening another thread about it ?

Cheers,
D

This won’t work as many of the users are on Mac OS X 10.12 and have System Integrity Protection enabled (ROOT Dynamic Library Path - #5 by ksmith)

I’d be happy to.

I opened a thread at Unloading? a library or loading a library again?

Hi,

it is enough to let the rootmaps sit in the same directory of the libraries. The SIP is a detail.

Cheers,
D

thanks for starting another thread!

Use or not to use rootmap files ?

Thanks,
Jan

My problem here is that I am using CMake and ROOT_GENERATE_DICTIONARY. This macro builds a rootmapfile, but it doesn’t work correctly.

First, it needs to be manually installed, more of an annoyance than anything else:

#Install the ROOT 6 PCM and rootmap files.
if (${ROOT_VERSION} VERSION_GREATER "6.0")                                                             
   install(                                                                                            
      FILES
         ${CMAKE_CURRENT_BINARY_DIR}/libFooDict_rdict.pcm                                      
         ${CMAKE_CURRENT_BINARY_DIR}/libFooDict.rootmap                                        
      DESTINATION lib/)
endif (${ROOT_VERSION} VERSION_GREATER "6.0")

Secondly the rootmap file is incorrectly named for the library libFooDict.rootmap and top of the rootmap file reads:

[ libFooDict.so ]

This is incorrect as I am on a Mac and the extension should by .dylib and in addition it should not have the Dict. At some point I will make a small example and open a new thread with issues related to ROOT_GENERATE_DICTIONARY (I have a couple additional issues as well).

Hi Jan,

both Philippe and I are right. If you are running a macro, you will need to load the libraries so better to rely on autoloading and therefore rootmaps. If you build executables or shared objects, better to directly link.

Cheers,
D

1 Like

Hi Jan,

Plus, the first library should be loaded with the help of a rootmap file, all dependent libraries should be loaded by the dynamic linker because they were explicitly linked against the first library.

Cheers, Axel

1 Like

Hi @ksmith,

Yes please open a new thread or even a bug report on the issues with the CMake macro.

Note that MacOS uses .so as shared library extension since 10.7 or 10.6 if I remember correctly. No need to keep .dylib on your side.

But of course the rootmap file should still respect parameters like the library name, if specified.

Cheers, Axel

I’ve started to open new thread about CMake issues. I’ll update this post with links to those threads as they are created:

1 Like

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