Possible solution to making boost::regex link under debug, static runtime library for .NET 2003 (VC7)

Currently, if you try to compile a program that uses boost::regex (either boost versions 1.31 and 1.32) under the debug static runtime library(libboost_regex-vc71-sgd-1_32.lib), you'll get a bunch of multiply defined symbols something like this: LIBCMTD.lib(_wctype.obj) : error LNK2005: _iswlower already defined in c_regex_traits.obj and so on for all of the character type macros: _iswalpha _iswupper _iswlower _iswdigit _iswxdigit _iswspace _iswpunct _iswalnum _iswprint _iswgraph _iswcntrl _iswascii This has been noticed before && stems from the fact that the inline directive is ignored for debug mode, causing those inline functions to exist both in the C runtime library and in the regex lib. I found a note going back to 2002 - http://lists.boost.org/MailArchives/boost-users/msg01398.php - which indicates that this problem is longstanding. Unfortunately, I'd like to be able to use boost::regex, and I'd like to be able to use static runtime libraries. I doubt I'm the only person who'd like be able to do that. Fortunately, the references to those macros/inlines seems to be localized to only one file, libs\regex\src\c_regex_traits.cpp, so I thought I'd try fixing that file. Digging around a bit, I modified libs\regex\src\c_regex_traits.cpp to compile and link correctly for this model. I attached the diffs below; I'm sure that there was a more elegant way, but at least this is a solution that allows the regex library to link under all runtime libraries for VC7. Maybe somebody could boostify the solution and incorporate this into the next release of the boost libraries? Thanks, Rob. --- diff follows 45a46,65
# ifdef BOOST_MSVC // Workaround for .NET2003 (VC7) linkage problem. // This prevents inline functions from existing in both the static debug multithreaded unicode runtime library and in this library, a problem // which causes link errors like: // LIBCMTD.lib(_wctype.obj) : error LNK2005: _iswlower already defined in c_regex_traits.obj
#define iswalpha(_c) ( iswctype(_c,_ALPHA) ) #define iswupper(_c) ( iswctype(_c,_UPPER) ) #define iswlower(_c) ( iswctype(_c,_LOWER) ) #define iswdigit(_c) ( iswctype(_c,_DIGIT) ) #define iswxdigit(_c) ( iswctype(_c,_HEX) ) #define iswspace(_c) ( iswctype(_c,_SPACE) ) #define iswpunct(_c) ( iswctype(_c,_PUNCT) ) #define iswalnum(_c) ( iswctype(_c,_ALPHA|_DIGIT) ) #define iswprint(_c) ( iswctype(_c,_BLANK|_PUNCT|_ALPHA|_DIGIT) ) #define iswgraph(_c) ( iswctype(_c,_PUNCT|_ALPHA|_DIGIT) ) #define iswcntrl(_c) ( iswctype(_c,_CONTROL) ) #define iswascii(_c) ( (unsigned)(_c) < 0x80 ) # endif
520,521c540,545 < lower_case_map[i] = (char)std::tolower(i); < } ---
# ifdef BOOST_MSVC lower_case_map[i] = (char)tolower(i); # else lower_case_map[i] = (char)std::tolower(i); # endif } 915a940,967 # ifdef BOOST_MSVC bool BOOST_REGEX_CALL c_regex_traits<regex_wchar_type>::do_iswclass(regex_wchar_type c, boost::uint_fast32_t f) { BOOST_RE_GUARD_STACK if((c & ~0xFF) == 0) return BOOST_REGEX_MAKE_BOOL(re_detail::wide_unicode_classes[(uchar_type)c] & f); if((f & char_class_alpha) && iswalpha(c)) return true; if((f & char_class_cntrl) && iswcntrl(c)) return true; if((f & char_class_digit) && iswdigit(c)) return true; if((f & char_class_lower) && iswlower(c)) return true; if((f & char_class_punct) && iswpunct(c)) return true; if((f & char_class_space) && iswspace(c)) return true; if((f & char_class_upper) && iswupper(c)) return true; if((f & char_class_xdigit) && iswxdigit(c)) return true; if(f & char_class_unicode) return true; return false; }
#else 940a993 # endif // BOOST_MSVC

Currently, if you try to compile a program that uses boost::regex (either boost versions 1.31 and 1.32) under the debug static runtime library(libboost_regex-vc71-sgd-1_32.lib), you'll get a bunch of multiply defined symbols something like this:
LIBCMTD.lib(_wctype.obj) : error LNK2005: _iswlower already defined in c_regex_traits.obj and so on for all of the character type macros: _iswalpha _iswupper _iswlower _iswdigit _iswxdigit _iswspace _iswpunct _iswalnum _iswprint _iswgraph _iswcntrl _iswascii
This has been noticed before && stems from the fact that the inline directive is ignored for debug mode, causing those inline functions to exist both in the C runtime library and in the regex lib. I found a note going back to 2002 - http://lists.boost.org/MailArchives/boost-users/msg01398.php - which indicates that this problem is longstanding.
I've been trying to reproduce this (again), but can't at present, can you be more specific because linking with the static VC runtime definitely works for me. Are you defining _UNICODE when building the regex lib? If so can you try building the lib without _UNICODE defined and linking to that (defining _UNICODE basically has no effect as far as the regex internals are concerned). John.

"John Maddock" <john@johnmaddock.co.uk> wrote in message news:03ba01c51f23$5ebf5100$81800252@fuji...
Currently, if you try to compile a program that uses boost::regex (either boost versions 1.31 and 1.32) under the debug static runtime library(libboost_regex-vc71-sgd-1_32.lib), you'll get a bunch of multiply defined symbols something like this:
LIBCMTD.lib(_wctype.obj) : error LNK2005: _iswlower already defined in c_regex_traits.obj and so on for all of the character type macros: _iswalpha _iswupper _iswlower _iswdigit _iswxdigit _iswspace _iswpunct _iswalnum _iswprint _iswgraph _iswcntrl _iswascii
This has been noticed before && stems from the fact that the inline directive is ignored for debug mode, causing those inline functions to exist both in the C runtime library and in the regex lib. I found a note going back to 2002 - http://lists.boost.org/MailArchives/boost-users/msg01398.php - which indicates that this problem is longstanding.
I've been trying to reproduce this (again), but can't at present, can you be more specific because linking with the static VC runtime definitely works for me. Are you defining _UNICODE when building the regex lib? If so can you try building the lib without _UNICODE defined and linking to that (defining _UNICODE basically has no effect as far as the regex internals are concerned).
John.
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

"John Maddock" <john@johnmaddock.co.uk> wrote in message news:03ba01c51f23$5ebf5100$81800252@fuji...
Currently, if you try to compile a program that uses boost::regex (either boost versions 1.31 and 1.32) under the debug static runtime library(libboost_regex-vc71-sgd-1_32.lib), you'll get a bunch of multiply defined symbols something like this:
LIBCMTD.lib(_wctype.obj) : error LNK2005: _iswlower already defined in c_regex_traits.obj and so on for all of the character type macros: _iswalpha _iswupper _iswlower _iswdigit _iswxdigit _iswspace _iswpunct _iswalnum _iswprint _iswgraph _iswcntrl _iswascii
This has been noticed before && stems from the fact that the inline directive is ignored for debug mode, causing those inline functions to exist both in the C runtime library and in the regex lib. I found a note going back to 2002 - http://lists.boost.org/MailArchives/boost-users/msg01398.php - which indicates that this problem is longstanding.
I've been trying to reproduce this (again), but can't at present, can you be more specific because linking with the static VC runtime definitely works for me. Are you defining _UNICODE when building the regex lib? If so can you try building the lib without _UNICODE defined and linking to that (defining _UNICODE basically has no effect as far as the regex internals are concerned).
Sure. Lets start by playing "your version, my version". bjam -v gives me: D:\extra\bin>bjam -v Boost.Jam Version 3.1.10. OS=NT. Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc. Copyright 2001 David Turner. Copyright 2001-2004 David Abrahams. Copyright 2002-2004 Rene Rivera. And I've got SP1 of the .NET 2003 compiler, which is actually a significant change despite the minor version number - technically that'd be VC7.1, and it shows up as "Version 7.1.3088" in the "About" box of Visual Studio. Next, how did I build? Well, I'm using boost.jam to build this, as per the installation instructions. Appended below are the instructions that I wrote up when I did it. These are the exact command lines I did, none of which define _UNICODE. They are also pretty much the installation instructions from boost.org. Now, I'm not saying that _UNICODE doesn't get defined, simply that it isn't anything concious that I did. It all boils down to: 1) get a "Visual Studio .NET 2003" command prompt 2) bjam "-sTOOLS=vc-7_1" "-sPYTHON_ROOT=d:\Python23" "-sPYTHON_VERSION=2.3" stage PS. I took a look at my environment variables, and UNICODE isn't defined. Finally, which precise library did I use? Well, that'd be multi-threaded, static, debug. Hope that helps. ============================================================================ ======= Step 1: Downloaded boost_1_32_0 to a workarea [d:\svn\code\thirdpty\boost\boost_1.32.0] corresponding to http://server/code/thirdpty/boost/boost_1.32.0. See http://www.boost.org/more/getting_started.html#Download Step 1.5: Imported the whole tree into Subversion before making any changes or compiling anything: cd d:\svn\code\thirdpty\boost\boost_1.32.0 svn import http://server/code/thirdpty/boost/boost_1.32.0 -m "Initial import from boost.org" Step 2: Downloaded bjam.exe executable (see http://www.boost.org/tools/build/jam_src/index.html) Step 3. Installed Python version 2.3 before building, so that we could get the compiled python support. Step 4 Patched the boost_1_32_0 source to get around the _iswalpha link issue Step 5: in the directory extracted from the archive downloaded in step 1 (making sure that the VC7.1 command line tools are selected (on my box I used a command prompt icon called "Visual Studio .NET 2003 Command Prompt" created by the visual studio instalation process) use bjam to build the libraries D:\boost\boost_1_32_0>bjam "-sTOOLS=vc-7_1" "-sPYTHON_ROOT=d:\Python23" "-sPYTHON_VERSION=2.3" stage
John.
_______________________________________________ Unsubscribe & other changes:

Appended below are the instructions that I wrote up when I did it. These are the exact command lines I did, none of which define _UNICODE. They are also pretty much the installation instructions from boost.org. Now, I'm not saying that _UNICODE doesn't get defined, simply that it isn't anything concious that I did. It all boils down to:
1) get a "Visual Studio .NET 2003" command prompt 2) bjam "-sTOOLS=vc-7_1" "-sPYTHON_ROOT=d:\Python23" "-sPYTHON_VERSION=2.3" stage
PS. I took a look at my environment variables, and UNICODE isn't defined.
Finally, which precise library did I use? Well, that'd be multi-threaded, static, debug.
Hope that helps.
Nope, the strange thing is that's the build-combination that I use all the time, and I still can't reproduce the issue, there must still be some piece of vital information missing somewhere. Can you put together a small VC IDE project that demonstrates the problem (preferably using one of the regex examples or test programs if you can)? Mail it to john *at* johnmaddock.co.uk to avoid cluttering up the list with attachments, Thanks, John.

And I've got SP1 of the .NET 2003 compiler, which is actually a significant change despite the minor version number - technically that'd be VC7.1, and it shows up as "Version 7.1.3088" in the "About" box of Visual Studio.
Build 7.1.3088 of Visual Studio .NET 2003 is RTM ("gold", ie. no service packs). Actually I first time hear about Service Pack 1 for .NET 2003 compiler; maybe you confused it with SP1 for .NET framework 1.1 (which has nothing to do with C++ compiler)? What's the output of cl.exe when called without any arguments? I was only able to find Service Pack 1 for Visual .NET 2002 (ie. Visual C++ 7.0), it's been just published at http://www.microsoft.com/downloads/details.aspx?FamilyId=C41D8159-B42F-4D06-... . BTW: somewhere in the middle of March I'm going to run regression tests against this build of MSVC7.0
PS. I took a look at my environment variables, and UNICODE isn't defined.
I think that John meant preprocesor symbol _UNICODE used by MSVC, not environment variable Regards B. -- Bronek Kozicki brok@rubikon.pl http://b.kozicki.pl/

"Bronek Kozicki" <b.kozicki@gmail.com> wrote in message news:48270273050303090161b4c38e@mail.gmail.com...
And I've got SP1 of the .NET 2003 compiler, which is actually a significant change despite the minor version number - technically that'd be VC7.1, and it shows up as "Version 7.1.3088" in the "About" box of Visual Studio.
Build 7.1.3088 of Visual Studio .NET 2003 is RTM ("gold", ie. no service packs). Actually I first time hear about Service Pack 1 for .NET 2003 compiler; maybe you confused it with SP1 for .NET framework 1.1 (which has nothing to do with C++ compiler)? What's the output of
Sigh, I never really know with Microsoft what I'm getting when I install a SP. How would you know that SP1 for .NET didn't change the compiler version, or patch some random STL header? Anyway, here's the compiler version: K:\comp\db\src>cl --version Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 13.10.3077 for 80x86 Copyright (C) Microsoft Corporation 1984-2002. All rights reserved.
cl.exe when called without any arguments? I was only able to find Service Pack 1 for Visual .NET 2002 (ie. Visual C++ 7.0), it's been just published at
http://www.microsoft.com/downloads/details.aspx?FamilyId=C41D8159-B42F-4D06-...
. BTW: somewhere in the middle of March I'm going to run regression tests against this build of MSVC7.0
PS. I took a look at my environment variables, and UNICODE isn't defined.
I think that John meant preprocesor symbol _UNICODE used by MSVC, not environment variable
Well you've heard of the "CL" environment variable, right? If it's set in the environment, it will effect how CL operates. SET CL=[ [option] ... [file] ...] [/link link-opt ...] I was just fencing off that possibility.
Regards
B.
-- Bronek Kozicki brok@rubikon.pl http://b.kozicki.pl/ _______________________________________________ Unsubscribe & other changes:
participants (3)
-
Bronek Kozicki
-
John Maddock
-
Robert Mathews