Undefined references using root libraries in cygwin

Hello -

I am trying to link C++ code with ROOT libraries on WinXP, but I am unable to link to the ROOT libraries in cygwin. I get “undefined reference” errors, even though I believe the libraries are being found by the compile and link request. The makefile I am using works fine in Linux. Apparently the libraries are seen correctly but for some reason the applications are not being linked. I am suspicious of root-config --glibs output (see below).

I have cygwin_NT-5.1 with developer additions to the standard installation, so I have g++ etc. I installed the binary package root_v4.04.02.win32gdk.tar.gz, along with MS Visual Studio.NET 7.0 C++ package. Note that I am NOT trying to run within the VS environment. I want this to look like unix as much as possible. I never ran any Configure file because there is not one present in the root/ area. Root runs fine with the demos.C examples.

Several things I have noted while trying to debug this problem:

  1. root-config --glibs is used to produce the root library locations for linking in the make file and gives an odd result. The --cflags option seems OK. I did some copying and pasting to create root library linking options that seem to (almost) work. Note that the root-config output is shown below. My fix can be seen in the compile and link request.
  2. Root #include files are being found. I tried sticking in #include <gobble.h> to see if the compiler would complain, and it did.
  3. The root libraries are being found by the linker. I tried listing the paths in a variety of ways, and got an error message about not being able to find such and such file for every method except as listed below in the output from the compile and link request. I even tried adding an extra link -lgobble and got an error, so the software is paying attention.
  4. LD_LIBRARY_PATH is not set, and setting it to $ROOTSYS/lib does not make a difference.
  5. I can not get the root/test make to work either. I noticed that the makefile uses a VS routine called cl.exe to do the compiling, whereas I have been using gcc and g++. Still doesn’t work in root/test though. Output below.

Lots of output is listed below to help get a handle on this problem.

Thanks,
Scott


PATH and ROOTSYS from cygwin window


$ echo $PATH
/usr/local/bin:/usr/bin:/bin:/usr/X11R6/bin:/cygdrive/c/root/bin:/cygdrive/c/Pro
gram Files/Microsoft Visual Studio .NET 2003/Common7/IDE:/cygdrive/c/Program Fil
es/Microsoft Visual Studio .NET 2003/Vc7/bin:/cygdrive/c/Program Files/Microsoft
Visual Studio .NET 2003/SDK/v1.1/Bin:/cygdrive/c/WINDOWS/system32:/cygdrive/c/W
INDOWS:/cygdrive/c/WINDOWS/System32/Wbem:/cygdrive/c/Program Files/Common Files/
Adaptec Shared/System:/cygdrive/c/Program Files/SSH Communications Security/SSH
Secure Shell:‘cygpath -u c:/root’/bin:.

$echo $ROOTSYS
c:\root


OUTPUT FROM root-config


$ root-config --glibs
-include:_G__cpp_setupG__Hist -include:_G__cpp_setupG__Graf1 -include:_G__cpp_se
tupG__G3D -include:_G__cpp_setupG__GPad -include:G__cpp_setupG__Tree -include:
G__cpp_setupG__Rint -include:_G__cpp_setupG__PostScript -include:G__cpp_setupG
_Matrix -include:_G__cpp_setupG__Physics -include:_G__cpp_setupG__Gui1 ‘c:\root
lib\libCore.lib’ ‘c:\root\lib\libCint.lib’ ‘c:\root\lib\libHist.lib’ ‘c:\root\li
b\libGraf.lib’ ‘c:\root\lib\libGraf3d.lib’ ‘c:\root\lib\libGpad.lib’ ‘c:\root\li
b\libTree.lib’ ‘c:\root\lib\libRint.lib’ ‘c:\root\lib\libPostscript.lib’ ‘c:\roo
t\lib\libMatrix.lib’ ‘c:\root\lib\libPhysics.lib’ ‘c:\root\lib\libGui.lib’

$ root-config --cflags
-MD -I’c:\root\include’


OUTPUT from make in root/test


nutters@NKU-054570 /cygdrive/c/root/test
$ make
bindexplib libEvent Event.obj EventDict.obj > libEvent.def
lib -nologo -MACHINE:IX86 Event.obj EventDict.obj -def:libEvent.def
-out:libEvent.lib
Creating library libEvent.lib and object libEvent.exp
link -DLL -opt:ref -pdb:none -nologo Event.obj EventDict.obj libEvent.exp -incl
ude:_G__cpp_setupG__Hist -include:_G__cpp_setupG__Graf1 -include:G__cpp_setupG
_G3D -include:_G__cpp_setupG__GPad -include:_G__cpp_setupG__Tree -include:_G__cp
p_setupG__Rint -include:_G__cpp_setupG__PostScript -include:_G__cpp_setupG__Matr
ix -include:_G__cpp_setupG__Physics ‘c:\root\lib\libCore.lib’ ‘c:\root\lib\libCi
nt.lib’ ‘c:\root\lib\libHist.lib’ ‘c:\root\lib\libGraf.lib’ ‘c:\root\lib\libGraf
3d.lib’ ‘c:\root\lib\libGpad.lib’ ‘c:\root\lib\libTree.lib’ ‘c:\root\lib\libRint
.lib’ ‘c:\root\lib\libPostscript.lib’ ‘c:\root\lib\libMatrix.lib’ ‘c:\root\lib\l
ibPhysics.lib’
-out:libEvent.dll
link: invalid option – D
Try `link --help’ for more information.
make: *** [libEvent.dll] Error 1


OUTPUT from a compile and link request on my program (note my fix for linking):


g++ -MD -I’c:\root\include’ -o stump src/stump.cpp crmfile/crc16.o -Lcrmfile -Icrmfile -lcrmfile -L’c:\root\lib’ -lCore -lCint -lHist -lGraf -lGraf3d -lGpad -lTree -lRint -lPostscript -lMatrix -lPhysics -lGui
/cygdrive/c/temp/ccUu5vNu.o:stump.cpp:(.text+0x4c5): undefined reference to TAp plication::TApplication(char const*, int*, char**, void*, int)' /cygdrive/c/temp/ccUu5vNu.o:stump.cpp:(.text+0x4fd): undefined reference toTFi
le::TFile(char const*, char const*, char const*, int)’
/cygdrive/c/temp/ccUu5vNu.o:stump.cpp:(.text+0x549): undefined reference to TTr ee::TTree(char const*, char const*, int)' /cygdrive/c/temp/ccUu5vNu.o:stump.cpp:(.text+0x5a4): undefined reference toTOb
ject::operator delete(void*)’
/cygdrive/c/temp/ccUu5vNu.o:stump.cpp:(.text+0x6bf): undefined reference to TFi le::Write(char const*, int, int)' /cygdrive/c/temp/ccUu5vNu.o:stump.cpp:(.text+0x6d5): undefined reference toTFi
le::Close(char const*)’
/cygdrive/c/temp/ccUu5vNu.o:stump.cpp:(.text+0x6f9): undefined reference to TFi le::~TFile()' /cygdrive/c/temp/ccUu5vNu.o:stump.cpp:(.text+0x70e): undefined reference toTAp
plication::~TApplication()’
/cygdrive/c/temp/ccUu5vNu.o:stump.cpp:(.text+0x73e): undefined reference to TFi le::~TFile()' /cygdrive/c/temp/ccUu5vNu.o:stump.cpp:(.text+0x76b): undefined reference toTAp
plication::~TApplication()’
/cygdrive/c/temp/ccUu5vNu.o:stump.cpp:(.text$_ZN7TObjectnwEj[TObject::operator n
ew(unsigned int)]+0xd): undefined reference to TStorage::ObjectAlloc(unsigned i nt)' /cygdrive/c/temp/ccUu5vNu.o:stump.cpp:(.rdata$_ZTV10TCanvasImp[vtable for TCanva sImp]+0x60): undefined reference toTCanvasImp::ShowMembers(TMemberInspector&,
char*)’
/cygdrive/c/temp/ccUu5vNu.o:stump.cpp:(.rdata$_ZTV10TCanvasImp[vtable for TCanva
sImp]+0x64): undefined reference to TCanvasImp::Streamer(TBuffer&)' /cygdrive/c/temp/ccUu5vNu.o:stump.cpp:(.rdata$_ZTV15TApplicationImp[vtable for T ApplicationImp]+0x3c): undefined reference toTApplicationImp::ShowMembers(TMem
berInspector&, char*)’
/cygdrive/c/temp/ccUu5vNu.o:stump.cpp:(.rdata$_ZTV15TApplicationImp[vtable for T
ApplicationImp]+0x40): undefined reference to TApplicationImp::Streamer(TBuffer &)' /cygdrive/c/temp/ccUu5vNu.o:stump.cpp:(.text$_ZNK15TApplicationImp3IsAEv[TApplic ationImp::IsA() const]+0x7): undefined reference toTApplicationImp::Class()’
/cygdrive/c/temp/ccUu5vNu.o:stump.cpp:(.text$_ZN15TApplicationImpD0Ev[TApplicati
onImp::~TApplicationImp()]+0x19): undefined reference to TString::~TString()' /cygdrive/c/temp/ccUu5vNu.o:stump.cpp:(.text$_ZN15TApplicationImpD1Ev[TApplicati onImp::~TApplicationImp()]+0x19): undefined reference toTString::~TString()’
/cygdrive/c/temp/ccUu5vNu.o:stump.cpp:(.text$_ZNK10TCanvasImp3IsAEv[TCanvasImp::
IsA() const]+0x7): undefined reference to `TCanvasImp::Class()'
collect2: ld returned 1 exit status
make: *** [stump] Error 1


CODE fragment containing references


// ROOT Headers
#include “TApplication.h”
#include “TTimeStamp.h”
#include “TCanvas.h”
#include “TROOT.h”
#include “TTree.h”
#include “TFile.h”
#include “TArc.h”
#include “TH1.h”

int main(int argc, char **argv)
{

TApplication theApp(“stump”, NULL, NULL);

// Create output file and tree
TFile tree_file(“tree.root”,“RECREATE”);
TTree *t = new TTree(“t”,"");
// Set up the Tree
t->Branch(“tcd”, &tcd,“fADC[18][4]/S:fTDC[18][4]/S:fEvtNum/I”);
t->Branch(“cvd”, &cvd,“fADC[2][4]/S:fEvtNum/I”);

// loop over all data files
for (int i=1; i< argc; i++)
{
do_file(argv[i],t);
}

// write the root tree to a file
tree_file.Write();
tree_file.Close();
printf(“Data written to file ‘tree.root’\n”);

return 0;
}

Hi Scott,

You are using the native windows build, so there’s no use in having the gcc,… cygwin packages. But it doesn’t hurt either - as long as you don’t let them loose on the root build. The tools you want to use (i.e. that fit to your binary distribution) are MS Visual C++'s tools; the linker is called “link.exe”, the compiler “cl.exe”.

[quote=“Scott Nutter”]Several things I have noted while trying to debug this problem:

  1. root-config --glibs is used to produce the root library locations for linking in the make file and gives an odd result.[/quote]
    There’s nothing odd with your root-config output.

It’s not a fix :slight_smile: The original build is just fine, but it picks up the wrong link.exe. Simply run (under a cygwin bash) “mv /usr/bin/link.exe /usr/bin/link.exe.orig” and you’re done.

Note that your PATH is wrong; I assume you meant cygpath -u c:/root(backticks, not ticks).

Cheers, Axel.

Since you have Visual Studio installed you may not use “g++” .
Use “cl” - Visual C++ compiler instead.

Axel - Your fix of hiding the /usr/bin/link program worked so that root/test files can compile and run. And Valeri, thanks for pointing out that I am using the wrong compiler.

Sadly, I am not completely successful yet. I delved deeply into the root/test/Makefile and Makefile.arch files and now better understand how to write a Makefile that works across architectures and platforms. However, I still have one more problem. It probably does not have anything to do with root but you may know the solution.

Now I get a problem finding a standard include file during the compile:

$ make
cl -O2 -G5 -GR -GX -MD -DWIN32 -D_WINDOWS -nologo -DVISUAL_CPLUSPLUS -D_X86_=1 -
D_DLL -MD -I’c:\root\include’ -c src/stump.cpp -o stump.obj
stump.cpp
src\stump.cpp(12) : fatal error C1083: Cannot open include file: ‘stdint.h’: No
such file or directory
make: *** [stump] Error 2

What am I missing?

Scott

Do you really need the GNU make?
Can you use Microsoft “nmake” instead.
See $ROOTSYS/test/Makefile.win32 for example.
From VC++ command mode console do

cd %ROOTSYS%\test\ nmake -f Makefile.win32

Hi Scott,
I don’t know of any stdint.h on windows. Visual C++ contains stdarg.h, stddef.h, stdexcept, stdexcpt.h, stdio.h, stdlib.h.
Cheers, Axel.

I have a new respect for cross platform programming. What just works on linuxdeb doesn’t even begin to compile in win32gdk. What I have always assumed to be standard isn’t even close to normal.

I have my work cut out for me. Thanks for the help.

Scott

[quote=“Scott Nutter”]
What I have always assumed to be standard isn’t even close to normal.
Scott[/quote]

Excuse me the “standard” it is not what one “assumes”. “Standard” it is something which is written on the paper entitled “standard”.