Are C++ Libs Created with Different Versions of Visual Studio Compatible with Each Other

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

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.

Are compiled .lib files interchangeable for different versions of Microsoft Visual C++?

The MS COFF format (.lib, .obj, etc) is the same for all VC++ versions and even for other languages.

The problem is that .obj files depend on other .obj (.lib) files.

For C++ code, there is a happy chance that code won't compile with new version of VC++ standard library implementation. For example, an old version of CRT used extern "C++" void internal_foo(int), and newer CRT uses extern "C++" void internal_foo(int, int), so linker will fail with "unresolved external symbol" error.
For C code, there is a chance that code will compile, because for extern "C", symbol names doesn't encode whole signature. But at runtime application will crash after this function will be called.

The same thing can happen if layout of some data structure will change, linker will not detect it.

Library ABI compatibility between versions of Visual Studio

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.

Sample Image

Questions about Binary Compatibility between Visual Studio 2015 and Visual Studio 2017

Since you explicitly call out the

... CRT DLLs ...

I will answer that part:

Backwards Compatibility between the VS2017 CRT and the VS2015 CRT is 100% guaranteed! (Modulo MS Bugs of course.)

How can I say this? The default deployment method for the MSVC CRT is deploying all CRT files to System32, so there is one (1) global set of CRT DLLs that most applications will use. (At least AFAIKT, many many apps use the MS CRT in DLL form, but do not bundle all CRT DLLs in their app directory.)

And with VS 2017 vs. 2015, all CRT DLLs have the same filenames, i.e. msvcp140.dll, vcruntime140.dll, there are no 141 files! (So Bullet Point 6 does not exist.)

So a given Windows system can have at most one global set of CRT140 files, and since no application controls this, newer versions of CRT140 must be backwards compatible to apps built against older versions.


Given that, I would simply not do cases 3 and 5 (with regard to CRT) from your question: Always deploy the newest MS CRT that your components rely upon.

Even found a blog entry wrt. this (2017/03/07):

... The VCRedist is only backward compatible, so you will need to redistribute the latest VCRedist 140 available in VS 2017 with your app. ...


With regard to the bullet point 3 and 4 situation 2015.exe <-> 2017.dllI have created a new question: Is the official binary incompatibility between VS2017 and VS2015 app vs. dll accurate? because this is really weird, IMHO.

Why can some libraries built by older compilers link against modern code, and others cannot?

I will try to answer some integral parts, but be aware this answer could be incomplete. With more information from peers we will maybe be able to construct a full answer!

The simples kind of linking is linking towards a C library. Since there is no concept of classes and overloading function names, the compiler creators are able to create entry points to functions by their pure name. This seems to be pretty much quasi-standardized since, I myself, haven't encountered a pure C library not at least linkable to my projects. You can select this behaviour in C++ code by prepending a function declaration with extern "C". (This also makes it easy to link against a library from C# code) Here is a detailed explanation about extern "C". But as far as I am aware this behaviour is not standardized; it is just so simple - it seems - there is just one sane solution.

Going into C++ we start to encounter function, variable and struct names repeating. Lets just talk about overloaded functions here. For that compiler creators have to come up with some kind of mapping between void a(); void a(int x); void a(char x); ... and their respective library representation. Since this process also is not standardized (see this thread) and this process is far more complex than the 1 to 1 mapping of C, the ABIs of different compilers or even compiler versions can differ in any way.

Now given two compilers (or linkers I couldn't find a resource wich specifies wich one exactly is responsible for the mangling but since this process is not standardized it could be also outsourced to cthulhu) with different name mangling schemes, create following function entry points (simplified):

compiler1
_a_
_a_int_
_a_char_

compiler2
_a_NULL_
_a_++INT++_
_a_++CHAR++_

Different linkers will not understand the output of your particular process; linker1 will try to search for _a_int_ in a library containing only _a_++INT++_. Since linkers can't use fuzzy string comparison (this could lead to a apocalypse imho) it won't find your function in the library. Also don't be fooled by the simplicity of this example: For every feature like namespace, class, method etc. there has to be a method implemented to map a function name to a entry point or memory structure.

Given your example you are lucky you use libraries of the same publisher who coded some logic to detect old libraries. Usually you will get something along the lines of <something> could not be resolved or some other convoluted, irritating and/or unhelpful error message.

Some info and experience dump regarding Visual Studio and libraries in general:

  • In general the Visual C++ suite doesn't support crosslinked libs between different versions but you could be lucky and it works. Don't rely on it.
  • Since VC++ 2015 the ABI of the libraries is guaranteed by microsoft to be compatible as drescherjm commented: link to microsoft documentation
  • In general when using libraries from different suites you should always be cautious as n. 1.8e9-where's-my-share m. commented here (here is your share btw) about dependencies to other libraries and runtimes. In general in general not having the control over how libraries are built is a huge pita

Edit addressing memory layout incompatibilities in addition to Tzigs answer: different name mangling schemes seem to be partially intentional to protect users against linkage against incompatible libraries. This answer goes into detail about it. The relevant passage from gcc docs:

G++ does not do name mangling in the same way as other C++ compilers. This means that object files compiled with one compiler cannot be used with another.

This effect is intentional [...].

Microsoft Visual C++ runtime versions? Do I need to keep 'em all?

the 2017 redistributable replaces the 2015 one, and so on

Yes, for certain values of "and so on" ;-) The 2015, 2017 and 2019 redistributables are binary compatible with the most recent release thereof. Quoting Microsoft from C++ binary compatibility between Visual Studio 2015, 2017, and 2019:

The runtime libraries and apps compiled by any of these versions of the compiler [2015, 2017, 2019] are binary-compatible. It's reflected in the C++ toolset major number, which is 14 for all three versions. [...] Say you have third-party libraries built by Visual Studio 2015. You can still use them in an application built by Visual Studio 2017 or 2019. There's no need to recompile with a matching toolset. The latest version of the Microsoft Visual C++ Redistributable package (the Redistributable) works for all of them.


does that backward compatibility go all the way back to the 2005 SP1 version?

No. Quoting again from the same page:

The Microsoft C++ (MSVC) compiler toolsets in Visual Studio 2013 and earlier don't guarantee binary compatibility across versions. You can't link object files, static libraries, dynamic libraries, and executables built by different versions. The ABIs, object formats, and runtime libraries are incompatible.

To make things even worse, VS 2005 and 2008 did not have one single set of redistributables, but instead several different versions that were installed in SxS (side by side) mode. From Side-by-side assembly:

In side-by-side, Windows stores multiple versions of a DLL in the WinSxS subdirectory of the Windows directory, and loads them on demand. This reduces dependency problems for applications that include a side-by-side manifest. [...]
Microsoft Visual C++ 2005 and 2008 employ SxS with all C runtime libraries.


are there any well known 3rd party developer tools that you know are using one of the four Redistributables mentioned in my list above?

This is way too wide for any useful answer. You'll have to (a) identify which tools/components/etc you are using, and (b) which are the dependencies of each, including (though not limited to) the C/C++ runtimes.

Static library compiled with Visual C++ is compatible with a higher version of Visual C++?

Generally, no. A static library can only be used with a project that's built using the same compiler version and substantially the same settings. For example, even when using the same VC version, you can't combine a library built with Debug configuration and another module built with Release, or vice versa.

Since you say you've compiled the library, this means you have source code for it. Why not just rebuild it with VC2013?

Visual studio cross linking DLL built from different VC compiler

There is no 'universal ABI' for C/C++, but you can generally get C-style exports on Intel platforms to link against other C-style exports on Intel platforms as long as you make sure they are using a consistent calling convention. If they are using the same name-mangling scheme, you can get some C++ code to link with other C++ code from a different compiler--Intel goes through some effort to make their complier link-compatible with Visual C++.

This of course all falls down with inline code, and in particular the Standard C++ Library is not guaranteed to match up. The link error is there because Visual C++ only maintains Compiler/Standard Library compatibility in the same version (i.e. Update 1 to Update 2), but not between major versions (VS 2013 to VS 2015).

Note that with VS 2017, the C/C++ Library is actually the same as the VS 2015 version.



Related Topics



Leave a reply



Submit