VS2012 compatibility with VS2019 - c++

So, I know that Microsoft enhanced their toolsets such that there is compatibility between applications and libraries built with VS2015, VS2017 and VS2019.
However, I thought that this combination would fail:
C++ application (.exe) built with the toolset from VS2012 (VC11), linking at runtime with
shared library (.dll) containing C++ built with the toolset from VS2019
However, we have seen that this combination "seems" to work.
I am expecting that combination to fail, but cannot explain its success.
Anyone have any ideas on this?

The 'binary compatibility' covered on Microsoft Docs between VS 2015 Update 3, VS 2017, and VS 2019 is specifically around the Standard C++ Library and static library linkage. Historically different generations of toolsets would fail to link or would crash at runtime. To avoid the crash, VS added these symbols so you'd get an error at link time instead:
error LNK2038: mismatch detected for '_MSC_VER': value '1600' doesn't match value '1700' in CppFile1.obj
VS 2015 Update 3, VS 2017, and VS 2019 all use '1900' as the link stamp because they are designed and tested to work when mixed. Of course, it's important to note that the final link is expected to be against the newer CRT libs and linker (i.e. it's forward compatibility only). The link stamp is only pulled in when using C++ headers, not C headers or Win32 system headers.
For example, if you had a C++ library that had inline functions that worked on a std::vector in the class implementation, and the rest of the class was hosted in a DLL, historically this would fail if you built with different toolsets because the implementation of std::vector would use different binary layouts, etc. This was the key value of having this 'binary compatibility' policy between toolsets so it would be easier to use the newest toolset and keep the majority of your existing 3rd party libraries and tools.
C ABIs via import libraries has always worked across compiler versions. That is in large part why Win32 APIs and COM APIs are hosted in DLLs and use C ABIs. Otherwise, every release of the compiler toolset would require a new set of OS libraries. In theory you could successfully link a program with VS 2019 using the libraries shipped in one of the ancient Platform SDKs.
So it really depends on exactly what your exe is using. If it's just using C APIs, extern "C" linkage, and/or Win32 APIs it would work pretty much no matter what combination you used.
TL;DR: Dynamic Link Libraries that use C ABIs work across toolsets. Static libraries or libraries with C++ ABIs only work across toolsets in specific scenarios.
One more caveat here: Whole Program Optimization / Link-Time Code Generation static libraries are not compatible between toolsets.

Related

Upgrading VS2017 15.2 to 15.3 broke third party libraries

I recently updated my Visual Studio version to the latest (mostly because of an automatic update rather than me willingly doing so). This proceeded to break my compiler when linking in third party libraries that were built using 15.2 instead of the current version of 15.3. The error I'm seeing is:
"Library_Name_here.lib" was created with an older compiler than other objects; rebuild old objects and libraries
I am looking for either ideas for solutions to avoid a re-compile of these libraries, but if one does not exist, I am looking for a way to compile the libraries to be version agnostic to not have to keep recompiling every time that vs updates.
It is not a good idea to mix and match code (object files or static libraries) compiled by different versions of the compiler in the same binary.
To quote MSDN on that:
To avoid run-time errors that are difficult to detect and diagnose, we
recommend that you never statically link to binaries that were
compiled by using different versions of the compiler. Also, when you
upgrade an EXE or DLL project, make sure to upgrade the libraries that
it links to. If you're using CRT (C Runtime) or STL (Standard Template
Library) types, don't pass them between binaries (including DLLs) that
were compiled by using different versions of the compiler. For more
information, see Potential Errors Passing CRT Objects Across DLL
Boundaries.
The solution is therefore to recompile all third-party static libraries with the new compiler.
I also had issues few months ago when i upgraded VS2015 to VS2017 and one of my big project that i was running on visual studio 2015 stopped working. That project had several class libraries and external DLLs added.
So what I did was, Uninstalled the upgraded version of visual studio 2017 and re-installed the complete visual studio 2017 from MSDN website (selecting the default selection of features). And then i loaded my Project in VS2017 fresh copy and added the reference of all external libraries and it worked.
I suggest you to try the same
This is a shot in the dark, based on this other SO answer: Error C1047: Object file created with an older compiler than other objects
Recompile the other library without link time code generation enabled (/GL and /LTCG). With it enabled the library expects the linker to do most of the compiling, and you cannot expect one version of the compiler to finish the compiling another version started.
Do not disable it in your active project, as it improves performance significantly. Just in the library.
Major compiler versions may still require rebuilding the 3rd party library, but not minor.
You can do this from within VS2017. It allows you to use tool sets going all the way back to VS2008
See this for details!
https://blogs.msdn.microsoft.com/vcblog/2016/02/24/stuck-on-an-older-toolset-version-move-to-visual-studio-2015-without-upgrading-your-toolset/
Hope that helps!

Runtime compatibility for library packaging

I want to package a library as a NuGet native package. This question is not specific to a way in which the packaged lib/dll/pdb/includes are distributed; but to be specific, I am looking at CoApp scripts (I wish there was something better I could link to), and I got an impression that there are too many different build targets, obtained combinatorially. I am trying to come up with a more or less minimal set of targets that is usable by applications that depend on the package. There are the following mostly orthogonal axes for build targets:
32 bit vs 64 bit. Obviously, this is legit.
Dynamic vs static builds. This is also sensible.
Debug vs. Release build. This also makes perfect sense, as debug builds reference the debug runtime (libcmtd.lib or msvcdrtd.lib) and the release builds reference the static runtime (libcmtd.lib or msvcdrtd.lib). Makes sense to include these to avoid a default library conflict.
The above are unquestionably good axes. The next one is questionable, although present in many examples:
_cdecl vs _stdcall vs __fastcall vs __thiscall. I think this makes little sense. The calling conventions would be supported for this particular library regardless of other linked libraries. Besides, variable arguments are for _cdecl only in Win32, and also 64 bit calling conventions are different anyway. My understanding is that anything I select will do, as long as header files declare a calling conventions compatible with the platform. Microsoft runtime libraries are not supplied for different calling conventions in any case.
And the next one I am not sure how to handle. Again, the examples declare
libraries build by different toolsets, which come with different Visual Studio versions: from v100 (v10.0, VS 2010) to vs140 (v14.0, VS 2015). My main question is, how compatible are the runtime libraries across different Visual C++ libraries? A problem here is we are using also other toolsets (Intel C++ is an example), and these usually have no corresponding packaging cases in CoApp, while being compatible with Microsoft runtimes.
I want to avoid packaging for a particular toolset. How possible is that, provided the code compiles with the oldest vesrion and also not using any newer runtime functions (e. g., v110 being the lowest supported version)? I am worried about two main things here (sorry, another numbered list starts here):
If I compile a static library with VS 2012 (provided bithood, staticity and debugness match), will I be able to link against it in VS2013 (its libcmt[d].lib)?
Under same conditions, will I be able to link against it in VS2010?
Same two questions, but speaking of a shared, DLL runtime?
Same questions, but taking into account runtime library defined exceptions that might be thrown by the library: will e. g. std exceptions be compatible up and down the version chain of the compilers, provided I compile the library with RTTI enabled?
More generally, is there a runtime compatibility matrix provided by Microsoft?
And if any other numbered list points, I'd like to hear that too.

Library ABI compatibility between versions of Visual Studio

I have two scenarios. Suppose I have 3 shared libraries that export C++ symbols, each built with VS7.1, VS8, and VS9. I compile all 3 in VS9. For some reason, this works. I do not need to recompile the first 2 libraries in VS9 for VS9 linker to successfully find the symbols and link against them.
Now, if I have a library that only exports symbols using C syntax (extern "C"), is this the same? I've heard people say that the ABI for C is standardized, so there is somewhat of a guarantee that you can use a C library compiled in Visual Studio 8 in all versions of Visual Studio.
Basically, the combination of all of these things is confusing. I'm not sure of what guarantees I have between linking against both C++ and C based shared libraries (using their corresponding import libraries) between different versions of Visual Studio. I'd like to hear the general consensus on both forward/backward compatibility of both C AND C++ import or static libraries on any other version of Visual Studio.
The reason this has come up for me is because there are closed-source libraries I'm using that were compiled in Visual Studio .NET 2003 (VS7.1). My team thinks that this locks us to the VS 7.1 compiler, however I've gone out and tested these libraries in both VS8 and VS9, even VS2010 and they link just fine. However, I'm not sure of the inherent danger in this. Note that the library in question has a C variant and a C++ variant. Basically, the C variant is standard-C exports, and the C++ library is an abstraction over the C library and exports classes.
The issue may be not only in ABI differences (calling conventions, etc.) between these VS versions, but also in removed/changed symbols in system DLL libraries. See this table for the detailed comparison of system DLL libraries between VS8 (2005, Windows SDK 5.0) and VS9 (2008, Windows SDK 6.0).
See also compatibility matrix for Windows SDKs.
extern "C" exported symbols are different from C++ symbols. C++ has name mangling (see http://en.wikipedia.org/wiki/Name_mangling).
The mangling of C++ symbols may vary from compiler version to compiler version, so in your VS7/8/9 setup, the same C++ method name may be mangled to different names.
Basically, your team seems to be right - you will be locked in the same major version of the compiler that was used to compile your library.

C++ Dynamic Library Compiling/Linking

I know that if I link my c++ program to a dynamic library (DLL) that was built with a different version of Visual Studio, it won't work because of the binary compatibility issue.
(I have experienced this with Boost library and VS 2005 and 2008)
But my question is: is this true for all versions of MSVS? Does this apply to static libraries(LIB) as well? Is this an issue with GCC & Linux as well? and finally how about linking in VS to a DLL built with MinGW?
By the way aside from cross-platform or cross-compiler, why can't two version of the same compiler(VS) be compatibile?
Hi. I know that if I link my c++ program to a dynamic library (DLL) that was built with a different version of Visual Studio, it won't work because of the binary compatibility issue. (I have experienced this with Boost library and VS 2005 and 2008)
I do not remember ever seeing MS changing the ABI, so technically different versions of the compiler will produce the same output (given the same flags (see below)).
Therefore I don't think this is not incompatibilities in Dev Studio but changes in Boost.
Different versions of boost are not backwards compatible (in binary, source they are backward compatible).
But my question is: is this true for all versions of MSVS?
I don't believe there is a problem. Now if you use different flags you can make the object files incompatible. This is why debug/release binaries are built into separate directories and linked against different versions of the standard run-time.
Does this apply to static libraries(LIB) as well?
You must link against the correct static library. But once the static library is in your code it is stuck there all resolved names will not be re-resolved at a later date.
Is this an issue with GCC & Linux as well?
Yes. GCC has broken backwards compatability in the ABI a couple of times (several on purpose (some by mistake)). This is not a real issue as on Linux code is usually distributed as source and you compile it on your platform and it will work.
and finally how about linking in VS to a DLL built with MinGW?
Sorry I don't know.
By the way aside from cross-platform or cross-compiler, why can't two version of the same compiler(VS) be compatibile?
Well fully optimized code objects may be compressed more thus alignment is different. Other compiler flags may affect the way code is generated that is incompatible with other binary objects (changing the way functions are called (all parameters on the stack or some parameters in registers)). Technically only objects compiled with exactly the same flags should be linked together (technically it is a bit looser than that as a lot of flags don't affect the binary compatibility).
Note some libraries are released with multiple versions of the same library that are compiled in different ways. You usually distinguish the library by the extension on the end. At my last job we used the following convention.
libASR.dll // A Sincgle threaded Relase version lib
libASD.dll // A Single threaded Debug version
libAMR.dll // A Multi threaded Release version
libAMD.dll // A Multi threaded Debug version
If properly built, DLLs should be programming-language and version neutral. You can link to DLLs built with VB, C, C++, etc.
You can use dependency walker to examine the exported functions in the dll.
To answer part of your question, GCC/Linux does not have this problem. At least, not as often. libstdc++ and glibc are the standard C++/C libraries on GNU systems, and the authors of those libraries go to efforts to avoid breaking compatibility. glibc is pretty much always backward compatible, but libstdc++ has broken ABI several times in the past and probably will again in the future.
It is very difficult to write stable ABIs in C++ compared to C, because the automatic features in C++ take away some of the control you need to maintain an ABI. Especially once you get into templates and inline functions, where some of the code gets embedded in your application rather than staying contained in the shared library. That means that the object's structure can't ever change without requiring a recompilation of the application.
In practice, it isn't a huge deal on Windows. It would be fantastic if Microsoft just made the MSI installer know how to grab Microsoft-provided DLLs from Windows Update when an app is installed that needs them, but simply adding the redistributable to an InnoSetup-generated installer works well enough.

Are C++ libs created with different versions of Visual Studio compatible with each other?

I am creating a open-source C++ library using Visual Studio 2005. I would like to provide prebuilt libs along with the source code. Are these libs, built with VS2005, also going to work with newer versions of Visual Studio (esp VS Express Edition 2008)? Or do I need to provide separate libs per VS version?
Not normally, no. Libraries built with the VS tools are linked into the 'Microsoft C Runtime' (called MSVCRT followed by a version number) which provides C and C++ standard library functions, and if you attempt to run a program that requires two different versions of this runtime then errors will occur.
On top of this, different compiler versions churn out different compiled code and the code from one compiler version frequently isn't compatible with another apart from in the most trivial cases (and if they churned out the same code then there would be no point having different versions :))
If you are distributing static libraries, you may be able to distribute version-independent libraries, depending on exactly what you are doing. If you are only making calls to the OS, then you may be OK. C RTL functions, maybe. But if you use any C++ Standard Library functions, classes, or templates, then probably not.
If distributing DLLs, you will need separate libraries for each VS version. Sometimes you even need separate libraries for various service-pack levels. And as mentioned by VolkerK, users of your library will have to use compatible compiler and linker settings. And even if you do everything right, users may need to link with other libraries that are somehow incompatible with yours.
Due to these issues, instead of spending time trying to build all these libraries for your users, I'd spend the time making them as easy to build as possible, so that users can can build them on their own with minimal fuss.
Generally it's not possible to link against libraries built with different compilers, different versions of the same compiler, and even different settings of the same compiler version and get a working application. (Although it might work for specific subsets of the language and std library.) There is no standard binary interface for C++ - not even one for some common platform as there are in C.
To achieve that, you either need to wrap your library in a C API or you will have to ship a binary for every compiler, compiler version, and compiler setting you want to support.
If your library project is a static library, then, you'll have to supply a build for every Visual Studio version that you want your users to be in. In the example you gave, that equates to providing both a VS2005 and a VS2008 library.
If your library project is a dynamic library, then, you evade the problems somewhat, but, it means that users will need to make sure that they use the 'Microsoft C Runtime' that's compatible with your build environment. You can eliminate that criteria should you statically link the 'Microsoft C Runtime' into your dynamic library.