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