We have a lot of prebuilt libraries (via CMake mostly), built using Visual Studio 2017 v141. When we try to use these against a project using Visual STudio 2019 v142 we see errors like:
Error C1047 The object or library file ‘boost_chrono-vc141-mt-gd-x32-1_68.lib’ was created by a different version of the compiler than other objects...
On the other hand, we also use pre-compiled .libs from 3rd-party vendors which are over a decade old and these have worked just fine when linked against our codebase.
What determines whether a library needs to be rebuilt, and why can some ancient libraries still be used when others that are only one version behind cannot?
Technically your compiler does not figure out which libraries will be used. The linker (commonly ld ) does this. The header files only tell the compiler what interface your library functions use and leaves it up to the linker to figure out where they are.
With reference to MSDN, this error The object or library file 'file' was created with an older compiler than other objects; rebuild old objects and libraries is caused when object files or libraries built with /LTCG are linked together, but where those object files or libraries are built with different versions of the ...
This is because there is no sequence point anywhere in that expression. The only requirement is that each of those subexpressions is evaluated before the result is needed (that is, before the result is to be printed).
Hi, Yes, it is also possible for results to differ when the compiler version is different.
The ABIs, object formats, and runtime libraries are incompatible. We've changed this behavior in Visual Studio 2015, 2017, and 2019. The runtime libraries and apps compiled by any of these versions of the compiler are binary-compatible. It's reflected in the C++ toolset major number, which starts with 14 for all three versions.
This means that when compiling they require inclusion of library header files when you create a .o file, as well as a linking stage when creating an executable. Let’s take a look at how we can link to a library called Google test, which performs modular code testing for files. For more information on Google testing visit our post here.
You can't link object files, static libraries, dynamic libraries, and executables built by different versions of these toolsets. The ABIs, object formats, and runtime libraries are incompatible.
Some libraries do not require explicit inclusion or linking becuase the compiler g++ already knows where to search. For example, iostream is actually a header file which operates the same way as any other library. It’s placement is computer specific, but mine is stored in /usr/include/c++/4.8/iostream along with other standard c++ header files.
ABI incompatibilities could cause some issues. Even though the C++ standard calls for objects such as std::vector
and std::mutex
and that they need to have specific public/protected members, how these classes are made is left to the implementation.
In practice, it means that nothing prevents the GNU standard library from having their data fields in another orders than the LLVM standard library, or having completely different private members.
As such, if you try to use a function from a library built with the LLVM libc++ by sending it a GNU libstdc++ vector it causes UB. Even on the same standard library, different versions could have changed something and that could be a problem.
To avoid these issues, popular C++ libraries only use C data structures in their ABIs since (at least for now) every compiler produces the same memory layout for a char*, an int or a struct.
These ABI issues can appears in two places:
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:
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 [...].
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