Re: [ROOT] Unable to link libraries to gui

From: cstrato@EUnet.at
Date: Tue Aug 21 2001 - 23:54:52 MEST


Dear Jiri

Thank you very much for your offer, I have now created a
testcode which demonstrates the problems.

Below you can find all files including the make files:
gmake -f Makefile4MyClassA
gmake -f Makefile4MyClassB
gmake -f Makefile4Mygui

I include also a macro which shows that the libraries
work within root:
.x macroMyClass.C

When I delete all code using libMyClassB and link Mygui
only with libMyClassA, then the Mygui can be compiled
but running it gives the error:
./Mygui: error in loading shared libraries: ./Mygui: undefined symbol:
__8MyClassA

However, when I link both libraries, I get the link error:
Mygui.o: In function `TMyFrame::FRun1(void)':
Mygui.o(.text+0xc58): undefined reference to `MyClassA::MyClassA(void)'
./libMyClassB.so: undefined reference to `operator>>(TBuffer &, MyClassA
*&)'
collect2: ld returned 1 exit status

It seems that my make file may be incorrect?

Thank you very much for your help

Best regards
Christian

////////////////////////////////////
//--------- MyClassA.h -------------
#ifndef MYCLASSA
#define MYCLASSA

//////////////////////////////////////////////////////////////////////////

// MyClassA
//
//////////////////////////////////////////////////////////////////////////

#include "TObject.h"
#include "TString.h"

class MyClassA : public TObject
{
private:
   TString fString;

public:
   MyClassA();
   virtual ~MyClassA();
   virtual void FTest(const char *vName);

  ClassDef(MyClassA,1)  //MyClassA
};

#endif

//--------- MyClassA.cxx -------------
#include <stdio.h>
#include <stdlib.h>
#include <iostream.h>
#include <fstream.h>

#include "MyClassA.h"

ClassImp(MyClassA);

MyClassA::MyClassA()
{
}

MyClassA::~MyClassA()
{
}

void MyClassA::FTest(const char *vName)
{
   fString = vName;
   cout << "  MyClassA: fDir = " << vName << endl;
}

//--------- MyClassALinkDef.h -------------
#ifdef __CINT__

#pragma link off all globals;
#pragma link off all classes;
#pragma link off all functions;

#pragma link C++ class MyClassA+;

#endif

//--------- Makefile4MyClassA -------------
# Makefile for class MyClassA.
# shell: gmake -f Makefile4MyClassA

ARCH          = linuxppcegcs

CXX           =
ObjSuf        = o
SrcSuf        = cxx
ExeSuf        =
DllSuf        = so
OutPutOpt     = -o

ROOTCFLAGS   := $(shell root-config --cflags)
ROOTLIBS     := $(shell root-config --libs)
ROOTGLIBS    := $(shell root-config --glibs)


ifeq ($(ARCH),linuxegcs)
# Linux with egcs (>= RedHat 5.2)
CXX           = g++
CXXFLAGS      = -O -Wall -fPIC
LD            = g++
LDFLAGS       = -O
SOFLAGS       = -shared
endif

ifeq ($(ARCH),linuxppcegcs)
# MkLinux with egcs/glibc
CXX           = g++
CXXFLAGS      = -O -Wall -fPIC
LD            = g++
LDFLAGS       = -O
SOFLAGS       = -shared -Wl,-soname,
endif


CXXFLAGS     += $(ROOTCFLAGS)
LIBS          = $(ROOTLIBS) $(SYSLIBS)
GLIBS         = $(ROOTGLIBS) $(SYSLIBS)

#------------------------------------------------------------------------------

MYCLASSAO       = MyClassA.$(ObjSuf) MyClassADict.$(ObjSuf)
MYCLASSAS       = MyClassA.$(SrcSuf) MyClassADict.$(SrcSuf)
MYCLASSASO      = libMyClassA.$(DllSuf)


OBJS          = $(MYCLASSAO)
PROGRAMS      = $(MYCLASSASO)

#------------------------------------------------------------------------------

.SUFFIXES: .$(SrcSuf) .$(ObjSuf) .$(DllSuf)

all:            $(PROGRAMS)

$(MYCLASSASO):    $(MYCLASSAO)
                $(LD) $(SOFLAGS) $(LDFLAGS) $^ $(OutPutOpt) $@

clean:
  @rm -f $(OBJS) core

.SUFFIXES: .$(SrcSuf)

###


MyClassA.$(ObjSuf): MyClassA.h
MyClassADict.$(SrcSuf): MyClassA.h MyClassALinkDef.h
 @echo "Generating dictionary MyClassADict..."
 @rootcint -f MyClassADict.$(SrcSuf) -c MyClassA.h MyClassALinkDef.h

.$(SrcSuf).$(ObjSuf):
 $(CXX) $(CXXFLAGS) -c $<


////////////////////////////////////
//--------- MyClassB.h -------------
#ifndef MYCLASSB
#define MYCLASSB

//////////////////////////////////////////////////////////////////////////

// MyClassB
//
//////////////////////////////////////////////////////////////////////////

#include "TObject.h"
#include "TString.h"

#include "MyClassA.h"

class MyClassA;

class MyClassB : public TObject
{
private:
   MyClassA  *fClassA;
   TString fString;

public:
   MyClassB();
   virtual ~MyClassB();
   virtual void FTest(const char *vName);
   virtual void FTestA(const char *vName);

  ClassDef(MyClassB,1)  //MyClassB
};

#endif

//--------- MyClassB.cxx -------------
#include <stdio.h>
#include <stdlib.h>
#include <iostream.h>
#include <fstream.h>

#include "MyClassB.h"

ClassImp(MyClassB);

MyClassB::MyClassB()
{
   fClassA = new MyClassA();
}

MyClassB::~MyClassB()
{
   delete fClassA;
}

void MyClassB::FTest(const char *vName)
{
   fString = vName;
   cout << "  MyClassB: fDir = " << vName << endl;
}

void MyClassB::FTestA(const char *vName)
{
   fString = vName;
   fClassA->FTest(vName);
   cout << "  MyClassB: fDir = " << vName << endl;
}

//--------- MyClassBLinkDef.h -------------
#ifdef __CINT__

#pragma link off all globals;
#pragma link off all classes;
#pragma link off all functions;

#pragma link C++ class MyClassB+;

#endif

//--------- Makefile4MyClassB -------------
# Makefile for class MyClassB.
# shell: gmake -f Makefile4MyClassB

ARCH          = linuxppcegcs

CXX           =
ObjSuf        = o
SrcSuf        = cxx
ExeSuf        =
DllSuf        = so
OutPutOpt     = -o

ROOTCFLAGS   := $(shell root-config --cflags)
ROOTLIBS     := $(shell root-config --libs)
ROOTGLIBS    := $(shell root-config --glibs)


ifeq ($(ARCH),linuxegcs)
# Linux with egcs (>= RedHat 5.2)
CXX           = g++
CXXFLAGS      = -O -Wall -fPIC
LD            = g++
LDFLAGS       = -O
SOFLAGS       = -shared
endif

ifeq ($(ARCH),linuxppcegcs)
# MkLinux with egcs/glibc
CXX           = g++
CXXFLAGS      = -O -Wall -fPIC
LD            = g++
LDFLAGS       = -O
SOFLAGS       = -shared -Wl,-soname,
endif


CXXFLAGS     += $(ROOTCFLAGS)
LIBS          = $(ROOTLIBS) $(SYSLIBS)
GLIBS         = $(ROOTGLIBS) $(SYSLIBS)

#------------------------------------------------------------------------------

MYCLASSBO       = MyClassB.$(ObjSuf) MyClassBDict.$(ObjSuf)
MYCLASSBS       = MyClassB.$(SrcSuf) MyClassBDict.$(SrcSuf)
MYCLASSBSO      = libMyClassB.$(DllSuf)


OBJS          = $(MYCLASSBO)
PROGRAMS      = $(MYCLASSBSO)

#------------------------------------------------------------------------------

.SUFFIXES: .$(SrcSuf) .$(ObjSuf) .$(DllSuf)

all:            $(PROGRAMS)

$(MYCLASSBSO):    $(MYCLASSBO)
                $(LD) $(SOFLAGS) $(LDFLAGS) $^ $(OutPutOpt) $@

clean:
  @rm -f $(OBJS) core

.SUFFIXES: .$(SrcSuf)

###


MyClassB.$(ObjSuf): MyClassB.h
MyClassBDict.$(SrcSuf): MyClassB.h MyClassBLinkDef.h
 @echo "Generating dictionary MyClassBDict..."
 @rootcint -f MyClassBDict.$(SrcSuf) -c MyClassB.h MyClassBLinkDef.h

.$(SrcSuf).$(ObjSuf):
 $(CXX) $(CXXFLAGS) -c $<


/////////////////////////////////
//--------- Mygui.h -------------
#ifndef __MYGUI__
#define __MYGUI__

#include "RQ_OBJECT.h"
#include "TGFrame.h"
#include "TRootEmbeddedCanvas.h"
#include "TGMenu.h"
#include "TGLayout.h"
#include "TGTextEntry.h"
#include "TGTextBuffer.h"
#include "TGListBox.h"
#include "TGFileDialog.h"

#include "TString.h"

#include "MyClassA.h"
#include "MyClassB.h"

/*
// Constants
const Int_t kBufSize = 256;
const char *kSep = "=";
const char *kPathSep = "/";
const char *kSepPt = ".";
*/

class MyClassA;
class MyClassB;

//////////////////////////////////////////////////////////////////////////

// TMyFrame
//
//////////////////////////////////////////////////////////////////////////

class TMyFrame {

   RQ_OBJECT()

   private:
      TGMainFrame         *fMain;
      TGCompositeFrame    *fFrame;
      TRootEmbeddedCanvas *fCanvas;

      TGMenuBar           *fMenuBar;
      TGPopupMenu         *fMenuFile;
      TGLayoutHints       *fL1, *fL2, *fL3, *fL4, *fL5;

      TList               *fCleanup;
      Bool_t               fHasProject;

   // Parameters
      MyClassA  *fClassA;
      MyClassB  *fClassB;
      TString    fDir;

   public:
      TMyFrame(const TGWindow *vWindow, UInt_t vWidth, UInt_t vHeight);
      virtual ~TMyFrame();

      void FRun1();
      void FRun2();

   // Slots
      void FCloseWindow();
      void FHandleMenu(Int_t vId);

      ClassDef(TMyFrame,0) //MainFrame
};

#endif

//--------- Mygui.cxx -------------
#include <stdio.h>
#include <stdlib.h>
#include <iostream.h>
#include <fstream.h>

#include "TROOT.h"
#include "TApplication.h"
#include "TVirtualX.h"

#include "Mygui.h"

// Constants
const Int_t kBufSize = 256;
const char *kSep = "=";
const char *kPathSep = "/";
const char *kSepPt = ".";

// TMyFrame
enum ECommandIds {
   M_FILE,
   M_FILE_RUN1,
   M_FILE_RUN2,
   M_FILE_EXIT,
};


ClassImp(TMyFrame);

//----------------------------------------------------------------------//

// TMyFrame
//----------------------------------------------------------------------//

TMyFrame::TMyFrame(const TGWindow *vWindow, UInt_t vWidth, UInt_t
vHeight)
{
   fHasProject = kFALSE;
   fCleanup = new TList;

// Create main frame. A TGMainFrame is a top level window.
   fMain   = new TGMainFrame(vWindow, vWidth, vHeight);
   fMain->Connect("CloseWindow()", "TMyFrame", this, "FCloseWindow()");

// Create menubar and popup menus.
   fL1 = new TGLayoutHints(kLHintsTop | kLHintsLeft, 0, 4, 0, 0);
   fL2 = new TGLayoutHints(kLHintsTop | kLHintsRight);
   fL3 = new TGLayoutHints(kLHintsTop | kLHintsLeft | kLHintsExpandX, 0,
0, 1, 1);
   fL4 = new TGLayoutHints(kLHintsLeft | kLHintsTop);
   fL5 = new TGLayoutHints(kLHintsTop | kLHintsLeft, 5, 5, 5, 5);
   fCleanup->Add(fL1);
   fCleanup->Add(fL2);
   fCleanup->Add(fL3);
   fCleanup->Add(fL4);
   fCleanup->Add(fL5);

// File menu
   fMenuFile = new TGPopupMenu(gClient->GetRoot());
   fMenuFile->AddEntry("&Run1", M_FILE_RUN1);
   fMenuFile->AddEntry("&Run2", M_FILE_RUN2);
   fMenuFile->AddEntry("E&xit", M_FILE_EXIT);

// Connect menus to FHandleMenu method

fMenuFile->Connect("Activated(Int_t)","TMyFrame",this,"FHandleMenu(Int_t)");

// Add menus to MenuBar
   fMenuBar = new TGMenuBar(fMain, 1, 1, kHorizontalFrame);
   fMenuBar->AddPopup("&File", fMenuFile, fL1);

//   fDir = gSystem->WorkingDirectory();
   fDir = "/home/christian/dir";

   fMain->AddFrame(fMenuBar, fL3);

// Frame for Canvas
   fFrame = new TGCompositeFrame(fMain, 200, 20, kVerticalFrame);
   fMain->AddFrame(fFrame, fL4);

   fCanvas = new TRootEmbeddedCanvas("canvasA",fFrame,300,200);
   fFrame->AddFrame(fCanvas, fL5);

   fMain->SetWindowName("MyFrame");
   fMain->MapSubwindows();
   fMain->Resize(fMain->GetDefaultSize());
   fMain->SetWMPosition(140,120);
   fMain->MapWindow();
}//Constructor

//----------------------------------------------------------------------//

TMyFrame::~TMyFrame()
{
   fCleanup->Delete();
   delete fCleanup;

   delete fMenuBar;
   delete fMenuFile;

   delete fCanvas;
   delete fFrame;

   delete fMain;
}//Destructor

//----------------------------------------------------------------------//

void TMyFrame::FRun1()
{
   printf("FRun1-------------------------------\n");
   cout << "  Directory: " << fDir << endl;

   fClassA = new MyClassA();
   fClassA->FTest(fDir);
   delete fClassA;
}//FRun

//----------------------------------------------------------------------//

void TMyFrame::FRun2()
{
   printf("FRun2-------------------------------\n");
   cout << "  Directory: " << fDir << endl;

   fClassB = new MyClassB();
   fClassB->FTest(fDir);
   fClassB->FTestA(fDir);
   delete fClassB;
}//FRun

//----------------------------------------------------------------------//

void TMyFrame::FCloseWindow()
{
//   delete this;  //does not exit root
   gApplication->Terminate(0);  //exit root, needed for standalone App
}//FCloseWindow

//----------------------------------------------------------------------//

void TMyFrame::FHandleMenu(Int_t vId)
{
   switch (vId) {
   // File menu
      case M_FILE_RUN1:
         this->FRun1();
         break;

      case M_FILE_RUN2:
         this->FRun2();
         break;

      case M_FILE_EXIT:
         this->FCloseWindow();
         break;

      default:
         printf("Menu item %d selected\n", vId);
         break;
   }
}//FHandleMenu


//---- Main program
----------------------------------------------------//
TROOT root("Mygui", "GUI for test");


int main(int argc, char **argv)
{
   TApplication theApp("App", &argc, argv);

   if (gROOT->IsBatch()) {
      fprintf(stderr, "%s: Cannot run in batch mode\n", argv[0]);
      return 1;
   }

   new TMyFrame(gClient->GetRoot(), 400, 220);

   theApp.Run();

   return 0;
}


//--------- MyguiLinkDef.h -------------
#ifdef __CINT__

#pragma link off all globals;
#pragma link off all classes;
#pragma link off all functions;

#pragma link C++ class TMyFrame;

#endif

//--------- Makefile4Mygui -------------
# Makefile for Mygui.
# modified from root example Event
# shell: gmake -f Makefile4Mygui

ARCH          = linuxppcegcs

CXX           =
ObjSuf        = o
SrcSuf        = cxx
ExeSuf        =
DllSuf        = so
OutPutOpt     = -o

LPATH         = .
MYLIB    = -L$(LPATH) -lMyClassB -lMyClassA
#MYLIB    = -L$(LPATH) -lMyClassA

ROOTCFLAGS   := $(shell root-config --cflags)
ROOTLIBS     := $(shell root-config --libs)
ROOTGLIBS    := $(shell root-config --glibs)


ifeq ($(ARCH),linuxegcs)
# Linux with egcs (>= RedHat 5.2)
CXX           = g++
CXXFLAGS      = -I ./ -O -Wall -fPIC
LD            = g++
LDFLAGS       = -O
SOFLAGS       = -shared
endif

ifeq ($(ARCH),linuxppcegcs)
# MkLinux with egcs/glibc
CXX           = g++
CXXFLAGS      = -O -Wall -fPIC
LD            = g++
LDFLAGS       = -O
SOFLAGS       = -shared
endif

CXXFLAGS     += $(ROOTCFLAGS)
LIBS          = $(ROOTLIBS) $(SYSLIBS)
GLIBS         = $(ROOTGLIBS) $(SYSLIBS)

#------------------------------------------------------------------------------

MYGUIO      = Mygui.$(ObjSuf) MyguiDict.$(ObjSuf)
MYGUIS      = Mygui.$(SrcSuf) MyguiDict.$(SrcSuf)
MYGUI       = Mygui$(ExeSuf)

OBJS          = $(MYGUIO)

PROGRAMS      = $(MYGUI)

#------------------------------------------------------------------------------

.SUFFIXES: .$(SrcSuf) .$(ObjSuf) .$(DllSuf)

all:            $(PROGRAMS)

$(MYGUI):     $(MYGUIO)
# $(LD) $(LDFLAGS) $(MYGUIO) $(MYLIB) $(GLIBS) $(OutPutOpt) $(MYGUI)
 $(LD) $(LDFLAGS) $(OutPutOpt) $(MYGUI) $(MYGUIO) $(MYLIB) $(GLIBS)
#  $(LD) $(LDFLAGS) $^ $(MYLIB) $(GLIBS) $(OutPutOpt)$@
 @echo "$@ done"

clean:
 @rm -f $(OBJS) core

distclean:      clean
 @rm -f $(PROGRAMS) $(MYGUIO) *Dict.* *.def *.exp \
  *.root *.ps *.so .def so_locations
#  @rm -rf cxx_repository

.SUFFIXES: .$(SrcSuf)

###

Mygui.$(ObjSuf): Mygui.h
MyguiDict.$(SrcSuf): Mygui.h MyguiLinkDef.h
 @echo "Generating dictionary $@..."
 @rootcint -f $@ -c $^

.$(SrcSuf).$(ObjSuf):
 $(CXX) $(CXXFLAGS) -c $<


/////////////////////////////////
//--------- macroMyClass.C -------------
void macroMyClass()
{
   gROOT->Reset();
   gSystem->Load("/home/christian/rt/rootcode/xps/libMyClassA.so");
   gSystem->Load("/home/christian/rt/rootcode/xps/libMyClassB.so");

   MyClassA *vMyClassA = new MyClassA();
   MyClassB *vMyClassB = new MyClassB();

   vMyClassA->FTest("/home/TestNameAAA");
   vMyClassB->FTest("/home/TestNameBBB");
   vMyClassB->FTestA("/home/TestNameAAABBB");

   delete vMyClassB;
   delete vMyClassA;
}//macro





Jiri Masik wrote:

> Hi Christian,
>
> if you want send me your code+Makefile or all object files you are
> willing to link. or put it on a web. I'll have a look.
>
>         Jiri



This archive was generated by hypermail 2b29 : Tue Jan 01 2002 - 17:50:58 MET