12/11/2014

How to CMake MyProject together with ROOT GUI

I have MyProject composed of source files

myProject/c++/src/myMain.cpp
myProject/c++/include/myMain.h
myProject/c++/include/myMainLinkDef.h

to run on ROOT GUI. In myMain.cpp, a class MyMainGUI is called in a loop of  TApplication. In myMain.h,  this class is declared with the first line

    RQ_OBJECT("myMainGui").

myMainLinkDef.h includes pragma comment lines which look like

#pragma link C++ class MyMainGUI;
#pragma link C++ class mylib::MyFunction;

where mylib::MyFunction is a class used in ROOT GUI and given in

/somewhere/myLibrary/myLib.h
/somewhere/myLibrary/libmyLib.a

Problem: Compose a cmake package to build MyProject in an arbitrary directory myWKDIR.

I describe a solution in the following.

1. Prepare myProject/c++/CMakeLists.txt (presupposition: ROOT version 5.34):
==========================================================
cmake_minimum_required(VERSION 2.8)

set(CMAKE_VERBOSE_MAKEFILE 1)
#is convenient for debugging the make process.

project(MyProject)

set(CMAKE_CXX_COMPILER g++)
# since I used g++ to compile libmyLib.a

set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/..)
#since I'm going to build MyProject in myWKDIR/build/
#so that ${PROJECT_BINARY_DIR}/.. means myWKDIR.

#Prepare for the ROOT GUI
#-------------------------------------
#imitating geant4/examples/analysis/AnaEx02
#/////////////////////////////////////////////////////////////////////
find_package(ROOT REQUIRED)
find_program(ROOT_CINT_EXECUTABLE rootcint PATHS ${ROOT_DIR}/bin NO_DEFAULT_PATH})

#External Libraries to be linked
#---------------------------------------
set(myLibrary_DIR /somewhere/myLibrary)
add_library(MyLib STATIC IMPORTED)
set_property(TARGET MyLib PROPERTY
IMPORTED_LOCATION ${myLibrary_DIR}/libmyLib.a)
#Other ways to include libmyLib.a in the ld process is to specify this library in
#CMAKE_EXE_LINKER_FLAGS as
#-L${myLibrary_DIR} -lmyLib
#or find_library(MyLib myLib PATHS ${myLibrary_DIR})
#and include MyLib in target_link_libraries.

#building a dictionary for ROOT GUI
#------------------------------------------------
set(INCLUDE_DIRECTORIES
${PROJECT_SOURCE_DIR}
${PROJECT_SOURCE_DIR}/include
${myLibrary_DIR}
${ROOT_INCLUDE_DIR}
)
include_directories(${INCLUDE_DIRECTORIES})

#generate the dictionary
#the following part is imported from http://lcio.desy.de/v01-60/cmake/MacroRootDict.cmake
set(MAINPRGM "myMain")
set(headers include/myMain.h)
set( _dict_includes )
FOREACH( _inc ${INCLUDE_DIRECTORIES} )
SET( _dict_includes "${_dict_includes}\t-I${_inc}")
ENDFOREACH()
ADD_CUSTOM_COMMAND(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${MAINPRGM}Dict.cpp ${CMAKE_CURRENT_BINARY_DIR}/${MAINPRGM}Dict.h
COMMAND ${ROOT_CINT_EXECUTABLE} -f ${CMAKE_CURRENT_BINARY_DIR}/${MAINPRGM}Dict.cpp -c ${_dict_includes} ${headers} include/${MAINPRGM}LinkDef.h
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
DEPENDS ${headers} include/${MAINPRGM}LinkDef.h
COMMENT "generating: ${MAINPRGM}Dict.cpp ${MAINPRGM}Dict.h"
)
list(APPEND headers ${CMAKE_CURRENT_BINARY_DIR}/${MAINPRGM}Dict.h)

#build the target
#-------------------------
#prepare for the ld flag
execute_process(COMMAND root-config --glibs OUTPUT_VARIABLE     
               ROOT_LD_FLAGS OUTPUT_STRIP_TRAILING_WHITESPACE)                 
set(CMAKE_EXE_LINKER_FLAGS "${ROOT_LD_FLAGS}")

#destination
set(sources src/myMain.cpp
${CMAKE_CURRENT_BINARY_DIR}/${MAINPRGM}Dict.cpp
)
add_executable(${PROJECT_NAME}.exe ${sources} ${headers})
target_link_libraries(${PROJECT_NAME}.exe MyLib)

2. build MyProject in myWKDIR
============================
> mkdir myWKDIR
> mkdir myWKDIR/build
cd myWKDIR/build
myWKDIR/build> cmake /directory_path_to/myProject/c++
myWKDIR/build> make

Any comments are welcome.

2/15/2014

Choosing a python bundle for PyROOT

After played with python 2.7 for a while, I got a need for ROOT drawings. So, I decided to try PyROOT which was supposed to be installed already in my ROOT 5.34.09 installation:

% port -v installed root
The following ports are currently installed:
  root @5.34.09_1+graphviz+gsl+minuit2+opengl+python27+roofit+soversion+ssl+tmva+xml (active) platform='darwin 12' archs='x86_64'

OK, python27 is there. But my python told

% python -c "import ROOT"
Traceback (most recent call last):
  File "<string>", line 1, in <module>
ImportError: No module named ROOT

Well, PyROOT needs two files, ROOT.py and libPyROOT.so which must be visible from python. Where are they?
% port contents root | grep ROOT.py
  /opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/ROOT.py
% port contents root | grep libPyROOT.so
  /opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/libPyROOT.so
  /opt/local/lib/root/libPyROOT.so

OK, you guys are there. But when I make these guys visible (by copying or symbolic links) from python, it told

% python -c "import ROOT"
Fatal Python error: PyThreadState_Get: no current thread
Abort trap: 6

What's wrong? After for a while, I found the bundle of python which I was using did not fit with the guy libPyROOT.so, who came through macport. To use this guy, I need to switch my python to the one came also from macport. This one was installed as /opt/local/bin/python2.7, and

%/opt/local/bin/python2.7 -c "import ROOT"

Passed!  What is the difference between 'em?

%/usr/bin/python
Python 2.7.5 (default, Aug  1 2013, 01:01:17)
[GCC 4.2.1 Compatible Apple Clang 4.1 ((tags/Apple/clang-421.11.66))] on darwin

%/opt/local/bin/python2.7
Python 2.7.5 (default, Aug 25 2013, 00:04:04) 
[GCC 4.2.1 Compatible Apple LLVM 5.0 (clang-500.0.68)] on darwin

Well, well, well. I can set my default python as the later one by, for instance,
sudo ln -s /opt/local/bin/python2.7 /opt/local/bin/python
and exporting PATH with /opt/local/bin placed earlier than /usr/bin so that I can just write, e.g.

%python -c "from ROOT import TCanvas"