Andy Prowl
Andy Prowl

Reputation: 126522

Can I link a static library built with the v120_xp toolset into an EXE/DLL built with the v120 toolset in VS2013?

I am working with a large codebase that contains four sets of native C++ VS2013 projects. I'll call these sets A, B, C, and D.

Projects in sets A and B generate C++ static libraries (.lib). Projects in sets C and D generate DLLs and executables.

Projects in set C link only to static libraries in set A, while projects in set D link to static libraries from both set A and set B:

              C (.dll, .exe) ----> A (.lib)
                                   ^
                                   |
                                   |
                                   D (.dll, .exe) -----> B (.lib)

I have the following requirements:

  1. Those DLLs and EXEs that are generated by projects in set C must run on Windows XP as well as on Windows 7;
  2. Those DLLs and EXEs that are generated by projects in set D, on the other hand, do not need to run on Windows XP.

What I would like to do is to build the projects in sets A and C with the v120_xp platform toolset, and those in sets B and D with the v120 platform toolset:

                (WinXP, Win7)
                 C [v120_xp] ----> A [v120_xp]    
                                   ^
                                   |
                                   |
                                   D [v120] -----> B [v120]
                                 (Win7 only)

I believe this should not be a problem for projects in set C, but I'm concerned with projects in set D.

I tried doing the above for a few small projects and it all seems to work correctly, but is this guaranteed to be safe in the general case?


My research:

Point 2) in this question asks pretty much the same thing I'm asking, but for VS2012. It did not receive an answer.

This answer (again, for VS2012) mentions that:

Long story short, mixing modules that were built with a mix of v110 and v110_xp toolsets is not a problem.

This other answer to the same question, on the other hand, says:

Mixing v110_xp executables and v110 libraries is officially unsupported.

Upvotes: 9

Views: 2424

Answers (1)

Hans Passant
Hans Passant

Reputation: 942119

I don't really see how this question covers new territory. Everything that Steve-o quoted that Microsoft Support told him is accurate. His conclusion is not, you can certainly call Microsoft Support about it and ask for help. It is a waste of money, they'll unequivocally tell you that you must select the v120_xp toolset.

It is really rather straight-forward, if you want the executable to run on XP then using the v120_xp toolset is a hard requirement. If you don't then it doesn't matter. The only setting that really matters is the linker's /subsystem option. Starting with VS2012, the toolset sets this so that your executable contains 6.0 as the required subsystem. The Windows generation that started with Vista. And using v120_xp changes this setting, using the legacy value of 4.0. The generation that started with NT 4.0. XP is generation 5.0, it will refuse to run a program that has the subsystem set to 6.0

The value does matter, somewhat, the operating system looks at it and decides which appcompat shims to turn on. With the subsystem set to 4.0 in the header, Windows assumes that you wrote your code without consideration for Aero. Several appcompat shims are dedicated to turning on lies that make your program believe it still runs on the classic user interface. The fat window borders are a significant appcompat problem, the CreateWindowEx() call takes the outer window size but many programs really care about the size of the client area.

What you ought be worried about is having multiple versions of the CRT running inside your process. Rather bad things tend to happen when modules don't use the same version. Like a function in a DLL that returns a standard C++ library class object like std::string. That invokes failure when the client code doesn't use the same allocator as the DLL does, it cannot reliably destroy the object. Or worse, if it uses a legacy version of the C++ library with an std::string object that has a completely different layout. The changes in C++11 in particular make that a common mishap.

That is not something you have to worry about in your case. The v120 and v120_xp toolsets use the exact same CRT version, msvcr120.dll and msvcp120.dll when you build with /MD (as you should). That CRT can run on XP as well as later Windows versions, it dynamically binds to winapi functions that may not be available, using GetProcAddress(). This isn't anything new, previous CRT versions already did this for winapi functions like FlsAlloc(), there's just more of it. Additions relate to support for threading and locale.

Upvotes: 10

Related Questions