Using Makefile in ROOTSYS/test under winXP cygwin with vc++

Hi

I’m trying to get to grips with ROOT on WinXP with the free Visual C++ kit, in order to port my code to this platform. I followed the collected wisdom of Bellenot, Naumann, Rademakers et al and got the Visual C++ toolkit installed, cygwin installed (without gcc) and ROOT installed (WindowsXP/NT/w2000 with VC++ 7.1 version 5.13/02).

ROOT runs fine, demos.C does everything it should, and I can compile and run macros on the Cint command line (.x/.L toto.C++).

Now I want to look into building libraries etc. with makefiles run under cygwin, so I go into ROOTSYS/test and try ‘make Hello’:

frankland@ganp571 /cygdrive/c/root/test
$ make Hello
cl -O2 -nologo -I/cygdrive/c/root//include -FIw32pragma.h -MD -GR -GX -G5 -I’c:\root\include’ -c Hello.cxx
cl : Command line warning D4029 : optimization is not available in the standard edition compiler
Hello.cxx
cl -O2 -nologo -I/cygdrive/c/root//include -FIw32pragma.h -MD -GR -GX -G5 -I’c:\root\include’ -c HelloDict.cxx
cl : Command line warning D4029 : optimization is not available in the standard edition compiler
HelloDict.cxx
link -DLL -opt:ref -pdb:none -nologo Hello.obj HelloDict.obj -include:_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__cpp_setupG__Rint -include:_G__cpp_setupG__PostScript -include:_G__cpp_setupG__Matrix -include:_G__cpp_setupG__Physics ‘c:\root\lib\libCore.lib’ ‘c:\root\lib\libCint.lib’ ‘c:\root\lib\libHist.lib’ ‘c:\root\lib\libGraf.lib’ ‘c:\root\lib\libGraf3d.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\libPhysics.lib’ -include:_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__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\lib\libGraf.lib’ ‘c:\root\lib\libGraf3d.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\libPhysics.lib’ ‘c:\root\lib\libGui.lib’ -out:Hello.dll
link: invalid option – D
Try `link --help’ for more information.
make: *** [Hello.dll] Error 1

Can anyone help please ?
John

PS. The Makefile.win32 doesn’t seem to be much help - it is not usable as is (syntax errors).

Hi,

mv /usr/bin/link.exe /usr/bin/link_orig.exe will do it. make is picking up cygwin’s link, not MSVC’s. Makefile.win32 is to be used with nmake (MS’s incarnation of make) - don’t bother.

Cheers, Axel.

Hi Axel,

Thanks a lot, I did what you said, it works fine. I got two warnings from link:

LINK : warning LNK4224: /PDB:NONE is no longer supported; ignored
Creating library Hello.lib and object Hello.exp
LINK : warning LNK4089: all references to ‘msvcp71.dll’ discarded by /OPT:REF

Any need to worry ?

In any case, I started ROOT and did

gSystem->Load("$ROOTSYS/test/Hello")
new Hello()

and it works fine.

Cheers,
John

Hi,

no, nothing to worry at all - one says “your flag telling me not to create debug info isn’t supported anymore”, the other one “you told me not to link what I don’t need, and I don’t need msvcp71.dll, so I don’t link it”. Whatever. Fine. :slight_smile:

Cheers, Axel.

Hi Axel,

I managed to get quite far in porting my stuff into this new environment, but I’ve hit a problem. Actually it’s the same problem you helped me with when I ported to cygwin/gcc…

In case you don’t remember :laughing: I build several different class libraries, with dependencies between the classes in different libraries. To build the libraries I am using the following part of $ROOTSYS/test/Makefile:

$(LIB_SO): $(OBJECTS) $(DICT_OBJ)

ifeq ($(PLATFORM),win32)
bindexplib lib$(PROJ_NAME) $^ > lib$(PROJ_NAME).def
lib -nologo -MACHINE:IX86 $^ -def:lib$(PROJ_NAME).def $(OutPutOpt)$(LIB_LIB)
$(LD) $(SOFLAGS) $(LDFLAGS) $^ lib$(PROJ_NAME).exp $(LIBS) $(GLIBS) $(LINK_LIB) $(OutPutOpt)$@
etc. etc.

where
PROJ_NAME = root name of library to build (KVMultiDet, KVVarGlob, etc.)
LIB_LIB = lib$(PROJ_NAME).lib
LIB_SO = lib$(PROJ_NAME).$(DllSuf) = lib$(PROJ_NAME).dll
OBJECTS = all the .obj of the classes in the library
DICT_OBJ = .obj of the rootcint-generated dictionary code
The other symbols should be defined in Makefile.arch.

I have a base library libKVMultiDet.dll which only depends on ROOT classes. I can build this with no problem.
Then libKVVarGlob.dll and libKVTrieur.dll both use classes in libKVMultiDet.dll. These I build by adding libKVMultiDet to LINK_LIB like so:
'C:\cygwin\home\frankland\KaliVeda\lib\libKVMultiDet.lib’
so that the entire ‘link’ looks like this:

link -DLL -opt:ref -pdb:none -nologo base/KVGVList.obj base/KVVarGlob.obj base/KVVarGlob1.obj base/KVVarGlobMean.obj charge/KVZbound.obj charge/KVZboundAv.obj charge/KVZmax.obj charge/KVZmean.obj charge/KVZtot.obj charge/KVZtotAv.obj energy/KVEkin.obj energy/KVEtrans.obj energy/KVEtransLCP.obj multiplicity/KVMultAv.obj multiplicity/KVMultIMF.obj multiplicity/KVMultIMFAv.obj multiplicity/KVMultLeg.obj multiplicity/KVMultLegAv.obj shape/KVRiso.obj shape/KVRisoAv.obj shape/KVTensP.obj shape/KVTensPCM.obj shape/KVTenseur3.obj momentum/KVPtot.obj momentum/KVZVtot.obj KVVarGlobDict.obj libKVVarGlob.exp -include:_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__cpp_setupG__Rint -include:_G__cpp_setupG__PostScript -include:_G__cpp_setupG__Matrix -include:_G__cpp_setupG__Physics ‘c:\root\lib\libCore.lib’ ‘c:\root\lib\libCint.lib’ ‘c:\root\lib\libHist.lib’ ‘c:\root\lib\libGraf.lib’ ‘c:\root\lib\libGraf3d.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\libPhysics.lib’ -include:_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__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\lib\libGraf.lib’ ‘c:\root\lib\libGraf3d.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\libPhysics.lib’ ‘c:\root\lib\libGui.lib’ ‘C:\cygwin\home\frankland\KaliVeda\lib\libKVMultiDet.lib’ -out:libKVVarGlob.dll

That works too. The problem is when I want to build libKVIndra.dll, which uses classes in both libKVMultiDet and libKVVarGlob. I add both libraries to LINK_LIB, but I get unresolved symbols concerning classes in the two libraries:

link -DLL -opt:ref -pdb:none -nologo analysis/KVINDRADataAnalyser.obj analysis/KVINDRAInteractiveDataAnalyser.obj analysis/KVIdentRoot.obj analysis/KVReconIdent.obj analysis/KVSelector.obj calibration/KVChannelEnergyAlpha.obj calibration/KVChannelEnergyBrho.obj calibration/KVChannelEnergyChIo.obj calibration/KVChannelVolt.obj calibration/KVLightEnergyCsI.obj calibration/KVVoltEnergy.obj db/KVDBAlphaPeak.obj db/KVDBChIoPressures.obj db/KVDBElasticPeak.obj db/KVDBParameterSet.obj db/KVDBPeak.obj db/KVDBTape.obj db/KVINDRADB.obj db/KVINDRADB1.obj db/KVINDRADB2.obj db/KVINDRADB4.obj db/KVINDRADBRun.obj db/KVINDRARunListReader.obj db/KVINDRARunSheetReader.obj db/KVINDRAUpDater.obj db/KVRunListLine.obj detectors/KVChIo.obj detectors/KVCsI.obj detectors/KVPhoswich.obj detectors/KVSilicon.obj events/KVINDRAReconEvent.obj events/KVINDRATriggerInfo.obj gui/KVINDRARunSheetGUI.obj gui/KVNewGridRRMDialog.obj identification/KVIDChIoCsI.obj identification/KVIDChIoSi.obj identification/KVIDChIoSi75.obj identification/KVIDCsI.obj identification/KVIDCsIRLLine.obj identification/KVIDGChIoSi.obj identification/KVIDGCsI.obj identification/KVIDPhoswich.obj identification/KVIDSi75SiLi.obj identification/KVIDSiCsI.obj identification/KVIDSiLiCsI.obj identification/KVINDRACodeMask.obj identification/KVINDRACodes.obj indra/KVINDRA.obj indra/KVINDRA2.obj indra/KVINDRA4.obj indra/KVINDRARRMValidator.obj indra/KVINDRAe475s.obj particles/KVINDRAReconNuc.obj KVIndraDict.obj libKVIndra.exp -include:_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__cpp_setupG__Rint -include:_G__cpp_setupG__PostScript -include:_G__cpp_setupG__Matrix -include:_G__cpp_setupG__Physics ‘c:\root\lib\libCore.lib’ ‘c:\root\lib\libCint.lib’ ‘c:\root\lib\libHist.lib’ ‘c:\root\lib\libGraf.lib’ ‘c:\root\lib\libGraf3d.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\libPhysics.lib’ -include:_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__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\lib\libGraf.lib’ ‘c:\root\lib\libGraf3d.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\libPhysics.lib’ ‘c:\root\lib\libGui.lib’ ‘C:\cygwin\home\frankland\KaliVeda\lib\libKVMultiDet.lib’ ‘C:\cygwin\home\frankland\KaliVeda\lib\libKVVarGlob.lib’ -out:libKVIndra.dll

this gives a lot of warnings about locally defined symbols being imported (same for the other libraries, doesn’t stop them working), and then:

KVSelector.obj : error LNK2019: unresolved external symbol “private: static class TString KVBase::KVFilesDir” (?KVFilesDir@KVBase@@0VTString@@A) referenced in function “public: static char const * __cdecl KVBase::GetKVFilesDir(void)” (?GetKVFilesDir@KVBase@@SAPBDXZ)
KVNewGridRRMDialog.obj : error LNK2019: unresolved external symbol “protected: static double KVNewGridDialog::scale_y” (?scale_y@KVNewGridDialog@@1NA) referenced in function “protected: virtual void __thiscall KVNewGridRRMDialog::layout_parameter_control_widgets(void)” (?layout_parameter_control_widgets@KVNewGridRRMDialog@@MAEXXZ)
KVNewGridRRMDialog.obj : error LNK2019: unresolved external symbol “protected: static double KVNewGridDialog::scale_x” (?scale_x@KVNewGridDialog@@1NA) referenced in function “protected: virtual void __thiscall KVNewGridRRMDialog::layout_parameter_control_widgets(void)” (?layout_parameter_control_widgets@KVNewGridRRMDialog@@MAEXXZ)
KVNewGridRRMDialog.obj : error LNK2019: unresolved external symbol “protected: static bool KVNewGridDialog::choose_scales” (?choose_scales@KVNewGridDialog@@1_NA) referenced in function “protected: virtual void __thiscall KVNewGridRRMDialog::layout_parameter_control_widgets(void)” (?layout_parameter_control_widgets@KVNewGridRRMDialog@@MAEXXZ)
KVNewGridRRMDialog.obj : error LNK2019: unresolved external symbol “protected: static bool KVNewGridDialog::choose_runs” (?choose_runs@KVNewGridDialog@@1_NA) referenced in function “protected: virtual void __thiscall KVNewGridRRMDialog::layout_parameter_control_widgets(void)” (?layout_parameter_control_widgets@KVNewGridRRMDialog@@MAEXXZ)
KVNewGridRRMDialog.obj : error LNK2019: unresolved external symbol “protected: static bool KVNewGridDialog::choose_mods” (?choose_mods@KVNewGridDialog@@1_NA) referenced in function “protected: virtual void __thiscall KVNewGridRRMDialog::layout_parameter_control_widgets(void)” (?layout_parameter_control_widgets@KVNewGridRRMDialog@@MAEXXZ)
KVNewGridRRMDialog.obj : error LNK2019: unresolved external symbol “protected: static bool KVNewGridDialog::choose_rings” (?choose_rings@KVNewGridDialog@@1_NA) referenced in function “protected: virtual void __thiscall KVNewGridRRMDialog::layout_parameter_control_widgets(void)” (?layout_parameter_control_widgets@KVNewGridRRMDialog@@MAEXXZ)
libKVIndra.dll : fatal error LNK1120: 7 unresolved externals

KVNewGridRRMDialog is a class in libKVIndra.dll which inherits from KVNewGridDialog, a class in libKVMultiDet.dll.
As for KVSelector (the first error), this is a class in libKVIndra.dll, but the strange thing is it seems to be complaining about an undefined reference in KVBase to … itself … (KVBase is in libKVMultiDet.dll).

I guess I’ve probably missed something trivial, but can you please help me (again) ?
Thanks a lot
John

Hi,

this is very difficult to debug without the code. You can do two things: use link’s /VERBOSE switch to see what it’s doing, and check that you don’t have link B.obj A.obj where A.obj depends on B.obj. You can also use “dumpbin /SYMBOLS A.obj” or “dumpbin /SYMBOLS A.lib” to check that it really contains the symbols it should.

Cheers, Axel.

Thanks Axel, I’ll try what you suggest. BTW, I don’t suppose the fact that all this stuff works on Linux and MacOSX platforms means anything, does it ? I guess the Windows linker just doesn’t work in the same way, or that the other systems let us get away with something that ‘link’ won’t allow…
John

Errr, is dumpbin a cygwin or a windows executable ? and where can i find it ? because neither cygwin nor dos seem to know…
sorry
john

Hi,

for me, dumpbin is where the MSVC compiler (cl.exe) is: /cygdrive/c/Program Files/Microsoft Visual Studio 8/VC/BIN/dumpbin

But maybe it’s not part of the free compiler set… Check Google, it probably knows of a location to get it.

Cheers, Axel.

Hi Axel,

I managed to get everything working, with a few slight code modifications. The problem seems to come from the linkage of static member variables.

In one case (the KVSelector.obj error) I call a static method of KVBase which returns the value of a static member variable. The error was that the variable in question seemed to be unknown when the method was accessed by a class defined outside of the library containing KVBase (there were other examples of classes in the same library using the same method with no problem). The method was implemented in the KVBase.h file. I moved the implementation to KVBase.cpp, and the problem went away.

The other errors were all due to trying to access protected static members of a base class (in libKVMultiDet.dll) from a derived class (in libKVIndra.dll). The members of the base class appeared to unknown to the linker. I added set/get methods for each member in the base class and used these instead in the derived class. No problem.

Thanks a lot for your help, Axel.
Best regards
John

Hi,

yes, these are two of the many limitations the windows linker has: you cannot have structs as exports (I assume that explains your base class member problem), and static functions must not be inline.

Cheers, Axel.