Wednesday, April 9, 2008

compiling with std::min, std::max in Visual Studio 2008

I had a program which was working well in Visual Studio 6.0. I wanted to upgrade my compiler to VS9.0.  When I compiled the code (snippet listed below), I got the following error message.

void
SVD::Rank( int inRank )
{
mRank = inRank;

int max_rank = std::min( mS.size(), mU.size() ); <-- Line 329
if( mRank < 0 || mRank > max_rank )
{
mRank = max_rank;
}

} // SVD::Rank





1>------ Build started: Project: sci, Configuration: Debug Win32 ------
1>Compiling...
1>SVD.cpp
1>d:\projects\dev\libs\sci\svd.cpp(329) : error C2589: '(' : illegal token on right side of '::'
1>d:\projects\dev\libs\sci\svd.cpp(329) : error C2059: syntax error : '::'
1>Build log was saved at "file://d:\projects\dev\libs\sci\Debug\BuildLog.htm"
1>sci - 2 error(s), 0 warning(s)
========== Build: 0 succeeded, 1 failed, 1 up-to-date, 0 skipped ==========



When I googled for this error, I found the following article from DevX.com (http://www.devx.com/tips/Tip/14540).




The Standard Library defines the two template functions std::min() and std::max() in the <algorithm> header. In general, you should use these template functions for calculating the min and max values of a pair. Unfortunately, Visual C++ does not define these function templates. This is because the names min and max clash with the traditional min and max macros defined in <windows.h>. As a workaround, Visual C++ defines two alternative templates with identical functionality called _cpp_min() and _cpp_max(). You can use them instead of std::min() and std::max().To disable the generation of the min and max macros in Visual C++, #define NOMINMAX before #including <windows.h>.




Interesting, this solution was not really doable for me as I was compiling with ACE libraries (TAO 1.5a) with STLport (STL 5.1.5).  With ACE, I would be including <ace/OS.h> instead of <windows.h> and inserting #define NOMINMAX before #include <ace/OS.h> is not a good solution for me.  So I did the following.  Wherever, I use std::min, std::max, I had included <algorithm> header, but before that inclusion of <algorithm> I had forcible undefined min and max symbols like the following




#undef min
#undef max
#include <algorithm> // for std::sort, std::min, std::max



I got my source compiled without errors now.

Tuesday, April 8, 2008

Compile STLport 5.1.5 with Visual Studio 2008

As of today, the lastest version of STLPort is 5.1.5 and Visual Studio is 9.0 (2008).

STLport 5.1.5 does not directly support VS9 environment.  It contains solution files for VS8 (2005).  So, you need to make some tweaks make compile STL 5.1.5 with VS9.

I extracted the package at d:\projects in my WinXP machine.  Since, there is no option for MSVC 9, I used MSVC 8.

D:\projects\STLport-5.1.5>cd build\lib

D:\projects\STLport-5.1.5\build\lib>dir
Volume in drive D is BUILD
Volume Serial Number is E451-615B

Directory of D:\projects\STLport-5.1.5\build\lib

04/08/2008  02:18 PM    <DIR>          .
04/08/2008  02:18 PM    <DIR>          ..
04/19/2005  02:55 AM                 9 .cvsignore
11/01/2005  01:55 PM               393 aCC.mak
03/25/2006  01:27 AM               638 bcc.mak
11/18/2005  04:00 PM               422 CC.mak
07/08/2006  01:15 AM             4,049 configure
03/31/2007  02:41 AM            15,847 configure.bat
11/27/2005  02:25 AM               442 dmc.mak
05/31/2006  06:38 PM             1,156 evc.mak
12/27/2005  01:48 PM               383 gcc.mak
04/19/2005  02:55 AM               470 icc.mak
11/27/2005  02:50 AM                39 icl.mak
10/08/2007  12:49 AM             1,226 Makefile.inc
07/12/2006  01:43 AM             1,049 msvc.mak
11/01/2005  01:55 PM               401 mwccnlm.mak
02/08/2006  02:04 AM             1,881 nmake-src-prefix.mak
11/20/2005  09:16 PM             2,107 README
              16 File(s)         30,512 bytes
               2 Dir(s)     151,138,304 bytes free

D:\projects\STLport-5.1.5\build\lib>configure -c msvc8
STLport Configuration Tool for Windows

Setting compiler: Microsoft Visual C++ 2005

Done configuring STLport.

Please type "nmake /fmsvc.mak" to build STLport.
Type "nmake /fmsvc.mak install" to install STLport to the "lib"
and "bin" folder when done.

D:\projects\STLport-5.1.5\build\lib>

When I ran nmake /fmsvc.mak, I got the following error:

D:\projects\STLport-5.1.5\build\lib>nmake /fmsvc.mak

Microsoft (R) Program Maintenance Utility Version 9.00.21022.08
Copyright (C) Microsoft Corporation.  All rights reserved.

        cl /nologo /W4 /Wp64 /GR /EHsc /Zm800  /GL /MD /Zi /O2  /DWIN32 /D_WINDOWS /DNDEBUG  /I../../stlport  /c /Foobj\
vc8\shared\dll_main.o /Fdobj\vc8\shared\stlport.5.1.pdb ../../src\dll_main.cpp
cl : Command line warning D9035 : option 'Wp64' has been deprecated and will be removed in a future release
dll_main.cpp
D:\projects\STLport-5.1.5\stlport\stl/_locale.h(108) : error C2487: 'collate' : member of dll interface class may not be
declared with dll interface
D:\projects\STLport-5.1.5\stlport\stl/_locale.h(109) : error C2487: 'ctype' : member of dll interface class may not be declared with dll interface
D:\projects\STLport-5.1.5\stlport\stl/_locale.h(110) : error C2487: 'monetary' : member of dll interface class may not be declared with dll interface
D:\projects\STLport-5.1.5\stlport\stl/_locale.h(111) : error C2487: 'numeric' : member of dll interface class may not be declared with dll interface
D:\projects\STLport-5.1.5\stlport\stl/_locale.h(112) : error C2487: 'time' : member of dll interface class may not be declared with dll interface
D:\projects\STLport-5.1.5\stlport\stl/_locale.h(113) : error C2487: 'messages' : member of dll interface class may not be declared with dll interface
D:\projects\STLport-5.1.5\stlport\stl/_locale.h(118) : error C2487: 'all' : member of dll interface class may not be declared with dll interface
D:\projects\STLport-5.1.5\stlport\stl/_ios_base.h(74) : error C2487: 'right' : member of dll interface class may not bedeclared with dll interface
D:\projects\STLport-5.1.5\stlport\stl/_ios_base.h(75) : error C2487: 'internal' : member of dll interface class may not be declared with dll interface
D:\projects\STLport-5.1.5\stlport\stl/_ios_base.h(76) : error C2487: 'dec' : member of dll interface class may not be declared with dll interface
D:\projects\STLport-5.1.5\stlport\stl/_ios_base.h(77) : error C2487: 'hex' : member of dll interface class may not be declared with dll interface
D:\projects\STLport-5.1.5\stlport\stl/_ios_base.h(78) : error C2487: 'oct' : member of dll interface class may not be declared with dll interface
D:\projects\STLport-5.1.5\stlport\stl/_ios_base.h(79) : error C2487: 'fixed' : member of dll interface class may not be declared with dll interface
D:\projects\STLport-5.1.5\stlport\stl/_ios_base.h(80) : error C2487: 'scientific' : member of dll interface class may not be declared with dll interface
D:\projects\STLport-5.1.5\stlport\stl/_ios_base.h(81) : error C2487: 'boolalpha' : member of dll interface class may not be declared with dll interface
D:\projects\STLport-5.1.5\stlport\stl/_ios_base.h(82) : error C2487: 'showbase' : member of dll interface class may not be declared with dll interface
D:\projects\STLport-5.1.5\stlport\stl/_ios_base.h(83) : error C2487: 'showpoint' : member of dll interface class may not be declared with dll interface
D:\projects\STLport-5.1.5\stlport\stl/_ios_base.h(84) : error C2487: 'showpos' : member of dll interface class may not be declared with dll interface
D:\projects\STLport-5.1.5\stlport\stl/_ios_base.h(85) : error C2487: 'skipws' : member of dll interface class may not be declared with dll interface
D:\projects\STLport-5.1.5\stlport\stl/_ios_base.h(86) : error C2487: 'unitbuf' : member of dll interface class may not be declared with dll interface
D:\projects\STLport-5.1.5\stlport\stl/_ios_base.h(87) : error C2487: 'uppercase' : member of dll interface class may not be declared with dll interface
D:\projects\STLport-5.1.5\stlport\stl/_ios_base.h(88) : error C2487: 'adjustfield' : member of dll interface class may not be declared with dll interface
D:\projects\STLport-5.1.5\stlport\stl/_ios_base.h(89) : error C2487: 'basefield' : member of dll interface class may not be declared with dll interface
D:\projects\STLport-5.1.5\stlport\stl/_ios_base.h(90) : error C2487: 'floatfield' : member of dll interface class may not be declared with dll interface
D:\projects\STLport-5.1.5\stlport\stl/_ios_base.h(93) : error C2487: 'goodbit' : member of dll interface class may not be declared with dll interface
D:\projects\STLport-5.1.5\stlport\stl/_ios_base.h(94) : error C2487: 'badbit' : member of dll interface class may not be declared with dll interface
D:\projects\STLport-5.1.5\stlport\stl/_ios_base.h(95) : error C2487: 'eofbit' : member of dll interface class may not be declared with dll interface
D:\projects\STLport-5.1.5\stlport\stl/_ios_base.h(96) : error C2487: 'failbit' : member of dll interface class may not be declared with dll interface
D:\projects\STLport-5.1.5\stlport\stl/_ios_base.h(99) : error C2487: '__default_mode' : member of dll interface class may not be declared with dll interface
D:\projects\STLport-5.1.5\stlport\stl/_ios_base.h(100) : error C2487: 'app' : member of dll interface class may not be declared with dll interface
D:\projects\STLport-5.1.5\stlport\stl/_ios_base.h(101) : error C2487: 'ate' : member of dll interface class may not be declared with dll interface
D:\projects\STLport-5.1.5\stlport\stl/_ios_base.h(102) : error C2487: 'binary' : member of dll interface class may not be declared with dll interface
D:\projects\STLport-5.1.5\stlport\stl/_ios_base.h(103) : error C2487: 'in' : member of dll interface class may not be declared with dll interface
D:\projects\STLport-5.1.5\stlport\stl/_ios_base.h(104) : error C2487: 'out' : member of dll interface class may not be declared with dll interface
D:\projects\STLport-5.1.5\stlport\stl/_ios_base.h(105) : error C2487: 'trunc' : member of dll interface class may not be declared with dll interface
D:\projects\STLport-5.1.5\stlport\stl/_ios_base.h(109) : error C2487: 'beg' : member of dll interface class may not be declared with dll interface
D:\projects\STLport-5.1.5\stlport\stl/_ios_base.h(110) : error C2487: 'cur' : member of dll interface class may not be declared with dll interface
D:\projects\STLport-5.1.5\stlport\stl/_ios_base.h(115) : error C2487: 'end' : member of dll interface class may not be declared with dll interface
NMAKE : fatal error U1077: '"C:\Program Files\Microsoft Visual Studio 9.0\VC\BIN\cl.EXE"' : return code '0x2'
Stop.

D:\projects\STLport-5.1.5\build\lib>

When I checked what could be potentially wrong at _locale.h, I found the following code:

  typedef int category;
#if defined (_STLP_STATIC_CONST_INIT_BUG)
  enum _Category {
#else
  static const category
#endif
    none      = 0x000,
    collate   = 0x010,
    ctype     = 0x020,
    monetary  = 0x040,
    numeric   = 0x100,
    time      = 0x200,
    messages  = 0x400,
    all       = collate | ctype | monetary | numeric | time | messages
#if defined (_STLP_STATIC_CONST_INIT_BUG)
  }
#endif
  ;

Looks like, when multiple static variable are declared in one line, the compiler would report the above error message.  This is actually attributed as a compiler bug.  To get around with this compiler bug, STL has provided a macro namely _STLP_STATIC_CONST_INIT_BUG.

I added the following line to stlport/stl/config/user_config.h to activate the bug work around during the compilation process.

#define _STLP_STATIC_CONST_INIT_BUG    1

Then, I ran the following commands to get the source compiled and installed at lib and bin folders.

nmake /fmsvc.mak ( compilation )
nmake /fmsvc.mak install ( install lib, dll to lib and bin folders )

Great, got STLport compiled perfectly!