Archived

This forum has been archived. Please start a new discussion on GitHub.

link error building Ice3.3 app

We are migrating a C++ application from Ice-3.2/VisualStudio2005 to a Ice-3.3/VisualStudio2008. The application has not been changed, and we are running an un-modified Ice-3.3.0 installation.

The application build generates some unusual linker errors. Here are the link errors (complete build log attached to post):

CryptoError.obj : error LNK2005: "public: bool __thiscall IceUtil::Timer::Token::operator<(struct IceUtil::Timer::Token const &)const " (??MToken@Timer@IceUtil@@QBE_NABU012@@Z) already defined in AvEncrypter.obj
CryptoError.obj : error LNK2005: "public: bool __thiscall IceUtil::Timer::Token::operator<(struct IceUtil::Timer::Token const &)const " (??MToken@Timer@IceUtil@@$$FQBE_NABU012@@Z) already defined in AvEncrypter.obj
CryptoError.obj : error LNK2005: "public: __thiscall IceUtil::Timer::Token::Token(class IceUtil::Time const &,class IceUtil::Time const &,class IceUtil::Handle const &)" (??0Token@Timer@IceUtil@@2@@Z) already defined in AvEncrypter.obj
CryptoError.obj : error LNK2005: "public: __thiscall IceUtil::Timer::Token::Token(class IceUtil::Time const &,class IceUtil::Time const &,class IceUtil::Handle const &)" (??0Token@Timer@IceUtil@@2@@Z) already defined in AvEncrypter.obj
HgLtServant.obj : error LNK2005: "public: bool __thiscall IceUtil::Timer::Token::operator<(struct IceUtil::Timer::Token const &)const " (??MToken@Timer@IceUtil@@QBE_NABU012@@Z) already defined in AvEncrypter.obj
HgLtServant.obj : error LNK2005: "public: bool __thiscall IceUtil::Timer::Token::operator<(struct IceUtil::Timer::Token const &)const " (??MToken@Timer@IceUtil@@$$FQBE_NABU012@@Z) already defined in AvEncrypter.obj
HgLtServant.obj : error LNK2005: "public: __thiscall IceUtil::Timer::Token::Token(class IceUtil::Time const &,class IceUtil::Time const &,class IceUtil::Handle const &)" (??0Token@Timer@IceUtil@@2@@Z) already defined in AvEncrypter.obj
HgLtServant.obj : error LNK2005: "public: __thiscall IceUtil::Timer::Token::Token(class IceUtil::Time const &,class IceUtil::Time const &,class IceUtil::Handle const &)" (??0Token@Timer@IceUtil@@2@@Z) already defined in AvEncrypter.obj
HgLtService.obj : error LNK2005: "public: bool __thiscall IceUtil::Timer::Token::operator<(struct IceUtil::Timer::Token const &)const " (??MToken@Timer@IceUtil@@QBE_NABU012@@Z) already defined in AvEncrypter.obj
HgLtService.obj : error LNK2005: "public: bool __thiscall IceUtil::Timer::Token::operator<(struct IceUtil::Timer::Token const &)const " (??MToken@Timer@IceUtil@@$$FQBE_NABU012@@Z) already defined in AvEncrypter.obj
HgLtService.obj : error LNK2005: "public: __thiscall IceUtil::Timer::Token::Token(class IceUtil::Time const &,class IceUtil::Time const &,class IceUtil::Handle const &)" (??0Token@Timer@IceUtil@@2@@Z) already defined in AvEncrypter.obj
HgLtService.obj : error LNK2005: "public: __thiscall IceUtil::Timer::Token::Token(class IceUtil::Time const &,class IceUtil::Time const &,class IceUtil::Handle const &)" (??0Token@Timer@IceUtil@@2@@Z) already defined in AvEncrypter.obj
Logging.obj : error LNK2005: "public: bool __thiscall IceUtil::Timer::Token::operator<(struct IceUtil::Timer::Token const &)const " (??MToken@Timer@IceUtil@@QBE_NABU012@@Z) already defined in AvEncrypter.obj
Logging.obj : error LNK2005: "public: bool __thiscall IceUtil::Timer::Token::operator<(struct IceUtil::Timer::Token const &)const " (??MToken@Timer@IceUtil@@$$FQBE_NABU012@@Z) already defined in AvEncrypter.obj
Logging.obj : error LNK2005: "public: __thiscall IceUtil::Timer::Token::Token(class IceUtil::Time const &,class IceUtil::Time const &,class IceUtil::Handle const &)" (??0Token@Timer@IceUtil@@2@@Z) already defined in AvEncrypter.obj
Logging.obj : error LNK2005: "public: __thiscall IceUtil::Timer::Token::Token(class IceUtil::Time const &,class IceUtil::Time const &,class IceUtil::Handle const &)" (??0Token@Timer@IceUtil@@2@@Z) already defined in AvEncrypter.obj
..\current\deliverables\EncServices.exe : fatal error LNK1169: one or more multiply defined symbols found




Here is the linker command-line:
/OUT:"..\current\deliverables\EncServices.exe" /INCREMENTAL:NO /NOLOGO /LIBPATH:"C:\Ice-3.3.0-VC90\lib" /LIBPATH:"..\..\..\external_dependencies\uclmm\current\deliverables\lib" /LIBPATH:"..\..\..\external_dependencies\rock\current\deliverables\lib" /LIBPATH:"..\..\..\ice_definitions\current\deliverables" /LIBPATH:"C:\Program Files\Intel\IPP\5.3.3.082\ia32\lib" /MANIFEST /MANIFESTFILE:"Release\EncServices.exe.intermediate.manifest" /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /DEBUG /PDB:"c:\trees\refactor\halo\encryption\HgLtServiceCPP\current\deliverables\EncServices.pdb" /SUBSYSTEM:CONSOLE /OPT:REF /OPT:ICF /LTCG /FIXED:No /MACHINE:X86 /ERRORREPORT:PROMPT ice.lib iceutil.lib ippcpmerged.lib HaloICE2CPPStaticLib.lib _Rock.lib _uclmm.lib ippcorel.lib WS2_32.Lib winmm.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



The HaloICE2CPPStaticLib.lib is the result of the compilation of the sliceToCpp-generated files. The ippcmerged.lib, _Rock.lib, and _uclmm.lib, ippcorel.lib have to do with encryption and RTP support - they are non-ice-related. The winmm.lib provides support for modifying the windows clock interrupt frequency. The rest are libraries which VS adds to the mix.

None of the code in our application makes any explicit reference to the duplicate symbols - i.e. IceUtil::Timer.

I've spent a great deal of time tracking down and excluding the 'bone headed' build errors, including tracking down the advice MSDN gives on the subject:
Linker Tools Error LNK2005 (C++)

I am assuming that these symbols are exported by iceutil.lib, but I can't find what looks like a match between the output of LibDump (George Poulose's Home Page) on iceutil.lib and the linker error output, but I'm no C++ guru and may just be thrown off by the name mangling.

What's even more strange, is if I remove the ice.lib and iceutil.lib from the linker input list, the errors are still present (which makes no sense), only now they are joined by a bunch more LNK2001 unresolved symbol errors (which makes sense).

Any ideas?

Thanks

Dirk

Comments

  • bernard
    bernard Jupiter, FL
    Hi Dirk,

    Could you also copy & paste the flags you used to build AvEncrypter.obj, CryptoError.obj etc?

    Thanks,
    Bernard
  • Certainly.
    Thanks for the response.

    /Oi /Ot /GL /I "C:\Ice-3.3.0-VC90\include" /I "C:\Program Files\Intel\IPP\5.3.3.082\ia32\include" /I "..\..\..\ice_definitions\current\deliverables\include" /I "..\..\..\external_dependencies\uclmm\current\deliverables\include" /I "..\..\..\external_dependencies\rock\current\deliverables\include" /I "..\..\..\external_dependencies\log4net\current\deliverables" /D "WIN32" /D "_LIB" /D "_WIN32_WINNT=0x0400" /D "USE_IPP" /D "_MBCS" /FD /EHa /MD /Fo"Release\\" /Fd"Release\vc90.pdb" /W3 /nologo /c /Zi /clr /TP /errorReport:prompt /FU "c:\trees\refactor\halo\external_dependencies\log4net\current\deliverables\log4net.dll" /FU "c:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\System.XML.dll" /FU "c:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\System.dll"
  • Bernard-
    In case it helps, the compile line for HaloICE2CPPStaticLib.lib is as follows:

    /Od /I "." /I "C:\Ice-3.3.0-VC90\include" /I "..\..\current\generatedCPP\\" /I "..\..\current\generatedCPP\Administration" /I "..\..\current\generatedCPP\Calibration" /I "..\..\current\generatedCPP\Device" /I "..\..\current\generatedCPP\Messaging" /I "..\..\current\generatedCPP\Node" /I "..\..\current\generatedCPP\PubSub" /I "..\..\current\generatedCPP\SWAV" /I "..\..\current\generatedCPP\UI" /I "..\..\current\generatedCPP\UI\UIMessaging" /I "..\..\current\generatedCPP\UI\Directory" /I "..\..\current\generatedCPP\UI\Localization" /I "..\..\current\generatedCPP\UI\Topology" /D "WIN32" /D "NDEBUG" /D "_LIB" /D "_VC80_UPGRADE=0x0710" /D "_MBCS" /FD /EHsc /RTC1 /MD /Fo"../../current/tmp_CPP/Release\\" /Fd"../../current/tmp_CPP/Release\vc90.pdb" /W3 /nologo /c /Wp64 /Z7 /TP /errorReport:prompt

    The command-line for the Librarian is as follows:
    /OUT:"..\..\current\deliverables\HaloICECPPStaticLib.lib" /NOLOGO /NODEFAULTLIB
  • bernard
    bernard Jupiter, FL
    Hi Dirk,

    One problem is "/clr", i.e. produce managed code. Ice for C++ is un-managed.

    Can you rebuild without /clr?

    Best regards,
    Bernard
  • Bernard-
    Unfortunately, we have written some logging functionality which is managed C++ - it is using log4net and some foundation class libraries. The logging functionality is not fundamental to the application, so if we can't build a managed-unmanaged hybrid, then this logging functionality will have to be re-written. This is obviously not optimal. I imagine that an unmanaged C++ executable can link (either statically or dynamically) a CLR-based library. Thus we could break the logging functionality out into a different application (with CLR support), and have our ice C++-based library build without CLR support.

    So I see our options as follows (in order of desirability). If you could comment on the feasibility of each (again, I am no C++ guru), I would appreciate it.
    1. some compile flag which allows the ice C++ elements to build in a managed-unmanaged hybrid (OK - unrealistic, but I gotta mention this option)
    2. break out the managed elements into a separate application, and link to them from the unmanaged C++ elements
    3. re-write the logging functionality (OK - requires no comment on feasibility)

    Thanks

    Dirk
  • bernard
    bernard Jupiter, FL
    Hi Dirk,

    Unfortunately I don't know anything about mixing managed and un-managed code in the same program.

    Another option (depending on the complexity of this program) could be to switch to managed C++ and Ice for .NET.
    Although we do not officially support "managed C++" with Ice for .NET, I don't anticipate any issue. You would however need to use the code generated by slice2cs (i.e. C# code) from your managed C++ application.

    Best regards,
    Bernard
  • matthew
    matthew NL, Canada
    Dirk, the following article looks promising. Intro to Managed C++, Part 2: Mixing Managed and Unmanaged Code | O'Reilly Media

    If you look at the section on the second page entitled "Using Managed Types from Unmanaged Code", it looks like you should be able to use the managed log4net types directly from unmanaged C++ code (assuming you add the right magic).
  • Bernard-
    I replaced our logging code with calls to the Ice::Logger, and removed all references to the foundation class libraries, and changed the project configuration to not support CLR. I still get the same error. Here is the new compile command-line:

    /Oi /Ot /GL /I "C:\Ice-3.3.0-VC90\include" /I "C:\Program Files\Intel\IPP\5.3.3.082\ia32\include" /I "..\..\..\ice_definitions\current\deliverables\include" /I "..\..\..\external_dependencies\uclmm\current\deliverables\include" /I "..\..\..\external_dependencies\rock\current\deliverables\include" /D "WIN32" /D "_LIB" /D "_WIN32_WINNT=0x0400" /D "USE_IPP" /D "_MBCS" /FD /EHa /MD /Fo"Release\\" /Fd"Release\vc90.pdb" /W3 /nologo /c /Zi /TP /errorReport:prompt


    Here is the build log output:



    Creating temporary file "c:\trees\refactor\halo\encryption\HgLtServiceCPP\src\Release\RSP00000930963368.rsp" with contents
    [
    /Oi /Ot /GL /I "C:\Ice-3.3.0-VC90\include" /I "C:\Program Files\Intel\IPP\5.3.3.082\ia32\include" /I "..\..\..\ice_definitions\current\deliverables\include" /I "..\..\..\external_dependencies\uclmm\current\deliverables\include" /I "..\..\..\external_dependencies\rock\current\deliverables\include" /D "WIN32" /D "_LIB" /D "_WIN32_WINNT=0x0400" /D "USE_IPP" /D "_MBCS" /FD /EHa /MD /Fo"Release\\" /Fd"Release\vc90.pdb" /W3 /c /Zi /TP .\Logging.cpp

    .\HgLtService.cpp

    .\HgLtServant.cpp

    .\CryptoError.cpp

    .\AvEncrypter.cpp
    ]
    Creating command line "cl.exe @c:\trees\refactor\halo\encryption\HgLtServiceCPP\src\Release\RSP00000930963368.rsp /nologo /errorReport:prompt"
    Creating temporary file "c:\trees\refactor\halo\encryption\HgLtServiceCPP\src\Release\RSP00000A30963368.rsp" with contents
    [
    /OUT:"..\current\deliverables\EncServices.exe" /INCREMENTAL:NO /LIBPATH:"C:\Ice-3.3.0-VC90\lib" /LIBPATH:"..\..\..\external_dependencies\uclmm\current\deliverables\lib" /LIBPATH:"..\..\..\external_dependencies\rock\current\deliverables\lib" /LIBPATH:"..\..\..\ice_definitions\current\deliverables" /LIBPATH:"C:\Program Files\Intel\IPP\5.3.3.082\ia32\lib" /MANIFEST /MANIFESTFILE:"Release\EncServices.exe.intermediate.manifest" /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /DEBUG /PDB:"c:\trees\refactor\halo\encryption\HgLtServiceCPP\current\deliverables\EncServices.pdb" /SUBSYSTEM:CONSOLE /OPT:REF /OPT:ICF /LTCG /FIXED:No /MACHINE:X86

    ice.lib iceutil.lib ippcpmerged.lib HaloICE2CPPStaticLib.lib _Rock.lib _uclmm.lib ippcorel.lib WS2_32.Lib winmm.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

    ".\Release\AvEncrypter.obj"

    ".\Release\CryptoError.obj"

    ".\Release\HgLtServant.obj"

    ".\Release\HgLtService.obj"

    ".\Release\Logging.obj"
    ]
    Creating command line "link.exe @c:\trees\refactor\halo\encryption\HgLtServiceCPP\src\Release\RSP00000A30963368.rsp /NOLOGO /ERRORREPORT:PROMPT"

    Compiling...
    Logging.cpp
    HgLtService.cpp
    HgLtServant.cpp
    CryptoError.cpp
    AvEncrypter.cpp
    .\AvEncrypter.cpp(327) : warning C4244: 'argument' : conversion from 'int64' to 'uint32', possible loss of data
    .\AvEncrypter.cpp(343) : warning C4244: 'argument' : conversion from 'int64' to 'uint32', possible loss of data
    .\AvEncrypter.cpp(353) : warning C4244: 'argument' : conversion from 'int64' to 'uint32', possible loss of data
    .\AvEncrypter.cpp(459) : warning C4244: 'argument' : conversion from 'uint64' to 'uint32_t', possible loss of data
    .\AvEncrypter.cpp(274) : warning C4101: 'rtpPacketSpace' : unreferenced local variable
    .\AvEncrypter.cpp(471) : warning C4101: 'e' : unreferenced local variable
    .\AvEncrypter.cpp(576) : warning C4018: '<' : signed/unsigned mismatch
    .\AvEncrypter.cpp(580) : warning C4018: '>' : signed/unsigned mismatch
    Linking...
    CryptoError.obj : error LNK2005: "public: bool __thiscall IceUtil::Timer::Token::operator<(struct IceUtil::Timer::Token const &)const " (??MToken@Timer@IceUtil@@QBE_NABU012@@Z) already defined in AvEncrypter.obj
    CryptoError.obj : error LNK2005: "public: __thiscall IceUtil::Timer::Token::Token(class IceUtil::Time const &,class IceUtil::Time const &,class IceUtil::Handle const &)" (??0Token@Timer@IceUtil@@2@@Z) already defined in AvEncrypter.obj
    HgLtServant.obj : error LNK2005: "public: bool __thiscall IceUtil::Timer::Token::operator<(struct IceUtil::Timer::Token const &)const " (??MToken@Timer@IceUtil@@QBE_NABU012@@Z) already defined in AvEncrypter.obj
    HgLtServant.obj : error LNK2005: "public: __thiscall IceUtil::Timer::Token::Token(class IceUtil::Time const &,class IceUtil::Time const &,class IceUtil::Handle const &)" (??0Token@Timer@IceUtil@@2@@Z) already defined in AvEncrypter.obj
    HgLtService.obj : error LNK2005: "public: bool __thiscall IceUtil::Timer::Token::operator<(struct IceUtil::Timer::Token const &)const " (??MToken@Timer@IceUtil@@QBE_NABU012@@Z) already defined in AvEncrypter.obj
    HgLtService.obj : error LNK2005: "public: __thiscall IceUtil::Timer::Token::Token(class IceUtil::Time const &,class IceUtil::Time const &,class IceUtil::Handle const &)" (??0Token@Timer@IceUtil@@2@@Z) already defined in AvEncrypter.obj
    Logging.obj : error LNK2005: "public: bool __thiscall IceUtil::Timer::Token::operator<(struct IceUtil::Timer::Token const &)const " (??MToken@Timer@IceUtil@@QBE_NABU012@@Z) already defined in AvEncrypter.obj
    Logging.obj : error LNK2005: "public: __thiscall IceUtil::Timer::Token::Token(class IceUtil::Time const &,class IceUtil::Time const &,class IceUtil::Handle const &)" (??0Token@Timer@IceUtil@@2@@Z) already defined in AvEncrypter.obj
    ..\current\deliverables\EncServices.exe : fatal error LNK1169: one or more multiply defined symbols found
  • bernard
    bernard Jupiter, FL
    Hi Dirk,

    Could you confirm the version of your compiler: is it VS2008 or VS2008 with SP1?

    Thanks,
    Bernard
  • Bernard-

    Yes - Visual Studio 2008, SP 1.

    The Help->about has the following info:

    Microsoft Visual Studio 2008
    Version 9.0 30729.1 SP

    The .NET info is:
    Version 3.5 SP1

    The Visual C++ is:
    Microsoft Visual C++ 2008 91605-270-1158913-60900

    Dirk
  • bernard
    bernard Jupiter, FL
    Hi Dirk,

    I am unable to reproduce this problem (same compiler, same flags).

    Clearly, it's a problem with these two functions (the Token constructor and operator<), which should be inlined but are not.

    Could you try to edit IceUtil/Timer.h, and add after the #includes:
    #ifdef inline
    #undef inline
    #endif
    

    I am wondering if you have a macro somewhere that is "removing" the inline keyword.

    Thanks,
    Bernard
  • bernard
    bernard Jupiter, FL
    Apparently some libraries do that: see LNK2005 (VC8) : Visual C++ General : Visual C++ : Microsoft Forums

    Best regards,
    Bernard
  • Bernard-
    Adding the inline #defines fixed it!!!! Fantastic! I would have never figured this out myself. Thank-you!!!

    Looking through our includes, I found a
    #define inline
    in a header file called config_win32.h which is part of a open-source package whose RTP and UDP libraries we use.

    Sure enough, if I remove the '#define inline' in that file, I can remove the #undef lines you had me add to Timer.h, and things continue to build.

    Which leads to my (hopefully) final question:
    Where should the 'permanent' change be made? I am leaning toward the modification in the Timer.h file, as it appears to be purely 'defensive' - i.e. it just turns off a #define which 'screws-up' compilation steps related to the functionality defined in Timer.h. I do not know the semantics of the '#define inline' in the config_win32.h as far as the RTP and UDP libraries are concerned. Again, neither do you, but in your opinion, where should the change be made? Do you anticipate any problems with the #undef statements you asked me to add to Timer.h?

    Thanks again for all of your help!!!!!

    Dirk
  • bernard
    bernard Jupiter, FL
    Hi Dirk,

    Good to hear this was the issue :) .

    This "undef inline" in Timer.h is not a great solution because 'inline' may get removed from other headers as well. Even if you don't get a link error, you could get a performance hit because some functions unexpectedly become non-inline.

    If you use these RTP/UDP headers only in a few .cpp files, my preferred solution would be to organize the #includes in these files with the RTP/UDP includes last, and add a good comment, e.g.
    // .cpp file 
    
    #include <Ice/Ice.h>
    #include <IceUtil/IceUtil.h>
    #include <...>
    
    //
    // These headers define (remove) inline and must be included last
    //
    #include <...>
    
    

    This way you don't need to edit any header. It's also unusual to use the inline keyword in a .cpp file ... even if you do, it would be much easier to work around this issue in a few .cpp files than throughout your code.

    Best regards,
    Bernard
  • Bernard-
    Good point - that's what I ended up doing - just re-arranging my #includes.

    Thanks again for all of your help!

    Dirk