Compiling ROOT Gui applications

What is the trick for compiling ROOT gui applications with g++? I have no problems compiling ROOT code but when I attempt to compile and link a GUI app I get errors like:

[quote]/./example.cpp:24: undefined reference to TGMainFrame::TGMainFrame(TGWindow const*, unsigned int, unsigned int, unsigned int)' /./example.cpp:26: undefined reference toTGFrame::GetDefaultFrameBackground()’
/./example.cpp:26: undefined reference to `TRootEmbeddedCanvas::TRootEmbeddedCanvas(char const*, TGWindow const*, unsigned int, unsigned int, unsigned int, unsigned long)’
[/quote]
In this case, I’m trying to compile the GUI example from the user’s guide with a main() added.

[code]// example.C
#include <TGClient.h>
#include <TCanvas.h>
#include <TF1.h>
#include <TRandom.h>
#include <TGButton.h>
#include <TGFrame.h>
#include <TRootEmbeddedCanvas.h>
#include <RQ_OBJECT.h>

class MyMainFrame {
RQ_OBJECT(“MyMainFrame”)
private:
TGMainFrame *fMain;
TRootEmbeddedCanvas *fEcanvas;
public:
MyMainFrame(const TGWindow *p,UInt_t w,UInt_t h);
virtual ~MyMainFrame();
void DoDraw();
};

MyMainFrame::MyMainFrame(const TGWindow *p,UInt_t w,UInt_t h) {
// Create a main frame
fMain = new TGMainFrame(p,w,h);
// Create canvas widget
fEcanvas = new TRootEmbeddedCanvas(“Ecanvas”,fMain,200,200);
fMain->AddFrame(fEcanvas, new TGLayoutHints(kLHintsExpandX| kLHintsExpandY,
10,10,10,1));
// Create a horizontal frame widget with buttons
TGHorizontalFrame *hframe = new TGHorizontalFrame(fMain,200,40);
TGTextButton *draw = new TGTextButton(hframe,"&Draw");
draw->Connect(“Clicked()”,“MyMainFrame”,this,“DoDraw()”);
hframe->AddFrame(draw, new TGLayoutHints(kLHintsCenterX,5,5,3,4));
TGTextButton *exit = new TGTextButton(hframe,"&Exit",
“gApplication->Terminate(0)”);
hframe->AddFrame(exit, new TGLayoutHints(kLHintsCenterX,5,5,3,4));
fMain->AddFrame(hframe, new TGLayoutHints(kLHintsCenterX,2,2,2,2));
// Set a name to the main frame
fMain->SetWindowName(“Simple Example”);
// Map all subwindows of main frame
fMain->MapSubwindows();
// Initialize the layout algorithm
fMain->Resize(fMain->GetDefaultSize());
// Map main frame
fMain->MapWindow();
}

void MyMainFrame::DoDraw() {
// Draws function graphics in randomly choosen interval
TF1 *f1 = new TF1(“f1”,“sin(x)/x”,0,gRandom->Rndm()*10);
f1->SetFillColor(19);
f1->SetFillStyle(1);
f1->SetLineWidth(3);
f1->Draw();
TCanvas *fCanvas = fEcanvas->GetCanvas();
fCanvas->cd();
fCanvas->Update();
}

MyMainFrame::~MyMainFrame() {
// Clean up used widgets: frames, buttons, layouthints
fMain->Cleanup();
delete fMain;
}

void example() {
// Popup the GUI…
new MyMainFrame(gClient->GetRoot(),200,200);
}

int main(int argc, char *argv[]){
// Popup the GUI…
new MyMainFrame(gClient->GetRoot(),200,200);
}
[/code]

Thanks for any help you can provide.

2 Likes

Areyou linking with libGui ?
The recommended list of libs when working with GUI/Graphics can be seen/obtained via

root-config --glibs
you should get something like:

code [288] root-config --glibs
-L/Users/brun/root/lib -lCore -lCint -lRIO -lNet -lHist -lGraf -lGraf3d -lGpad -lTree -lRint -lPostscript -lMatrix -lPhysics -lMathCore -lThread -lGui -pthread -Wl,-rpath,/Users/brun/root/lib -lm -ldl
[/code]
more info in the Users Guide

Rene

Thanks Rene. That helps. I’m using

in the Makefile but for some reason on my system I get the following with out -lGui

When I add in -lGui explicitly, the code compiles but segfaults on

(gdb) where
#0  0x00002aaaadfdeb00 in TGClient::GetRoot () from /home/speterson/root/root_v5.26.00/lib/libGui.so
#1  0x000000000040353a in main (argc=1, argv=0x7fffff91c518) at example.cpp:73

I’m guessing the seg fault and the compile problems are related.

Note that you should use --glibs instead of --libs. That way you do not need to add -lGui manually.

1 Like
fixes the first problem, now on to the  seg fault . . . thanks Rene and kjan

fixes the first problem, now on to the seg fault . . . thanks Rene and kjan

Hi,

When creating a standalone application, you must create an instance of TApplication, e.g.:

int main(int argc, char *argv[]) { TApplication theApp("App", &argc, argv); // Popup the GUI... new MyMainFrame(gClient->GetRoot(),200,200); theApp.Run(); return 0; }
See for example $ROOTSYS/test/guitest.cxx

Cheers, Bertrand.

Hi, I know this thread is old. But I also have the same problem and get this segmentation fault. Using the GDB Debugger it seems that it happens on the following linenew Frame(gClient->GetRoot(),200,200);
I have --glibs and all other settings as discussed here in this thread, but it doesn’t help.

Any ideas?

thanks.
:slight_smile:

Hi,

Could you post a piece of code showing what you are trying to do?

Cheers, Bertrand.

Dear Bertrand,

I had the ambition to make a truly stand alone ROOT GUI application, inside a Mac App bundle, where all dependencies are met locally, and no ROOT installation is needed, and the program runs on every machine. I took the standard ROOT example from the ROOT User Guide, copy paste, and started to satisfy dependencies. I had a lot of success, but in the last step I get this seg fault. Please see the newest post in this thread: [url]Making MacOSX App bundles from ROOT GUI applications There I also have the complete code with the newest Makefile and bundler script.

Any help would be welcome. We can then put this example for everyone for the future.

Hi,

OK, then please avoid multiple posts for the same issue, to avoid confusion…
I don’t have access to a Mac, and this is obviously not the problem you have right now, but I see in your code that you are declaringclass Frame : public TGMainFrame { private: TGMainFrame *fMain;
And then using it in the Frame destructor:Frame::~Frame() { // Clean up used widgets: frames, buttons, layouthints fMain->Cleanup(); delete fMain; }But fMain has never been initialized, so this is going to crash…(and you should remove this class member anyway)

Cheers, Bertrand.

thanks for reply. Indeed this was a potential problem. But the segmentation fault still appears at the same position: new Frame(gClient->GetRoot(),200,200); Unfortunately the debugger doesn’t provide more information.

As I already mentioned, the program actually works without seg fault as long as ROOT is in path. The idea was to make the program independent. Now the same working program crashes with seg fault, when I remove ROOT from PATH and force it to use the locally available libs. I made sure that I satisfy all library dependencies locally, so that OSX doesn’t complain about missing dynamic libraries and actually tries to run the instant. But after running it seems that the call to gClient can not be handled.

I doubt it is a OSX specific problem. So what can it be? The experiment consists of 2 results: a software with locally available libs runs when ROOT is in path, and seg faults when not!!

From my basic understanding, there should be another lib which still needs to be made local. But which one is it?

[quote=“xaratustra”]As I already mentioned, the program actually works without seg fault as long as ROOT is in path. The idea was to make the program independent.[/quote]Well, ROOT is probably still looking for $ROOTSYS/etc, $ROOTSYS/fonts, $ROOTSYS/icons, and maybe some others… [quote=“xaratustra”]But after running it seems that the call to gClient can not be handled[/quote]gClient is defined in libGui, and it should be linked with your executable (you can use “root-config --glibs”). Note that some libraries are loaded via the plugin mechanism, which is looking for plugins in $ROOTSYS/etc/plugins.

[quote=“xaratustra”]From my basic understanding, there should be another lib which still needs to be made local. But which one is it?[/quote]As I just said, some of the libraries are loaded via the plugin manager…
One way of debugging this would be to have everything compiled in debug mode

Cheers, Bertrand.

Oh, that sounds I am at a dead end, the way to a truly stand alone application is stony and hard. #-o

I did some reverse engineering. Indeed you are right, the program needs $ROOTSYS/etc, $ROOTSYS/fonts, $ROOTSYS/icons and apart from that $ROOTSYS/libs. The last one is a surprise because I had actually met all dependencies that were visible to otool (which is the ldd under mac). These 4 directories make 127 MB of data, which can not be packed into a self contained portable bundle. Of course not everything is needed, e.g. I see that only one single font is needed for my program. I wish there would be a way to automatically identify all dependencies that are relevant only to current application.

I wonder why ROOT isn’t like any other library, like QT, GSL or FFTW etc… where you can just use the SO, DLL or DYLIB, and you are done on any OS or computer. Why all those Plugin/script stuff?

:frowning:

1 Like