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:
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.
Here's an example: you can link an app compiled using any 2017 toolset (v141, versions 15.0 through 15.9) to a static library compiled using, say, Visual Studio 2019 version 16.2 (v142). You just have to link them by using a version 16.2 or later toolset.
Add a class to the static library To add a class to the static library To create a header file for a new class, right-click to open the shortcut menu for the MathLibrary project in Solution Explorer, and then choose Add > New Item. In the Add New Item dialog box, select Visual C++ > Code.
There are three important restrictions on binary compatibility between the v140, v141, v142, and v143 toolsets and minor numbered version updates: You can mix binaries built by different versions of the v140, v141, v142, and v143 toolsets. However, you must link by using a toolset at least as recent as the most recent binary in your app.
Thank you. The Microsoft C++ (MSVC) compiler toolsets in Visual Studio 2013 and earlier don't guarantee binary compatibility across major versions. You can't link object files, static libraries, dynamic libraries, and executables built by different versions of these toolsets.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With