I understand that C++ compilers are not compatible with each other. However, I was unable to find anything on this topic for C in particular. I know that the C standard leaves a lot of room for compilers to implement things however they see fit: for example, the size and alignment of most (all?) data types is implementation-defined save for some minimal guarantees. Therefore, two compilers (or two versions of the same compiler) can disagree on numerous details.
Am I correct in thinking that there's no guarantee that two object files compiled with different compilers will actually link properly? For example, the size of pointers could be 32 bits in one object file and 64 bits in the other. But if that's so, why are C libraries sometimes distributed in precompiled form? Is there an expectation that I'll use the same compiler they did (e.g. gcc), or some de facto standard being used to ensure binary compatibility? And how do other languages with a Foreign Language Interface ensure things will line up properly when linking with C object files?
-
As far as I can remember, C object files should be compatible with each other as long as they are compiled for the same platform. An object file is just an archive containing loadable binary code with some symbol table that can be used to access each symbol inside the module.Giorgio– Giorgio2014年04月11日 18:36:07 +00:00Commented Apr 11, 2014 at 18:36
-
2libs can be made compatible, I don't think obj are guaranteed to beratchet freak– ratchet freak2014年04月11日 19:10:25 +00:00Commented Apr 11, 2014 at 19:10
-
@Giorgo By "same platform", do you mean CPU architecture or CPU architecture + OS?Doval– Doval2014年04月11日 19:12:19 +00:00Commented Apr 11, 2014 at 19:12
-
1@ratchetfreak I was under the impression a lib is for the most part just a concatenation of multiple object files. Is that wrong?Doval– Doval2014年04月11日 19:12:53 +00:00Commented Apr 11, 2014 at 19:12
-
I would not expect objects to be compatible across different compilers.old_timer– old_timer2014年04月12日 02:55:36 +00:00Commented Apr 12, 2014 at 2:55
2 Answers 2
The general answer is no, C language compilers are not compatible with each other. The C language standard does not define any kind of binary interoperability, and most compiler writers don't even try.
I need to qualify that. The objects emitted by a C compiler have to be linked with runtime libraries to produce either an executable or a runtime linkable library. Although the visible functions provided by the C runtime library should be compatible, there will also be non-visible functions that are unique to the implementation and prevent interoperability.
This lack of compatibility also extends to different versions of the same compiler. In general, programs and libraries compiled with older and newer versions of a compiler cannot be linked together, and those compiled with MSVC cannot be linked with those compiled by GCC.
There is a specific and very useful exception. Every platform provides a dynamic linking ABI (Application Binary Interface) and any program in any language that can conform to that ABI is compatible. Therefore it is generally possible to build a DLL (on Windows) with MSVC (or something else) and call it from a program compiled by a different version of MSVC or by GCC and vice versa.
There are two other ABIs on Windows: COM and .NET assemblies, and they span a wide range of languages. So interoperability is definitely possible, but compatible they are not.
The degree of incompatibility can easily be seen by comparing the linker maps. For GNU use ld -M
, for MSVC use link /map
. Study the two generated files. Both will have names in them that you recognise, such as printf and main, although (depending on options) the names are likely to be mangled in various ways. They will also have names that are completely different, many of which you won't recognise. In order for object files produced by different compilers to be compatible they have to agree on all those names, and they never do. Not even different versions of the same compiler can always do that.
-
1This answer seems to contradict Bart's; it sounds like only shared libraries are compatible. Could you explain why the non-visible, implementation-specific functions of the C runtime library prevent interoperability? You also say "the objects emitted by a C compiler have to be linked with runtime libraries to produce either an executable or a runtime linkable library" - what about static libraries?Doval– Doval2014年04月14日 12:22:03 +00:00Commented Apr 14, 2014 at 12:22
-
As Bart said, only libraries with an ABI are compatible. Shared libraries (on Unix) are one kind of ABI, there are others. Write HelloWorld.c, compile it with MSVC and gcc, compare the maps and you'll see how different they are. 'Runtime libraries' means the essential support functions automatically referenced in every C/C++ compile, which may be statically or dynamically linked. Read the map or the CRT source code to see them.david.pfx– david.pfx2014年04月14日 14:21:08 +00:00Commented Apr 14, 2014 at 14:21
-
I don't know what comparing the maps means so I'll be a little bit more specific: is it safe to assume in practice that all compilers for a given CPU architecture AND OS combination are compatible? E.g. I have main.c, which I compile with gcc and mylibrary.c which I compile with clang, both targeting Linux x64. Assuming a reasonably mainstream OS (Linux, Mac, Windows), is it safe to assume that would work regardless of what the two compilers are?Doval– Doval2014年04月14日 17:17:38 +00:00Commented Apr 14, 2014 at 17:17
-
1Highly unlikely, check the clang link map. See edit.david.pfx– david.pfx2014年04月15日 00:55:04 +00:00Commented Apr 15, 2014 at 0:55
-
"Every platform provides a dynamic linking ABI..." Can you please explain what you mean by 'dynamic linking ABI', if possible citing a reference.Declan– Declan2021年03月21日 18:25:46 +00:00Commented Mar 21, 2021 at 18:25
What you are looking for in called an ABI (Application Binary Interface).
The C language does not define an ABI, so in that sense there is indeed no guarantee that C files compiled with different compilers will work with each other.
On the other hand, on most platforms the OS defines an ABI for interfacing with it and all compilers targeting that OS & processor family also use that same ABI for interfacing with non-OS components. So, in practice, C objects created by different compilers can work with each other.
-
That makes sense. I take it shared libraries follow the OS's ABI too?Doval– Doval2014年04月11日 22:26:40 +00:00Commented Apr 11, 2014 at 22:26
-
3@Doval Especially shared libraries, they need to be callable by the outside world.toasted_flakes– toasted_flakes2014年04月11日 22:56:00 +00:00Commented Apr 11, 2014 at 22:56