Wednesday, April 28, 2010

Static Library Dependencies in Visual Studio 2010

I've been porting my Visual Studio 2008 C++ application to Visual Studio 2010. One rough spot I've hit is the change in how static library dependencies works. In VS2005 and VS2008, we completely gave up on automated static library dependencies because they only worked in the IDE, not from automated builds with VCBUILD. VS2010 was supposed to fix this problem. (Note that MSBUILD replaces VCBUILD for command line builds in VS2010.)

The problem manifested itself during Batch Build with errors indicating that Debug libraries were being linked into Release builds. For example, these errors happen if you are using STL:

Core.lib(HttpHelpers.obj) : error LNK2038: mismatch detected for '_ITERATOR_DEBUG_LEVEL': value '2' doesn't match value '0' in Activation.obj

MSVCRTD.lib(MSVCR100D.dll) : error LNK2005: _strcspn already defined in libcmt.lib(strcspn.obj)


I've also seen these errors for vanilla MFC projects:

msvcrtd.lib(ti_inst.obj) : error LNK2005: "private: __thiscall type_info::type_info(class type_info const &)" (??0type_info@@AAE@ABV0@@Z) already defined in libcmt.lib(typinfo.obj)

msvcrtd.lib(ti_inst.obj) : error LNK2005: "private: class type_info & __thiscall type_info::operator=(class type_info const &)" (??4type_info@@AAEAAV0@ABV0@@Z) already defined in libcmt.lib(typinfo.obj)

Visual Studio 2010 has multiple ways of specifying dependencies.  The actual effect of each setting and settings' interdependence does not appear to be officially documented, although there is some information at http://msdnrss.thecoderblogs.com/2010/02/16/project-settings-changes-with-vs2010/ and at http://blogs.msdn.com/vcblog/archive/2010/03/02/visual-studio-2010-c-project-upgrade-guide.aspx.

The first way of specifying dependencies continues from previous versions of Visual Studio in Project | Project Dependencies. However, unlike earlier versions of Visual Studio, this only affects project build order, not dependency library linking. Also, this only affects project build order in the IDE. It does not affect project build order in MSBUILD. Therefore, you need to configure that page, but it's useless for command line builds. Changes on this page are reflected in the .sln file.

The real action is now on the Framework and References tab in the project properties. This tab used to be exclusively for .Net dependencies, but now it's been expanded for C++ dependencies. When I looked at this page for my project, it looked like this:



There are a couple of things to notice. First, the Configuration in the top left is grayed out. The Debug/Release settings do not apply to the Framework and References page. Second, you'll notice that the Full Path in the properties on the right points to the Debug build. In other words, the Debug library is always linked, even in the Release build. I've blogged about this problem in the past with .Net libraries, but this is pretty fundamental for C++ libraries.

I first thought that the solution was to set Reference Assembly Output to False. However, after reading the blog of one of the Microsoft Program Managers and following up with him, he said that the Reference Assembly Output option is only for managed libraries and does not do anything for native libraries. He said that the behavior I'm seeing is anamolous and that it shouldn't be happening.

[Update 7/18/2010] I have confirmed that this problem only happens with Batch Build. The problem doesn't happen if you explicitly choose a configuration, nor does the problem happen when running MSBUILD from the command line.

I have opened a bug report on Microsoft Connect. Please vote for it at:
https://connect.microsoft.com/VisualStudio/feedback/details/576146/link-library-dependencies-for-c-does-not-work-with-batch-build

[Update 7/18/2010] Microsoft has reproduced the problem, but has decided not to fix it. If you are reading this, PLEASE let them you that fixing this problem is important to you!

9 comments:

  1. I am also seeing this and would appreciate seeing whatever follow up you receive.

    Jere

    ReplyDelete
  2. Thank you for your post, I could have lost a lot of time without it. Much appreciated.

    ReplyDelete
  3. Unfortunately I have wasted a lot of time trying to figure out what this problem is :( Thanks for your post, it was the first I've found that finally explained that I can't reliably get it to use the release lib when building release with build all. /sigh

    ReplyDelete
  4. If you use Project dependencies, I have found Visual Studio 2010 copies the library being depended upon into the output directory of the binary that depends on it. This is not enough because the output directory is not included in the library path. If you do the extra step of including this output directory [as the $(OutDir) symbol] in your library path, my projects build using Project Dependencies alone.

    James
    Boston, MA

    Of course, I am not doing batch builds yet; but this seemed to alleviate the problem in my native

    ReplyDelete
  5. hello sir i have an application in VC++ when i run it on VS2010 it says the application has failed to start because the application configuration is incorrect.Review the manifest file for possible errors.

    mine application release manifest file is:-






















    and debug intermediate manifest file is:-




















    and debug embed.manifest file is :-





















    from which i can conclude that my program is using VS2008 file dependencies.How an i resolve it????

    ReplyDelete
    Replies
    1. Tarun,

      I'm happy to help you, but I charge consulting fees for diagnosing specific problems like this. If you would like to do that, please click "Email" in my profile to contact me.

      Delete
  6. This was very usefull thanks for this :)

    ReplyDelete
  7. Hi Jim!

    While your post is older, I'm just today struggling with getting some lib dependencies in VS2010 right.

    One easy workaround I can conceive of so far would be to set [Link Library Dependencies] to "False", and then just manually add the static-lib output into the Linker - Input - Add.Dependencies Setting (e.g. "$(TargetDir)\mystatic.lib")

    This way the dependencies (build order) are satisfied, the linker is happy and batch build also seems to work. Have you ever tried this? (I see no mention of this here, in the linked blog nor on the connect bug.)

    cheers,
    Martin

    ReplyDelete
    Replies
    1. Hi Martin,

      You are correct, but when you are managing a non-trivial project (my project has almost 40 different configurations), it becomes a nightmarish job trying to keep all of those library dependencies up to date and synced with the project.

      Remember that each project configuration has Release/Debug and Win32/Win64. Now multiply that times the number of libraries and the number of executables. For anything except a trivial project, it becomes ugly very fast.

      Delete