How to use ROOT with VC++ to create library for WinXP?

Dear Rooters

I would like to try to build my library for WinXP, too, but have null experience with programming on WinXP.

Currently, I have downloaded and installed the following programs on my old WinXP laptop:

  1. VC++:
    I have downloaded from MS the iso image: “VS2008ExpressENUX1397868.iso” and installed:
    “Visual C++ 2008 Express Edition”

  2. ROOT:
    I have downloaded and installed the binary: “root_v5.18.00.win32.msi”

It is not quite clear to me how to proceed further, so I would appreciate any help.

Thank you in advance.
Best regards
Christian

Hi Christian,

You have to create a makefile for your project (or a MSVC ‘solution’)
Two options:

  • you have cygwin installed: take a look at ROOTSYS/test/Makefile
  • without cygwin: take a look at ROOTSYS/test/Makefile.win32
    you have to properly set the environment variables: start the batch file provided by Microsoft:
    c:\Program Files (x86)\Microsoft Visual Studio 8\VC\vcvarsall.bat
    (or similar path)

You can also search the forum, there are quite a few posts on the subject…

Cheers,
Bertrand.

Dear Bertrand

Thank you or your fast reply!

The first option, using cygwin, is a no-no for me for the following reason:
Some Windows users are interested to use my package, but they will never ever compile a program or package,
and they will never install cygwin. They will download the recommended ROOT binary (which I just installed)
and download a binary of my package which I need to supply.

Thus I will try your second option.

Best regards
Chirstian

Dear Bertrand

I have set the following environment variables:

INCLUDE:
C:\Programme\Microsoft Visual Studio 9.0\VC\include;C:\Programme\Microsoft SDKs\Windows\v6.0A\Include

LIB:
C:\Programme\Microsoft Visual Studio 9.0\VC\lib;C:\Programme\Microsoft SDKs\Windows\v6.0A\Lib;C:\root\lib

PATH:
C:\root\bin;C:\Programme\Microsoft Visual Studio 9.0\VC\bin;C:\Programme\Microsoft SDKs\Windows\v6.0A\bin;

Then I did run vcvarsall.bat as you said.

Finally, I started CMD and tried to compile the /root/test examples, but I got the following error:

C:\root\test>NMAKE /f “Makefile.win32” CFG=“Debug”

Microsoft ® Program Maintenance Utility Version 9.00.21022.08
Copyright © Microsoft Corporation. All rights reserved.

    cl  -D_MT -D_DLL -MDd -EHsc -nologo -GR -DWIN32  -DVISUAL_CPLUSPLUS 

-D_WINDOWS -IC:\root/include -D_CRT_SECURE_NO_DEPRECATE -Z7 -MDd -c Event.cxx
NMAKE : fatal error U1077: ‘“C:\Programme\Microsoft Visual Studio 9.0\VC\bin\cl.
EXE”’ : return code '0xc0000135’
Stop.

Can you tell me what mistake I did make?

Best regards
Christian

Hi Christian,

[quote]Then I did run vcvarsall.bat as you said.

Finally, I started CMD and tried to compile the /root/test examples, but I got the following error:[/quote]
Apparently a path is missing…
You must start vcvarsall.bat in the command prompt in which you will compile (it sets the variables for the current ‘shell’ only)

Bertrand.

Dear Bertrand

Thank you for your help, now I could compile and run the test samples.
From your answer I assume that I have to start vcvarsall.bat every time I start a new shell.

Best regards
Christian

Hi Christian,

You are welcome
And yes, you have to start vcvarsall.bat for each command prompt.
What you can do is to create a shortcut with this command on your desktop:

%comspec% /k ""C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\vcvarsall.bat""(just adapt it to your Visual C++ path)

Cheers, Bertrand.

Dear Bertrand

Thank you for this hint. With your help I could meanwhile test my first demo program, which I attach below (myclass.zip).

I could compile it successfully:

[code]
C:\home\Rabbitus\rootcode\myclass>NMAKE /f “Makefile.win32” CFG=“Debug”

Microsoft ® Program Maintenance Utility Version 9.00.21022.08

Copyright © Microsoft Corporation. All rights reserved.

    cl  -D_MT -D_DLL -MDd -EHsc -nologo -GR -DWIN32  -DVISUAL_CPLUSPLUS -D_W

INDOWS -Ic:\root/include -D_CRT_SECURE_NO_DEPRECATE -Z7 -MDd -c MyClassA.cxx

MyClassA.cxx

“Generating dictionary MyClassADict.cxx…”

    cl  -D_MT -D_DLL -MDd -EHsc -nologo -GR -DWIN32  -DVISUAL_CPLUSPLUS -D_W

INDOWS -Ic:\root/include -D_CRT_SECURE_NO_DEPRECATE -Z7 -MDd -c MyClassADict.cxx

MyClassADict.cxx

    link  /INCREMENTAL:NO /NOLOGO -entry:_DllMainCRTStartup@12 -dll -debug

/INCREMENTAL:NO /NOLOGO -subsystem:console,5.0 -nologo -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 -i

nclude:_G__cpp_setupG__PostScript -include:G__cpp_setupG__Matrix -include:G

cpp_setupG__Physics MyClassA.obj MyClassADict.obj c:\root/lib/libCore.lib c:\ro

ot/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/libR

int.lib c:\root/lib/libPostscript.lib c:\root/lib/libMatrix.lib c:\root/lib/lib

Physics.lib c:\root/lib/libNet.lib c:\root/lib/libRIO.lib c:\root/lib/libGui.li

b c:\root/lib/libGraf.lib c:\root/lib/libGpad.lib -out:libMyClassA.dll

Creating library libMyClassA.lib and object libMyClassA.exp

    mt -nologo -manifest libMyClassA.dll.manifest -outputresource:libMyClass

A.dll;2[/code]
and run it with root CINT.

However, when I try to compile it with ACLiC I get the following error:

[code]
root [0] gSystem->Load(“libMyClassA.dll”)

(int)0

root [1] .L macroMyClassA.C+

Info in TWinNTSystem::ACLiC: creating shared library C:\home\Rabbitus\rootcode

\myclass\macroMyClassA_C.dll

23444109_cint.cxx

cl : Command line warning D9002 : ignoring unknown option ‘-G5’

se4_.cxx

Creating library C:\home\Rabbitus\rootcode\myclass\macroMyClassA_C.lib and ob

ject C:\home\Rabbitus\rootcode\myclass\macroMyClassA_C.exp

se4_.obj : error LNK2019: unresolved external symbol "public: __thiscall MyClass

A::MyClassA(void)" (??0MyClassA@@QAE@XZ) referenced in function "void __cdecl Te

st(void)" (?Test@@YAXXZ)

C:\home\Rabbitus\rootcode\myclass\macroMyClassA_C.dll : fatal error LNK1120: 1 u

nresolved externals

Error in : Compilation failed![/code]
Is seems that ACLiC does not understand what a class is.
Do I have to add something?

BTW, is it possible to load the source code into VC++ and compile it from there?
Do I need special settings for VC++ to recognize root classes?

Best regards
Christian
myclass.zip (6.06 KB)

Hi Christian,

Please take a look at your modified files.
You have to generate a .lib file from your dll, and then link it.
To generate the lib file in the Makefile the following step is needed (note the bindexplib statement):

[code]MYLIB = lib$(MAIN).lib

[…]

(MYDLL): (MYOBJ)
bindexplib * (MYOBJ) > *.def lib -nologo -MACHINE:IX86 (MYOBJ) -def:*.def (OutPutOpt)(MYLIB) (LD) (SOFLAGS) (LDFLAGS) (MYOBJ) *.exp (GLIBS) (OutPutOpt)@ (MT_DLL)
[/code]
Then, to link with the library, use

#ifndef __CINT__ #pragma comment(lib, "libMyClassA.lib") #endif in macroMyClassA.C

Cheers,
Bertrand.
myclass.tar.gz (4.95 KB)

Dear Bertrand

First let me thank you for you help; second, I am also searching the RootTalk forum for help, but maybe VC90 is different.

Here are my current experiences with your modified example, which I appreciate very much:

When running the modified code I get:

root [0] gSystem->Load("libMyClassA.dll")
(int)0
root [1] .L macroMyClassA.C+
C:\home\Rabbitus\rootcode\myclass_VC\macroMyClassA_C.dll: Das angegebene Modul wurde nicht gefunden.
Load Error: Failed to load Dynamic link library C:\home\Rabbitus\rootcode\myclass_VC\macroMyClassA_C.dll
*** Interpreter error recovered ***

and the following Dialogbox:
root.exe - Component not found
Could not start application, since MSVCR90.dll could not be found.

Searching RootTalk forum I decided to add the following to my PATH:
C:\root\bin;C:\Programme\Microsoft Visual Studio 9.0\VC\bin;C:\Programme\Microsoft SDKs\Windows\v6.0A\bin;C:\Programme\Microsoft Visual Studio 9.0\VC\redist\x86\Microsoft.VC90.CRT;

Running now with ACLiC I get a huge error list and the following Dialogbox:
Microsoft Visual C++ Runtime Library
Runtime Error!
Program:C:\root\bin\root.exe
R6034
An application has made an attempt to load the C runtime library incorrectly.
Please contact the application’s support team for more information.

Sadly, even running with CINT results now in an error:

root [0] .L macroMyClassA.C
root [1] Test()
Error: MyClassA() header declared but not defined C:\home\Rabbitus\rootcode\myclass_VC\macroMyClassA.C(45)
*** Interpreter error recovered ***

It is completely unclear for me what is going on?

Best regards
Christian

Hi Christian,

It is probably a conflict between MSVC runtime libraries.
You dowloaded root_v5.18.00.win32.msi, which has been built with MSVC++7.1.
You should try root_v5.18.00.win32.vc80.msi (built with MSVC++8.0)
if it still doesn’t work, I will have to give you a version built with MSVC++9.0… which is not officially supported yet. (but I have it at home)
(blame Microsoft for this :imp: )

Cheers,
Bertrand.

Dear Bertrand

Thank you for your offer. At the moment I will stick with the official version, and hope that I will be able to adapt my program to MSVC.
Since CINT seems to work this may be sufficient for my purposes.

The reason why I downloaded root_v5.18.00.win32.msi is that users will always download the official binary version, so I have to make sure
that my program will work with this version.

Best regards
Christian

Dear Bertrand

Just by interest I tried to create a VC++ project by following:
gentit.home.cern.ch/gentit/roota … Debug.html

Although there are minor differences I could create a project with my example class.
However, building the project resulted in the following link error:

Build Log
 	 	

Build started: Project: VCmyclass, Configuration: Debug|Win32

Command Lines
 	 	

Creating temporary file "c:\home\Rabbitus\Projects\VCmyclass\VCmyclass\Debug\RSP00000427402240.rsp" with contents
[
/OUT:"C:\home\Rabbitus\Projects\VCmyclass\Debug\VCmyclass.exe" /MANIFEST /MANIFESTFILE:"Debug\VCmyclass.exe.intermediate.manifest" /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /DEBUG /PDB:"C:\home\Rabbitus\Projects\VCmyclass\Debug\VCmyclass.pdb" /DYNAMICBASE /NXCOMPAT /MACHINE:X86 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/libNet.lib c:\root/lib/libRIO.lib c:\root/lib/libGui.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib

".\Debug\MyClassA.obj"

".\Debug\MyClassADict.obj"
]
Creating command line "link.exe @c:\home\Rabbitus\Projects\VCmyclass\VCmyclass\Debug\RSP00000427402240.rsp /NOLOGO /ERRORREPORT:PROMPT"

Output Window
 	 	

Linking...
   Creating library C:\home\Rabbitus\Projects\VCmyclass\Debug\VCmyclass.lib and object C:\home\Rabbitus\Projects\VCmyclass\Debug\VCmyclass.exp
LINK : fatal error LNK1561: entry point must be defined

Results
 	 	

Build log was saved at "file://c:\home\Rabbitus\Projects\VCmyclass\VCmyclass\Debug\BuildLog.htm"
VCmyclass - 1 error(s), 0 warning(s)

Do you have any ideas?

Best regards
Christian

Hi Christian,

The linker tells you exactly what’s wrong:

[quote]LINK : fatal error LNK1561: entry point must be defined
[/quote]This means that you didn’t create a main() function for your executable… (main() in the entry point of any command line executable)

Cheers,
Bertrand.

Dear Bertrand

Thank you, I understand. However, I want to create a library and not an application.
Do I need also an entry point for a library?
Did I select the wrong settings?

BTW, “Visual C++ 2008 Express Edition” seems to be buggy, since selecting the panel
"Application Settings" in the “Win32 Application Wizard” caused the Wizard to hang.

Best regards
Christian

Christian,

indicates that the project is an executable…
You have to modify the project to create a DLL (or a static library).
Please take a look in MSVC help how to create different kind of projects, and take a look also in $ROOTSYS/test/Makefile.win32 to see differences between dlls and executables.

Bertrand.

Dear Bertrand

Thank you, simply changing “Configuration Type” to “Dynamic Library” solved the problem.

Best regards
Christian