Makefile doesn't work


I’m trying to compile a C++ program written for ROOT with a Makefile I created.
I’ve installed the last version of ROOT on Ubuntu 17.04. The root files are in the Download/root-6.08.06 directory.

These are the Makefile commands:

ROOTCFLAGS:= root-config --cflags
ROOTLFLAGS:= root-config --glibs
root: root.o
$( $(ROOTCFLAGS) $(ROOTLFLAGS) $(@F).o -o $(@F)
root.o: root.cpp
$( $(ROOTCFLAGS) -c $ *.cpp -o $(@F)
rm *.o

Before executing “make root” I go to the root directory and type . bin/, which should set all the necessary ambient variables to root directories.

If I try in the bash root-config --cflags and root-config --glibs I get the right paths to the /include and /lib directories.

However this is what I get:

make root
g++ -std=c++11 root-config --cflags -c root.cpp -o root.o
g++ -std=c++11 root-config --cflags root-config --glibs root.o -o root
root.o: In function graph_thread(void*)': root.cpp:(.text+0x5ab): undefined reference toTThread::Lock()'
root.cpp:(.text+0x5d4): undefined reference to TGraph::TGraph(int, double const*, double const*)' root.cpp:(.text+0x5e3): undefined reference toTGraph::SetTitle(char const*)'
root.cpp:(.text+0x604): undefined reference to TGraph::TGraph(int, double const*, double const*)' root.cpp:(.text+0x613): undefined reference toTGraph::SetTitle(char const*)'
root.cpp:(.text+0x633): undefined reference to TText::TText(double, double, char const*)' root.cpp:(.text+0x638): undefined reference toTThread::UnLock()'
root.cpp:(.text+0x648): undefined reference to TGraph::SetMaximum(double)' root.cpp:(.text+0x66c): undefined reference toTGraph::Draw(char const*)'
root.cpp:(.text+0x67b): undefined reference to TObject::Draw(char const*)' root.cpp:(.text+0x69f): undefined reference toTGraph::Draw(char const*)'
root.cpp:(.text+0x6e2): undefined reference to TObject::Draw(char const*)' root.cpp:(.text+0x720): undefined reference toTQObject::Emit(char const*)'
root.cpp:(.text+0x7a0): undefined reference to TText::~TText()' root.cpp:(.text+0x7a8): undefined reference toTGraph::~TGraph()'
root.cpp:(.text+0x7b0): undefined reference to TGraph::~TGraph()' root.cpp:(.text+0x9b3): undefined reference toTGraph::~TGraph()'
root.cpp:(.text+0x9c0): undefined reference to TGraph::~TGraph()' root.cpp:(.text+0x9cd): undefined reference toTText::~TText()'
root.o: In function TPad::Modified(bool)': root.cpp:(.text._ZN4TPad8ModifiedEb[_ZN4TPad8ModifiedEb]+0x25): undefined reference toTQObject::Emit(char const*)'
root.o: In function TCanvasImp::IsA() const': root.cpp:(.text._ZNK10TCanvasImp3IsAEv[_ZNK10TCanvasImp3IsAEv]+0x1): undefined reference toTCanvasImp::Class()'
root.o: In function TCanvasImp::ShowMembers(TMemberInspector&) const': root.cpp:(.text._ZNK10TCanvasImp11ShowMembersER16TMemberInspector[_ZNK10TCanvasImp11ShowMembersER16TMemberInspector]+0xd): undefined reference toTCanvasImp::Class()‘
root.cpp:(.text._ZNK10TCanvasImp11ShowMembersER16TMemberInspector[_ZNK10TCanvasImp11ShowMembersER16TMemberInspector]+0x21): undefined reference to ROOT::Class_ShowMembers(TClass*, void const*, TMemberInspector&)' root.o: In functionTApplicationImp::ShowMembers(TMemberInspector&) const’:
root.cpp:(.text._ZNK15TApplicationImp11ShowMembersER16TMemberInspector[_ZNK15TApplicationImp11ShowMembersER16TMemberInspector]+0xd): undefined reference to TApplicationImp::Class()' root.cpp:(.text._ZNK15TApplicationImp11ShowMembersER16TMemberInspector[_ZNK15TApplicationImp11ShowMembersER16TMemberInspector]+0x21): undefined reference toROOT::Class_ShowMembers(TClass*, void const*, TMemberInspector&)'
root.o: In function TApplicationImp::IsA() const': root.cpp:(.text._ZNK15TApplicationImp3IsAEv[_ZNK15TApplicationImp3IsAEv]+0x1): undefined reference toTApplicationImp::Class()'
root.o: In function _GLOBAL__sub_I_canvas': root.cpp:(.text.startup+0x11): undefined reference toTVersionCheck::TVersionCheck(int)'
root.o: In function main': root.cpp:(.text.startup+0xd1): undefined reference toTApplication::TApplication(char const*, int*, char**, void*, int)'
root.cpp:(.text.startup+0xdb): undefined reference to TStorage::ObjectAlloc(unsigned long)' root.cpp:(.text.startup+0xfb): undefined reference toTCanvas::TCanvas(char const*, char const*, int, int)'
root.cpp:(.text.startup+0x121): undefined reference to TPad::Divide(int, int, float, float, int)' root.cpp:(.text.startup+0x147): undefined reference toTThread::TThread(char const*, void* ()(void), void*, TThread::EPriority)'
root.cpp:(.text.startup+0x151): undefined reference to TThread::Run(void*)' root.cpp:(.text.startup+0x15e): undefined reference toTApplication::Run(bool)'
root.cpp:(.text.startup+0x163): undefined reference to TThread::SetCancelAsynchronous()' root.cpp:(.text.startup+0x16b): undefined reference toTThread::Kill()'
root.cpp:(.text.startup+0x17f): undefined reference to TThread::~TThread()' root.cpp:(.text.startup+0x187): undefined reference toTApplication::~TApplication()‘
root.cpp:(.text.startup+0x1e6): undefined reference to TObject::operator delete(void*)' root.cpp:(.text.startup+0x1ee): undefined reference toTApplication::~TApplication()‘
root.cpp:(.text.startup+0x206): undefined reference to TThread::~TThread()' root.o: In functionTApplicationImp::~TApplicationImp()’:
root.cpp:(.text._ZN15TApplicationImpD2Ev[_ZN15TApplicationImpD5Ev]+0x10): undefined reference to TString::~TString()' root.o: In functionTApplicationImp::~TApplicationImp()’:
root.cpp:(.text._ZN15TApplicationImpD0Ev[_ZN15TApplicationImpD5Ev]+0x14): undefined reference to TString::~TString()' root.o:([_ZTV15TApplicationImp]+0x80): undefined reference toTApplicationImp::Streamer(TBuffer&)'
root.o:([_ZTV10TCanvasImp]+0x100): undefined reference to `TCanvasImp::Streamer(TBuffer&)'
collect2: error: ld returned 1 exit status
Makefile:44: recipe for target ‘root’ failed
make: *** [root] Error 1

I’ve tried to fix it in the last two days but I didn’t manage to do anything. I haven’t even found a solution in the forum.

Thanks anyone who can help me!

You can just add “source dir_to_root/bin/” to the bashrc.

Or does the problem only occur by compiling via a makefile? Can you call ROOT directly in the shell?

When linking, the order of the libraries and files is important.
linker -lmyLib something-the-depends-on-lib is wrong,
linker something-the-depends-on-lib -lmyLib is correct.

So put the required libraries after the part that requires the lib. In your case, move $(ROOTLFLAGS) to the end of the line.

Personally I would suggest you try CMake. ROOT even comes with a FindROOT.cmake file for you to include.

Edit: have a look at

I would also suggest CMake. Judging from the following output:

g++ -std=c++11 root-config --cflags -c root.cpp -o root.o
g++ -std=c++11 root-config --cflags root-config --glibs root.o -o root

it looks like your forgot the back ticks around the root-config commands:

ROOTCFLAGS:= `root-config --cflags`
ROOTLFLAGS:= `root-config --glibs`
root: root.o
	$( $(ROOTCFLAGS) $(@F).o -o $(@F) $(ROOTLFLAGS)
root.o: root.cpp
	$( $(ROOTCFLAGS) -c $ *.cpp -o $(@F)
	rm *.o

First of all thanks everyone for the replies.

It tourned out I had to put the libs flags at at the end of the compilation code, as behrenhoff said. It’s strange because I’ve written the code on a Mac with a previous version of ROOT and I’ve managed to compile with the initial order of compilation, but probably I’m not remembering well.

Thank you again!

Might well be. If it works with the “wrong” order depends on the linker default settings. The correct order does not depend on linker default settings, i.e. the order shown in my post is always correct, your initial order might work or might not work.

For example, if you add the linker flag -Wl,--no-as-needed (or if that is the default setting), it will work. The default setting of your g++ is -Wl,--as-needed, basically discarding everything from the library that isn’t needed on the left side.

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