I have a minimalistic event class that I would eventually like to write to a TTree. I would like to compile the class into a shared library object (in reality I will have more classes in the shared library) and load the shared library in a compiled macro for usage.
Below are the source codes of five files: MyEvt.h, MyEvt.C, LinkDef.h, Makefile, app.C, also attached as a tar ball example.tar (10 KB)
. To re-produce the problem, put all of these file to a single directory and run make
to compile the shared library libexample.so.
When doing
root
.L libexample.so
.x app.C+
Everything works nicely. However, when one does
root app.C++
there is a linker error. Hence, why is there different behavior, although I load the shared library inside the macro with ‘gSystem->Load(“libexample.so”)’? How do I need to change the Makefile, such that running with ‘root app.C++’ would work?
#ifndef MyEvt_h
#define MyEvt_h
#include "TObject.h"
class MyEvt : public TObject {
public:
MyEvt();
~MyEvt();
// setters/getters
void SetVar(Double_t v) { fVar = v; }
Double_t GetVar() { return fVar; }
private:
Double_t fVar;
ClassDef(MyEvt, 1)
};
#include "MyEvt.h"
MyEvt::MyEvt() {
fVar = 0;
}
MyEvt::~MyEvt() {}
LinkDef.h def and Makefile:
#ifdef __CINT__
#pragma link off all globals;
#pragma link off all classes;
#pragma link off all functions;
#pragma link C++ class MyEvt+;
#endif
ROOTCFLAGS = $(shell root-config --cflags)
ROOTLIBS = $(shell root-config --libs)
CXX = $(shell root-config --cxx)
CXXFLAGS = -g -Wall -std=c++11 -fPIC
CXXFLAGS += $(ROOTCFLAGS)
LDFLAGS += $(ROOTLIBS)
PACKAGE = example
HEADERS = $(filter-out $(CURDIR)/LinkDef.h, $(wildcard $(CURDIR)/*.h))
SOURCES = $(filter-out $(CURDIR)/app.C, $(wildcard $(CURDIR)/*.C))
TARGET_LIB = $(CURDIR)/lib$(PACKAGE).so
DICTIONARY = $(CURDIR)/dic$(PACKAGE).cxx
all: $(TARGET_LIB)
$(TARGET_LIB): $(SOURCES) $(DICTIONARY)
@echo " Building $(PACKAGE)..."
@$(CXX) $(CXXFLAGS) -shared -O3 -o $@ $^ $(LDFLAGS)
$(DICTIONARY): $(HEADERS) LinkDef.h
@echo " Making dictionary for $(PACKAGE)..."
@rootcint -f $@ -c $^
clean:
@echo " Cleaning $(PACKAGE)..."
@rm -f $(TARGET_LIB)
@rm -f $(DICTIONARY)
@rm -f $(DICTIONARY:%.cxx=%.h)
@rm -f *rdict.pcm
.PHONY: clean all
And finally the macro where library is used:
#include "MyEvt.h"
#include "TSystem.h"
#include "TTree.h"
#include "TFile.h"
void app() {
gSystem->Load("libexample.so");
MyEvt *evt = new MyEvt();
TFile fout("fout.root","RECREATE");
TTree tout("t","t");
tout.Branch("evt", &evt);
for (Int_t i = 0; i < 10; i++) {
evt->SetVar(i);
tout.Fill();
}
fout.Close();
}
ROOT Version: 6.12.06, downloaded binary
Platform: Scientific linux 7
Compiler: gcc version 4.8.5