none
LNK2001, LNK2019, Link static libraries build with VS2005 with VS2008

    Question

  • Hi,

     

    I'm using VS2008 express to build a project developed in VS2005 Express. The project needs to link some static libraries (*.lib) built with VS2005. Everything works in "Release" configuration but fails in "Debug" configuration. Here is the output:

     

    1>Linking...
    1>vul.lib(vul_arg.obj) : error LNK2019: unresolved external symbol "__declspec(dllimport) public: __thiscall std::_Container_base::~_Container_base(void)" (__imp_??1_Container_base@std@@QAE@XZ) referenced in function "public: class vul_arg_base * & __thiscall std::vector<class vul_arg_base *,class std::allocator<class vul_arg_base *> >:Surpriseperator[](unsigned int)" (??A?$vector@PAVvul_arg_base@@V?$allocator@PAVvul_arg_base@@@std@@@std@@QAEAAPAVvul_arg_base@@I@Z)
    1>vil.lib(vil_nitf2_tagged_record.obj) : error LNK2001: unresolved external symbol "__declspec(dllimport) public: __thiscall std::_Container_base::~_Container_base(void)" (__imp_??1_Container_base@std@@QAE@XZ)
    1>vil.lib(vil_nitf2_tagged_record_definition.obj) : error LNK2001: unresolved external symbol "__declspec(dllimport) public: __thiscall std::_Container_base::~_Container_base(void)" (__imp_??1_Container_base@std@@QAE@XZ)
    1>vnl.lib(vnl_vector+double-.obj) : error LNK2001: unresolved external symbol "__declspec(dllimport) public: __thiscall std::_Container_base::~_Container_base(void)" (__imp_??1_Container_base@std@@QAE@XZ)
    1>vnl.lib(vnl_matrix+double-.obj) : error LNK2001: unresolved external symbol "__declspec(dllimport) public: __thiscall std::_Container_base::~_Container_base(void)" (__imp_??1_Container_base@std@@QAE@XZ)
    1>vil.lib(vil_nitf2_typed_field_formatter.obj) : error LNK2001: unresolved external symbol "__declspec(dllimport) public: __thiscall std::_Container_base::~_Container_base(void)" (__imp_??1_Container_base@std@@QAE@XZ)
    1>vil.lib(vil_nitf2_array_field.obj) : error LNK2001: unresolved external symbol "__declspec(dllimport) public: __thiscall std::_Container_base::~_Container_base(void)" (__imp_??1_Container_base@std@@QAE@XZ)
    1>vil.lib(vil_nitf2_field.obj) : error LNK2001: unresolved external symbol "__declspec(dllimport) public: __thiscall std::_Container_base::~_Container_base(void)" (__imp_??1_Container_base@std@@QAE@XZ)
    1>vil.lib(vil_nitf2_compound_field_value.obj) : error LNK2001: unresolved external symbol "__declspec(dllimport) public: __thiscall std::_Container_base::~_Container_base(void)" (__imp_??1_Container_base@std@@QAE@XZ)
    1>vil.lib(vil_nitf2_image_subheader.obj) : error LNK2001: unresolved external symbol "__declspec(dllimport) public: __thiscall std::_Container_base::~_Container_base(void)" (__imp_??1_Container_base@std@@QAE@XZ)
    1>vil.lib(vil_nitf2_field_sequence.obj) : error LNK2001: unresolved external symbol "__declspec(dllimport) public: __thiscall std::_Container_base::~_Container_base(void)" (__imp_??1_Container_base@std@@QAE@XZ)
    1>vil.lib(vil_nitf2_classification.obj) : error LNK2001: unresolved external symbol "__declspec(dllimport) public: __thiscall std::_Container_base::~_Container_base(void)" (__imp_??1_Container_base@std@@QAE@XZ)
    1>vil.lib(vil_nitf2_field_definition.obj) : error LNK2001: unresolved external symbol "__declspec(dllimport) public: __thiscall std::_Container_base::~_Container_base(void)" (__imp_??1_Container_base@std@@QAE@XZ)
    1>vil.lib(vil_tiff_header.obj) : error LNK2001: unresolved external symbol "__declspec(dllimport) public: __thiscall std::_Container_base::~_Container_base(void)" (__imp_??1_Container_base@std@@QAE@XZ)
    1>vil.lib(vil_nitf2_header.obj) : error LNK2001: unresolved external symbol "__declspec(dllimport) public: __thiscall std::_Container_base::~_Container_base(void)" (__imp_??1_Container_base@std@@QAE@XZ)
    1>vil.lib(vil_nitf2_data_mask_table.obj) : error LNK2001: unresolved external symbol "__declspec(dllimport) public: __thiscall std::_Container_base::~_Container_base(void)" (__imp_??1_Container_base@std@@QAE@XZ)
    1>vil.lib(vil_nitf2_des.obj) : error LNK2001: unresolved external symbol "__declspec(dllimport) public: __thiscall std::_Container_base::~_Container_base(void)" (__imp_??1_Container_base@std@@QAE@XZ)
    1>vil.lib(vil_ras.obj) : error LNK2001: unresolved external symbol "__declspec(dllimport) public: __thiscall std::_Container_base::~_Container_base(void)" (__imp_??1_Container_base@std@@QAE@XZ)
    1>vil.lib(vil_nitf2_image.obj) : error LNK2001: unresolved external symbol "__declspec(dllimport) public: __thiscall std::_Container_base::~_Container_base(void)" (__imp_??1_Container_base@std@@QAE@XZ)

     

    I omit most of the error messages for the sake of clarity. Most of them are LNK2001 and LNK2019.  Is there any solutions to this issue? Thanks.

    Wednesday, March 26, 2008 4:21 PM

Answers

  • Mixing object files produced with different toolchains or different compiler options are generally not supported. This is especially true when C++ libraries are involved.

     

    We just do not provide this kind of compatibility guarantees. The best course of action would be to rebuild your static libraries with VC++ 9. If that's not an option you could wrap the .lib in a DLL and consume that from your program. So long as you use binary compatible types at the interface between your program and the DLL you're fine.

     

    -hg

     

     

    Thursday, March 27, 2008 8:08 AM

All replies

  • You will need separate debug versions of your static libraries.
    Wednesday, March 26, 2008 5:24 PM
  • Brian, thank for the reply.

     

    But I have built separate versions for my static libraries, Here's part of the command line (obtained from project properties -> Configuration properties -> Linker -> Command line) for debug configuration:

    /LIBPATH:"C:\Projects\vxl\build-1.6.0-glut\lib\debug"

     

    And here is part of the command line for release configuration:

    /LIBPATH:"C:\Projects\vxl\build-1.6.0-glut\lib\release"

     

    Could you give me further help?

     

    Thursday, March 27, 2008 12:50 AM
  • Well, quite simply the linker can't find the DLL's or the debug configuration doesn't list the lib file correctly. I would approach this by determining the exact DLL which is missing, which I'm sure you can guess simply by viewing the external symbols listed. Confirm that by you have listed the lib file in  the configuration settings. Confirm that by moving the DLL directly into the same directory as the sources linker resolves the symbols. Also confirm that the libpath you specified contains the DLL that it is complaining of.

     

     

    Thursday, March 27, 2008 3:13 AM
  • > Confirm that by you have listed the lib file in  the configuration settings.

    Yes, there's no problem to build my project in VS2005 with the same configuration settings.

     

    > Confirm that by moving the DLL directly into the same directory as the sources linker resolves the symbols. 

    > Also confirm that the libpath you specified contains the DLL that it is complaining of.

    All my libraries are static (*.lib) and no DLLs.

    Thursday, March 27, 2008 7:16 AM
  • Mixing object files produced with different toolchains or different compiler options are generally not supported. This is especially true when C++ libraries are involved.

     

    We just do not provide this kind of compatibility guarantees. The best course of action would be to rebuild your static libraries with VC++ 9. If that's not an option you could wrap the .lib in a DLL and consume that from your program. So long as you use binary compatible types at the interface between your program and the DLL you're fine.

     

    -hg

     

     

    Thursday, March 27, 2008 8:08 AM
  • I'll rebuild the libraries with VC++2008 tonight and see if it works.

    But I am still puzzled why static libraries built with VC++8 cannot be used in VC++9? I use the same nmake file to build the project in both VC++8 and VC++9 so that the compiler and linker options are the same.

    Thursday, March 27, 2008 3:42 PM
  • Well, the headers can (and do) change from one version to another. 

     

    For instance it would be possible (I dont know happened but it is probably something similar) that VC 8 had (conceptually)

     

    class __declspec(dllimport) _ContainerBase { protected: ~_ContainerBase(); };

    template < typename T, typename A > class vector : _ContainerBase { ...};

     

    and VC9 something like
    // _ContainerBase no longer exists

    template < typename T, typename A > class vector : _VectorVal < T, A >{ ...};

     

    Now when the VC8 compiles your code:

     

    vector<int> x;

     

    it will have to instantiate vector's destructor (it is called once x is destroyed, the compiler will generate code to that effect). vector<int>::~vector() will reference _ContainerBase::~ContainerBase().

     

    Now would you link this object file (a static lib is really just an indexed archive of object files) with VC8, you'd get the VC8 version of msvcpt.lib and everyone's happy.

     

    However, when you link with the VC9 linker it will lift its version of msvcpt.lib which no longer has the symbol in question.

     

    You're actually lucky in this case that the linker flags the error. It can also happen that we change the binary layout of STL classes (this happened between VC6 & 7.0 for std::basic_string). In this case some of the code silently assumes a different layout which most certainly cause very hard-to-track-down problems at runtime.

     

    On a related note, also be aware that compiler options (e.g. /MT,/MD) and defines (e.g._STATIC_CPPLIB,_SECURE_SCL,_HAS_ITERATOR_DEBUGGING) can change these things for a single version of the compiler toolchain, too. Therefore, it's usually a good idea to use a consistent set of options with a single compiler toolchain version.

    -hg

    Thursday, March 27, 2008 6:48 PM
  • Holger has correctly pointed you in the right direction. I apologize for my earlier post, which was quite misleading. I should have seen the problem right off the bat.

     

    It is important to note that it is quite possible to create a library (static or dynamic) that is independent of the compiler, but some care and attention needs to be applied. If that is your intention, then it is best to only pass POD (plain-ole-data) types as parameters and return values. If you use STL containers, for example, you must rely on the fact that the compiler on both sides implement the same code. It's also best not to allocate from the heap in the library with expectations that the client will free the memory, since this causes heap algorithm dependencies. Also, you should avoid name mangling as this is also compiler-dependent.

     

    I assume you are past this stage and simply want to get it working, but it is good to keep these points in mind in the future.

     

     

     

    Thursday, March 27, 2008 6:59 PM
  • Just to reinterate that case: there is an important difference between static and dynamic libraries here.

     

    Static libraries are not fully statically linked (what link.exe does effectively). They still have references to other libraries. There can only be one definition of any given named symbol during final static linking (i.e. objs/libs => DLL). So it is not a good idea to mix static libraries from VC6 and VC7 which internally use std:Tongue Tiedtring, even if only PODs are used in the interface.

     

    This is different for DLLs where things are statically linked already. Several versions of std:Tongue Tiedtring functions can exist in several DLLs, which are loaded into the same process. It is perfectly safe to use std:Tongue Tiedtring in the internal implementation of VC 6 & VC 7 DLLs hosted in the same process _but not_ in the interface between the two.

     

    So static libraries are more vulnerable to the kind of problems outlined above.

     

    -hg

     

    Thursday, March 27, 2008 7:21 PM
  • Hi, Holger and Brian,

     

    Thank you very much for your help. I build my static libraries in VC++9 and now the problem is gone. I'll try the DLL way to see if it also works.

    Friday, March 28, 2008 3:58 PM
  • you must rebuild the library on vs 2008: because in vc9,stl xutily file is modified,class _Container_base is re-defined to _Container_base_secure "typedef _Container_base_secure _Container_base;", so the library build with vc8 ,refered to _Container_base::member_func(),but it hasn't exist in fact.class _Container_base in vc9,became an alias! you can compare the file 'xutilty' in vc8 and vc9,all is clear. http://www.enginedev.net
    Wednesday, August 05, 2009 9:23 AM