Cmake project building .so library used in ROOT macro

Hi Rooters,

I am pretty new with cmake so apologies if this is a naive question. I could not find a thread answering this one.

I would like to build with cmake a dynamic library containing a custom classes derived from TSelector and then load this library in a ROOT macro and run the TSelector.

Here is the structure of my project:


run

build

source  --> CMakeLists.txt
             --> submit_ttDM_DESY_plotter.cxx
            --> ttDM_DESY_plotter_0L
                            --> CMakeLists.txt
                            --> include
                                          --> ttDM_DESY_plotter_0L.h
                                          --> ttDM_DESY_plotter_0L_SR.h
                            -->src
                                         -->LinkDef.h
                                         -->ttDM_DESY_plotter_0L_SR.cxx

ttDM_DESY_plotter_0L_SR is a TSelector inheriting from ttDM_DESY_plotter_0L, which as been generated using TTree::MakeSelector to a generic “ttDM_DESY_plotter_0L” tree, the idea being that “*_SR” trees will get some extra variables.

The CMakeLists.txt in “source” dir is fairly simple:

cmake_minimum_required(VERSION 3.0 FATAL_ERROR)
project(ttDM_DESY_plotter)

add_subdirectory(ttDM_DESY_plotter_0L)

The one in ttDM_DESY_plotter_0L is inspired from https://root.cern.ch/how/integrate-root-my-project-cmake

# CMakeLists.txt for ttDM_DESY_plotter_0L package. It creates a library with dictionary and a main program
cmake_minimum_required(VERSION 3.0 FATAL_ERROR)
project(ttDM_DESY_plotter_0L)

# You need to tell CMake where to find the ROOT installation. This can be done in a number of ways:
#   - ROOT built with classic configure/make use the provided $ROOTSYS/etc/cmake/FindROOT.cmake
#   - ROOT built with CMake. Add in CMAKE_PREFIX_PATH the installation prefix for ROOT
list(APPEND CMAKE_PREFIX_PATH $ENV{ROOTSYS})

#---Locate the ROOT package and defines a number of variables (e.g. ROOT_INCLUDE_DIRS)
find_package(ROOT REQUIRED COMPONENTS RIO Net)

#---Define useful ROOT functions and macros (e.g. ROOT_GENERATE_DICTIONARY)
include(${ROOT_USE_FILE})

include_directories(${CMAKE_CURRENT_SOURCE_DIR})
ROOT_GENERATE_DICTIONARY(G__ttDM_DESY_plotter_0L include/*.h LINKDEF src/LinkDef.h)

#---Create a shared library with geneated dictionary
add_library(ttDM_DESY_plotter_0L SHARED src/ttDM_DESY_plotter_0L_SR.cxx G__ttDM_DESY_plotter_0L.cxx)
target_link_libraries(ttDM_DESY_plotter_0L ${ROOT_LIBRARIES})

the project compiles fine:


cd ../build
cmake ../source
make

I then do;

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:${PWD}/ttDM_DESY_plotter_0L
export ROOT_INCLUDE_PATH=$ROOT_INCLUDE_PATH:${PWD}/../source/ttDM_DESY_plotter_0L

In order to get the dynamic library and the header included in my environement and I run the macro:

cd …/run
root -l -b -q submit_ttDM_DESY_plotter.cxx

Unfortunately it fails loading the library:

cling::DynamicLibraryManager::loadLibrary(): /afs/desy.de/user/s/saimpert/atlas/ttbarDM/ttDM_DESY_plotter/build/ttDM_DESY_plotter_0L/libttDM_DESY_plotter_0L.so: undefined symbol: _ZN20ttDM_DESY_plotter_0L6NotifyEv

I use: R__LOAD_LIBRARY(libttDM_DESY_plotter_0L) to load the library.

Any idea what could be going wrong? Let me know if you need more information … sorry if this is a stupid bug from my side.

Thanks a lot for the help
M.S.

Could you attach the contents of submit_ttDM_DESY_plotter.cxx?

Dear vvassilev,

thanks a lot for your your quick answer. The entire project is available here:

https://cernbox.cern.ch/index.php/s/Lnxm38Ma4fYbtTR

I suspect something is wrong in my mother/daughter class implementation.

This morning I set the mother class functions implemented only in the daughter class “pure virtual” and create a separate cxx file for the mother class including Notify and Init function.

I know have as error message when running the macro:

Processing ../source/submit_ttDM_DESY_plotter.cxx...
cling::DynamicLibraryManager::loadLibrary(): /afs/desy.de/user/s/saimpert/atlas/ttbarDM/ttDM_DESY_plotter/build/ttDM_DESY_plotter_0L/libttDM_DESY_plotter_0L.so: undefined symbol: _ZN4ROOT8Internal20TTreeReaderValueBase11CreateProxyEv
HELLO WORLD

my macro is very simple:

// C++ includes
#include <string>
#include <iostream>

// ttDM_DESY_plotter includes (headers)
//#include <include/ttDM_DESY_plotter_0L.h>

// ttDM_DESY_plotter includes (lib)
R__LOAD_LIBRARY(libttDM_DESY_plotter_0L)

void submit_ttDM_DESY_plotter(const std::string& Nlepton="0L", const std::string& regionName="SR", bool isMC=true)
{
  std::cout << "HELLO WORLD" << std::endl;
  //TSelector *sl = TSelector::GetSelector( "ttDM_DESY_plotter_0L_SR" );
}

Thanks a lot for your help
Cheers
Matthias

Actually I think I found the problem. It seems that:

${ROOT_LIBRARIES}

does not include TreePlayer.

Is this possible?

replacing:

target_link_libraries(ttDM_DESY_plotter_0L ${ROOT_LIBRARIES})

by

target_link_libraries(ttDM_DESY_plotter_0L ${ROOT_LIBRARIES} TreePlayer)

seems to have solved the issue. I will try to confirm this asap.

Cheers
Matthias

It is possible. ROOT is not bug free :wink:

What is your ROOT version? Could you check if that’s still the case if you use the ROOT master.

I am using root 6.10.04-x86_64-slc6-gcc62-opt with cmake 3.8.1

Unfortunately it is not easy for me to switch to the master, I am not the admin of the machine I am using.

I also found a couple of more modifications to make to the generated code in order to make the TSelector work with a TChain containing several files.

Cheers
Matthias

You are right, ROOT did not use to include TreePlayer in the default libraries. ROOT 6.12 and above do include it, however.

1 Like

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