Building dependent shared libs with cygwin

Hello

Can somebody tell me how to build a shared library containing classes which derive from classes in another shared library with cygwin ?

To put it simply, I have a library libKVMultiDet.dll containing classes derived from ROOT classes. Another library libKVIndra.dll should contain classes derived from the ROOT classes and from those in libKVMultiDet.dll. With linux this is simply achieved by adding libKVMultiDet.so to the list of libraries to link with when building libKVIndra.so.

If I try to do the same thing with cygwin I end up with lots of ‘multiply defined symbol’ errors because all the ROOT classes are defined twice. If I don’t link with libKVMultiDet.dll then obviously all the classes in it are undefined, and it doesn’t work either.

My Makefiles are all based on test/Makefile and test/Makefile.arch; however I have also tried the suggestions in include/compiledata.h (variable MAKESHAREDLIB etc.) - by the way, why do the compile/linker options in this file differ significantly from the win32gcc target in test/Makefile.arch ?

In this case, the build of the 1st library looks like this:

g++ KVBase.o KVDetectorEvent.o KVDetector.o KVEvent.o KVList.o KVRList.o KVMaterial.o KVModule.o KVMult
iDetArray.o KVNucleus.o KVParticle.o KVPosition.o KVRing.o KVTelescope.o KVTestEvent.o KVLayer.o KVGrou
p.o KVCalibrator.o KVReconstructedNucleus.o KVBrowser.o KVDetectorBrowser.o KVWidget.o KVWidgetList.o K
VMultiDetBrowser.o KVLayerBrowser.o KVRingBrowser.o KVBrowserWidget.o KVACQParam.o KVBrowserNameDialog.
o KVTarget.o KVDataBase.o KVDBKey.o KVDBRecord.o KVDBTable.o KVRegister.o KVIDTelescope.o KV2Body.o KVD
ataBaseBrowser.o KVIDLine.o KVIDZLine.o KVIDZALine.o KVIDGrid.o KVIDZGrid.o KVIDZAGrid.o KVRegBinary.o
KVIDGridManager.o KVMultiDetDict.o -shared -Wl,-soname,libKVMultiDet.dll -Wl,–enable-auto-image-base -
Wl,–export-all-symbols -L/usr/X11R6/lib -L/cygdrive/c/root/lib -lCore -lCint -lHist -lGraf -lGraf3d -l
Gpad -lTree -lMatrix -lRint -lPhysics -lGui -o libKVMultiDet.dll
Info: resolving _gRandom by linking to __imp__gRandom (auto-import)
Info: resolving vtable for TNamedby linking to __imp___ZTV6TNamed (auto-import)
Info: resolving vtable for TIterby linking to __imp___ZTV5TIter (auto-import)
Info: resolving _gROOT by linking to __imp__gROOT (auto-import)
Info: resolving _gClient by linking to __imp__gClient (auto-import)
Info: resolving vtable for TCollectionby linking to __imp___ZTV11TCollection (auto-import)
Info: resolving vtable for TSeqCollectionby linking to __imp___ZTV14TSeqCollection (auto-import)
Info: resolving vtable for TListby linking to __imp___ZTV5TList (auto-import)
Info: resolving vtable for TRefby linking to __imp___ZTV4TRef (auto-import)
Info: resolving vtable for TGLayoutHintsby linking to __imp___ZTV13TGLayoutHints (auto-import)
Info: resolving vtable for TGHorizontalFrameby linking to __imp___ZTV17TGHorizontalFrame (auto-import)
Info: resolving vtable for TGTransientFrameby linking to __imp___ZTV16TGTransientFrame (auto-import)
Info: resolving vtable for TStringby linking to __imp___ZTV7TString (auto-import)
Info: resolving vtable for TQClassby linking to __imp___ZTV7TQClass (auto-import)
Info: resolving vtable for TGObjectby linking to __imp___ZTV8TGObject (auto-import)
Info: resolving vtable for TGWindowby linking to __imp___ZTV8TGWindow (auto-import)
Info: resolving vtable for TGFrameby linking to __imp___ZTV7TGFrame (auto-import)
Info: resolving vtable for TGCompositeFrameby linking to __imp___ZTV16TGCompositeFrame (auto-import)
Info: resolving vtable for TGTabby linking to __imp___ZTV5TGTab (auto-import)
Info: resolving vtable for TGMainFrameby linking to __imp___ZTV11TGMainFrame (auto-import)
libKVMultiDet.dll done

This library works fine on its own - I can load it in an interactive session and play with the classes no problem.
Then I try to build the 2nd library and get :

g++ KVINDRA.o KVSilicon.o KVChIo.o KVCsI.o KVPhoswich.o KVINDRAReconNuc.o KVINDRAReconEvent.o KVChannelVolt.o KVVoltEnergyAlpha.o KVChannelEnergyAlpha.o KVDBParameterSet.o KVDBRun.o KVDBSystem.o KVDBTape.o KVINDRACodes.o KVDBAlphaPeak.o KVINDRADB.o KVLineCSV.o KVINDRACodeMask.o KVChannelEnergyBrho.o KVIDSiCsI.o KVIDChIoSi.o KVIDCsI.o KVLineDST.o KVINDRADB1.o KVUpDater.o KVUpDater1.o KVINDRADB2.o KVUpDater2.o KVINDRA2.o KVINDRADB4.o KVUpDater4.o KVINDRA4.o KVIDPhoswich.o KVIDChIoCsI.o KVIDChIoSi75.o KVIDSi75SiLi.o KVIDSiLiCsI.o KVDBElasticPeak.o KVDBPeak.o KVChannelEnergyChIo.o KVLightEnergyCsI.o KVIDCsIRLLine.o KVIDGCsI.o KVIDGChIoSi.o KVIndraDict.o -shared -Wl,-soname,libKVIndra.dll -Wl,–enable-auto-image-base -Wl,–export-all-symbols -L/home/frankland/lib -lKVMultiDet -L/usr/X11R6/lib -L/cygdrive/c/root/lib -lCore -lCint -lHist -lGraf -lGraf3d -lGpad -lTree -lMatrix -lRint -lPhysics -o libKVIndra.dll

and the results are (I only include a few lines, there are far too many):

/home/frankland/lib/libKVMultiDet.dll(.text+0x0):streambuf-inst.cc: multiple definition of ___do_sjlj_init' /usr/lib/gcc-lib/i686-pc-cygwin/3.3.3/crtbegin.o(.text+0x0):crtstuff.c: first defined here /home/frankland/lib/libKVMultiDet.dll(.text+0xd92c0):streambuf-inst.cc: multiple definition ofKVBase::List()'
KVINDRA.o(.text$_ZN6KVBase4ListEv[KVBase::List()]+0x0):KVINDRA.cpp: first defined here
/home/frankland/lib/libKVMultiDet.dll(.text+0xdb6c0):streambuf-inst.cc: multiple definition of TNamed::IsSortable() const' KVINDRA.o(.text$_ZNK6TNamed10IsSortableEv[TNamed::IsSortable() const]+0x0):KVINDRA.cpp: first defined here /home/frankland/lib/libKVMultiDet.dll(.text+0xdb6d0):streambuf-inst.cc: multiple definition ofTNamed::Hash() const’
KVINDRA.o(.text$_ZNK6TNamed4HashEv[TNamed::Hash() const]+0x0):KVINDRA.cpp: first defined here
/home/frankland/lib/libKVMultiDet.dll(.text+0xdb6f0):streambuf-inst.cc: multiple definition of `TNamed::GetName() const’
KVINDRA.o(.text$_ZNK6TNamed7GetNameEv[TNamed::GetName() const]+0x0):KVINDRA.cpp: first defined here

etc. etc. etc.

Apologies if this is a trivial problem, but I haven’t found the answer anywhere on the web site, in the user’s guide, in the forum, or root-talk digest.

Thanks for any help
John.

Hi John,
the doc for this is in “info gcc” and “info ld” - the cygwin/i386PE target is what you’re interested in. Here is a summary of what you need, I’ll give the ld options as invoked by gcc:

g++ -shared -Wl,--enable-runtime-pseudo-reloc -Wl,--export-all-symbols [all objects] -Wl,--enable-auto-import -L... -l...You need to specify -Wl,–export-all-symbols before the first object file (the flag is sensitive to its position on the link line). And you need to specify -Wl,–enable-auto-import to allow your lib to pick up whatever it needs from the libraries you specify with -l (otherwise the traditional windows .def file is needed).

I’ll fix the inconsistency between test and the main Makefile.win32gcc when updating the gcc/ld flags next time, which is after the release of the next cygwin version. O, they released it yesterday - I’ll send the patch in today then :-]
Axel.

Hi Axel,

Thanks for the advice, unfortunately it doesn’t work any better than before. I still get an enormous list of ‘multiple definition’ errors when I try to build the second library, starting like this :

/home/frankland/lib/libKVMultiDet.dll(.text+0x0):streambuf-inst.cc: multiple definition of ___do_sjlj_init' /usr/lib/gcc-lib/i686-pc-cygwin/3.3.3/crtbegin.o(.text+0x0):crtstuff.c: first defined here /home/frankland/lib/libKVMultiDet.dll(.text+0xd92c0):streambuf-inst.cc: multiple definition ofKVBase::List()'
KVINDRA.o(.text$_ZN6KVBase4ListEv[KVBase::List()]+0x0):KVINDRA.cpp: first defined here
/home/frankland/lib/libKVMultiDet.dll(.text+0xdb6c0):streambuf-inst.cc: multiple definition of TNamed::IsSortable() const' KVINDRA.o(.text$_ZNK6TNamed10IsSortableEv[TNamed::IsSortable() const]+0x0):KVINDRA.cpp: first defined here /home/frankland/lib/libKVMultiDet.dll(.text+0xdb6d0):streambuf-inst.cc: multiple definition ofTNamed::Hash() const’
KVINDRA.o(.text$_ZNK6TNamed4HashEv[TNamed::Hash() const]+0x0):KVINDRA.cpp: first defined here
/home/frankland/lib/libKVMultiDet.dll(.text+0xdb6f0):streambuf-inst.cc: multiple definition of TNamed::GetName() const' KVINDRA.o(.text$_ZNK6TNamed7GetNameEv[TNamed::GetName() const]+0x0):KVINDRA.cpp: first defined here /home/frankland/lib/libKVMultiDet.dll(.text+0xdb700):streambuf-inst.cc: multiple definition ofTNamed::GetTitle() const’
KVINDRA.o(.text$_ZNK6TNamed8GetTitleEv[TNamed::GetTitle() const]+0x0):KVINDRA.cpp: first defined here
/home/frankland/lib/libKVMultiDet.dll(.text+0xdb860):streambuf-inst.cc: multiple definition of `TObject::GetOption() const’
KVINDRA.o(.text$_ZNK7TObject9GetOptionEv[TObject::GetOption() const]+0x0):KVINDRA.cpp: first defined here
etc. etc.

and ending like this :

KVIDGCsI.o(.text+0x672):KVIDGCsI.cpp: multiple definition of __fu61___ZTV5TIter' /home/frankland/lib/libKVMultiDet.dll(.text+0x55a2):streambuf-inst.cc: first defined here KVIDGCsI.o(.text+0x798):KVIDGCsI.cpp: multiple definition of__fu62___ZTV5TIter’
/home/frankland/lib/libKVMultiDet.dll(.text+0x7c65):streambuf-inst.cc: first defined here
KVIDGCsI.o(.text+0xea2):KVIDGCsI.cpp: multiple definition of `__fu63___ZTV5TIter’
/home/frankland/lib/libKVMultiDet.dll(.text+0x855b):streambuf-inst.cc: first defined here
/usr/lib/gcc-lib/i686-pc-cygwin/3.3.3/…/…/…/…/i686-pc-cygwin/bin/ld: BFD 2.15.94 20041229 assertion fail /netrel/src/binutils-20041229-1/bfd/cofflink.c:2270
/usr/lib/gcc-lib/i686-pc-cygwin/3.3.3/…/…/…/…/i686-pc-cygwin/bin/ld: /home/frankland/lib/libKVMultiDet.dll(d011375.o): illegal symbol index -397360059 in relocs
collect2: ld returned 1 exit status

Here is my link for the first library :

g++ -shared -Wl,–enable-runtime-pseudo-reloc -Wl,–export-all-symbols KVBase.o KVDetectorEvent.o KVDetector.o KVEvent.o KVList.o KVRList.o KVMaterial.o KVModule.o KVMultiDetArray.o KVNucleus.o KVParticle.o KVPosition.o KVRing.o KVTelescope.o KVTestEvent.o KVLayer.o KVGroup.o KVCalibrator.o KVReconstructedNucleus.o KVBrowser.o KVDetectorBrowser.o KVWidget.o KVWidgetList.o KVMultiDetBrowser.o KVLayerBrowser.o KVRingBrowser.o KVBrowserWidget.o KVACQParam.o KVBrowserNameDialog.o KVTarget.o KVDataBase.o KVDBKey.o KVDBRecord.o KVDBTable.o KVRegister.o KVIDTelescope.o KV2Body.o KVDataBaseBrowser.o KVIDLine.o KVIDZLine.o KVIDZALine.o KVIDGrid.o KVIDZGrid.o KVIDZAGrid.o KVRegBinary.o KVIDGridManager.o KVMultiDetDict.o -Wl,–enable-auto-import -L/usr/X11R6/lib -L/cygdrive/c/root/lib -lCore -lCint -lHist -lGraf -lGraf3d -lGpad -lTree -lMatrix -lRint -lPhysics -lGui -o libKVMultiDet.dll

And here is the second link, including the link to the first library :

g++ -shared -Wl,–enable-runtime-pseudo-reloc -Wl,–export-all-symbols KVINDRA.o KVSilicon.o KVChIo.o KVCsI.o KVPhoswich.o KVINDRAReconNuc.o KVINDRAReconEvent.o KVChannelVolt.o KVVoltEnergyAlpha.o KVChannelEnergyAlpha.o KVDBParameterSet.o KVDBRun.o KVDBSystem.o KVDBTape.o KVINDRACodes.o KVDBAlphaPeak.o KVINDRADB.o KVLineCSV.o KVINDRACodeMask.o KVChannelEnergyBrho.o KVIDSiCsI.o KVIDChIoSi.o KVIDCsI.o KVLineDST.o KVINDRADB1.o KVUpDater.o KVUpDater1.o KVINDRADB2.o KVUpDater2.o KVINDRA2.o KVINDRADB4.o KVUpDater4.o KVINDRA4.o KVIDPhoswich.o KVIDChIoCsI.o KVIDChIoSi75.o KVIDSi75SiLi.o KVIDSiLiCsI.o KVDBElasticPeak.o KVDBPeak.o KVChannelEnergyChIo.o KVLightEnergyCsI.o KVIDCsIRLLine.o KVIDGCsI.o KVIDGChIoSi.o KVIndraDict.o -Wl,–enable-auto-import -L/home/frankland/lib -lKVMultiDet -L/usr/X11R6/lib -L/cygdrive/c/root/lib -lCore -lCint -lHist -lGraf -lGraf3d -lGpad -lTree -lMatrix -lRint -lPhysics -lGui -o libKVIndra.dll

What am I doing wrong ?
Thanks a lot
John

PS. I did read the “ld” and “gcc” man pages, unfortunately it didn’t make me any wiser - well, actually I think I might have fallen into a coma before getting to the end… :open_mouth:

Hi,
what does ld-V, g++ --version give? I have GNU ld version 2.15.94 20041229, g++ (GCC) 3.3.3 (cygwin special). If you have a different one, update cygwin. I that doesn’t help, re-install these packages. If all fails, send me files to reproduce this, please (all .o and libs on your link line).
Axel.

Hi Axel,

I have exactly the same versions of g++ and ld. I reinstalled them as you suggest, the result is the same. I would be extremely grateful if you could try to build the libraries as you suggest.

You can get all the necessary files from the following links:
infodan.in2p3.fr/indra/KaliVedaD … ltiDet.tgz
infodan.in2p3.fr/indra/KaliVedaD … VIndra.tgz

The instructions for building the libs are on the web:
infodan.in2p3.fr/indra/KaliVedaD … ation.html
Basically you have to define a shell variable KVROOT to indicate where you want to install stuff, otherwise the Makefile will exit with an error.
The Makefiles for the two libraries include the last modifications I made according to your instructions.

Thankyou very very much
John.

Hi John,
sorry, that took me a while to figure out. It’s very simple, though: You create files a la libKVIndra.dll.1.3 (in $KVROOT/lib), and ld doesn’t know how to link those under windows. If you rename them to libKVIndra.1.3.dll everything works. And yes, even the symlink has to point to the proper dll, i.e. .1.3.dll, not dll.1.3 - apparently ld follows the symlink and then checks the file’s extension.
Axel.

Hi Axel

Thanks a lot, you’ve really been a great help. I’ve got both libraries to build now. However, I’m still having trouble with the symlinks. After running make for the 2 libraries, I have in my $KVROOT/lib directory both libraries with version numbers (libKVMultiDet.1.3.dll etc.) and two symlinks pointing to them (libKVMultiDet.dll -> libKVMultiDet.1.3.dll etc.). Now if I run ROOT and do
.L libKVMultiDet.dll
.L libKVIndra.dll
I get ‘dlopen Win32 error 126’, indicating that libKVIndra.dll (or something it depends on, like libKVMultiDet.dll for example) is missing from all the paths (even after adding $KVROOT/lib to my PATH). I tried setting the internal name of the libraries to ‘libKVMultiDet.dll’ and ‘libKVIndra.dll’ with ‘-Wl,–soname=…’ but that didn’t help. The solution seems to be to remove the symlink for libKVMultiDet and rename libKVMultiDet.1.3.dll as libKVMultiDet.dll: then I can load libKVIndra.dll with no problems (in fact, I don’t even need to load libKVMultiDet.dll beforehand, it’s done automatically as long as $KVROOT/lib is in PATH).
This is not a huge problem - I can simply abandon the idea of having dll’s with version numbers in the cygwin version - but I would like to know why you don’t have the same problem !!

Thanks a lot again
John

John,

Just for curiosity. Why do you try to use cygwin/gcc.
My experience is quite bad on this system. The performance is pretty bad,
typically a factor 3 worst than with cygwin/vc++7.1

Rene

Hi René

Is vc++ VisualC++ ? Isn’t that something you have to pay for ? (please excuse total ignorance)

In any case, I don’t have it. And I just started this out of idle curiosity after a colleague showed me how he had the best of both worlds - Linux and Windows - without having to reboot from one system to the other, thanks to cygwin. And coming from a Linux environment, ‘gcc’ has the advantage of being familiar (until you start actually trying to compile :wink: - see previous posts)

However, if vc++ is free and friendly, I’ll willingly take your advice…

Best regards
John

Hi John,

[quote=“j.d.frankland”]Now if I run ROOT and do
.L libKVMultiDet.dll
.L libKVIndra.dll
I get ‘dlopen Win32 error 126’, indicating that libKVIndra.dll (or something it depends on, like libKVMultiDet.dll for example) is missing from all the paths (even after adding $KVROOT/lib to my PATH).[/quote]
try gSystem->Load("libKVMultiDet");That works on all systems (root knows what so extension to append), and it works for me, even with symlinks. Only gSystem>Load() uses $PATH and $LD_LIBRARY_PATH, whereas .L is steered by (system).rootrc.

On the cygwin speed issue: I completely agree with Rene - cygwin is a test platform, not a production platform. Porting software to cygwin is fast and easy, but running it is pretty slow. MSVC is not free, but there is a free basic development kit available from MS, which includes the compiler. It might be good enough for your purposes of porting your library.

Axel.

Hi Axel,

I have exactly the same behaviour with gSystem->Load as with ‘.L’: if libKVMultiDet.dll is a symlink, then libKVIndra.dll will not load even if I load libKVMultiDet.dll by hand before it.

Nevermind, I’m sure it’s all much clearer with MSVC++ :laughing:

John

Oh dear, I can tell already I’m going to regret this, but I’m a sucker…

I started looking all over the web for this Visual C++ stuff. Axel, is the free download you mean the thing called “Visual C++ Toolkit 2003” ? I’m already pretty confused between Visual C++ (6 ? 7?), Visual Studio, and something called Visual .NET (???)…

Anyway, that’s what I downloaded, along with the win32gdk “recommended” binary for 4.02/00, defined the Windows environment variables ROOTSYS and Path according to Francois Gentit’s website, and (after downloading the MSVCP71.dll and MSVCR71.dll files - so I guess this means that I downloaded VC++6 ???) I can run ROOT using Start>Run> and giving the precise location of the ROOT executable (Path variable doesn’t seem very useful then…). Great. I edited the system.rootrc that came with the binary to add $ROOTSYS/tutorials to the macro path, and I try to execute the demos - actually behaviour is a little unstable, sometimes I get through all of benchmarks.C (less than 50% of the time), sometimes it blows up inbetween “na49view” and “Monte Carlo study of Z scaling” with a “C++ exception caught” error - I have never sent so many error reports to Microsoft in my life. Installation not quite correct ?

As for going any further, I have looked at your site and François’ site, and they seem to be talking about things I don’t have (like a GUI for Visual C++/Studio/NET/Thingamybob). Is there some doc out there for the poor man’s VC++ ?

John

Hi,
you’ve downloaded the right thing. I wouldn’t know of any doc for that, but it shouldn’t be that much different - execept for the fact that you’ll have to set everything via env vars instead of gui settings, see http://msdn.microsoft.com/visualc/vctoolkit2003/default.aspx?pull=/library/en-us/dv_vstechart/html/vctoolkitcmd.asp. I’m not claiming it’s easy, but it should be possible. Note that the compiler is only needed to build macros (or root). It’s not needed for running root or its tutorials, as long as you don’t compile them (i.e. .L tut.C is good, .L tut.C+ won’t work without the ms compiler on win32(gdk)).

The fact that it crashes from time to time could have plenty of reasons, so without being able to reproduce it it’s impossible to solve. You might have incompatible dll on your system, you’re out of disk space, it’s really hard to tell.

Axel.