Library ABI compatibility between versions of Visual Studio - c++

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.

Related

VS2012 compatibility with VS2019

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.

Convert from MinGW .a to VC++ .lib

I have an old library (in C++) that I'm only able to build on MinGW+MSYS32 on Windows. From that I can produce a .a static library file generated from GNU libtool. My primary development is done in Visual Studio 2008. If I try to take the MinGW produced library and link it in Visual Studio, it complains about missing externals. This is most likely due to the C++ symbol mangling that is done, and that it doesn't match whats in the .a file. Is there any know way to convert a static .a file to VC++ library format?
If symbols are mangled differently, the compilers are using a different ABI and you won't be able to "convert" or whatever the compiled libraries: the reason names are mangled in different ways is intentional to avoid users from ever succeeding with building an executable from object files using different ABIs. The ABI defines how arguments are passed, how virtual function tables are represented, how exceptions are thrown, the size of basic data types, and quite a number of other things. The name mangling is also part of this and carefully chosen to be efficient and different from other ABIs on the same platform. The easiest way to see if the name mangling is indeed different is to compiler a file with a couple of functions using only basic types with both compilers and have a look at the symbols (on UNIX I would use nm for this; I'm not a Windows programmer and thus I don't know what tool to use there).
Based on Wikipedia it seems that MinGW also uses a different run-time library: the layout and the implementation of the standard C++ library used by MinGW (libstdc++) and Visual Studio (Dinkumware) is not compatible. Even if the ABI between the two compilers is the same, the standard C++ library used isn't. If the ABI is the same you would need to replace set things up so that one compiler uses the standard library of the respective other compiler. There is no way to do this with the already compiled library. I don't know if this is doable.
Personally I wouldn't bother with trying to link things between these two different compiler because it is bound not to work at all. Instead, you'd need to port the implementation to a common compiler and go from there.
Search for the def file and run the command e.g. lib /machine:i386 /def:test.def it will generate
an import lib file.

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

Some projects provide a single set of "Windows" binaries for C (and possible C++ - not sure) libraries. For example, see the links on the right side of this libxml-related page.
I'm pretty sure there's no way to convert between VC++ .lib files and MinGW GCC .a files, so calling them "Windows" rather than "Microsoft" binaries seems a tad misleading. But I'm also surprised that there's no apparent need for different binaries for different VC++ versions.
I seem to remember, many years ago, having problems writing plugins for tracker-style music program (Jeskola Buzz) because that program was using VC++6, and I had upgraded to VC++7. I don't remember the exact issue - it may have been partly DLL related, but I know those don't need to care about VC++ version. I think the issue related to the .lib files provided and maybe also to the runtime libraries that they linked to. It was a long while ago, though, so it's all a bit vague.
Anyway, can libraries compiled by one version of MS VC++ be linked into projects built with another version? What limitations apply, if any?
I'm interested in both C and C++ libraries, which will be called from C++ projects (I rarely use C, except for C libraries called from 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.

Does static library avoids name mangling issues?

I have a C++\MFC application written in Visual Studio 2003 SP1 links to an external static library "SomeExtStaticLib.lib". I also include the header files provided with "SomeExtStaticLib.lib" to create the objects in my application.
SomeExtStaticLib.lib is a static library built with VC6.
Now, I am migrating my application to Visual Studio 2008.
I have very basic question.
Should I also migrate the "SomeExtStaticLib.lib" to VS2008 compiled one?
When I tried to use this VC6 compiled "SomeExtStaticLib.lib" in my VC9 compiled application it did not give any linker errors. I was expecting at least some name mangling issues.
Are static libraries eliminating the name mangling issues?
The issue isn't one of static vs. dynamic linking, nor really of name
mangling. The issue is one of binary compatibility for everything used
in the interface. Thus, for example, unless I'm badly mistaken, the
definition of std::string changed between VC6 and VC9, with a
different layout. So if any of the code uses std::string, you'll have
to recompile, or get strange and unexplicable errors at runtime.
In general, it's best to assume no binary compatibility as soon as
different versions of the compiler, or even different compilation
options are involved, unless the vendor guarantees otherwise. (Although
some common sense is in order: you can freely mix options which only
control warnings, for example. But beware of /Ds which cause added
debugging code to be generated or not.)
If the application is unchanged it needs the same set of symbols from the library. And hence perhaps you can link to the library compiled with VC6.0. Name mangling is not the concern at all unless both the application and library are the same as the compatible(working) ones in VC6.0.
Should I also migrate the SomeExtStaticLib.lib to VS2008 compiled one?
There are compatibility problems between VC6.0 and visual 2008. So YES you should rebuild yor library with Visual 2008.
Just because you can link to the library as is doesn't mean it will work correctly.
Are static libraries eliminating the name mangling issues?
Not really. They are not doing anything special at all.
Static libraries have nothing to do with or without name mangling.... if your code is C++ there is mangling, and if its C (or extern "C" in C++) then there is no mangling. As long as the library and the code that link it agree, there's no problem to link in the library.

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.