9

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.

Community
  • 1
  • 1
Andy Prowl
  • 124,023
  • 23
  • 387
  • 451

1 Answers1

10

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.

Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
  • `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`. I'm OK with that. My question does specify that what I'm concerned with is with binaries that do *not* need to run on WinXP (and therefore are built with the `v120` toolset) *and* link static libraries which are built with the `v120_xp` toolset (that's because those libraries are also linked by other binaries that *do* need to run on XP, and are themselves built with `v120_xp` toolset). So the question stands: can I link a `v120_xp` lib into a `v120` exe/dll? – Andy Prowl Feb 26 '14 at 17:34
  • 3
    I've completely run out of ways to say "it is not a problem". There's something you don't understand about how this works, I have no idea what that might be. – Hans Passant Feb 26 '14 at 17:42
  • 3
    Sorry for sounding thick, and for not knowing some of the things you mention, but if it's straightforward and not a problem I'd just expect you'd quote the only sentence in my question that contains a question mark and write a "Yes, it is super-safe." - possibly in bold font. Then you can go on explaining that by `The only setting that really matters is the linker's /subsystem option [...] and using v120_xp changes this setting` you actually mean "you won't have troubles". That was not straightforward to me. Might be my fault. Thank you for your time and explanation anyway, answer accepted. – Andy Prowl Feb 26 '14 at 17:50
  • The key reason to use the ``v14x_xp`` toolset is to have the Windows 7.1A SDK in the include/lib paths. It doesn't use a special compiler, just the last Windows SDK that supports targeting Windows XP. The Windows 8.0 SDK or later does not support targeting Windows XP. You can get some parts of the headers to work of course, but you can easily end up with an API that isn't actually supported on XP. One final note, the VS 2019 (16.7) is the last version of the Visual C++ CRT that supports Windows XP. – Chuck Walbourn Dec 10 '21 at 04:32