3

Say I have two compilers, or even a single compiler with two different option sets. Each compiler compiles some C code into an object and I try to link the two .o files with a common linker. Will this succeed?

My initial thought is: not always. If the compilers are using the same object file format and have compatible options, then it would succeed. But, if the compilers have conflicting options, or (and this is an easy one) are using two different object file formats, it would not work correctly.

Does anyone have more insight on this? What standards would the object files need to comply with to gain confidence that this will work?

phuclv
  • 37,963
  • 15
  • 156
  • 475
dls
  • 4,146
  • 2
  • 24
  • 26
  • 2
    Most platforms that are not Windows standardize these things. – fuz Aug 11 '16 at 17:19
  • 1
    Related: [On Solaris, are libraries compiled with gcc usable the same way as for libs generated with cc](http://stackoverflow.com/questions/38260829/on-solaris-are-libraries-compiled-with-gcc-usable-the-same-way-as-for-libs-gene) – Mark Plotnick Aug 11 '16 at 17:27
  • 1
    I think you said it yourself. I believe if the object files have the same [ABI](https://en.wikipedia.org/wiki/Application_binary_interface) then they will play nicely together, but I don't have any direct experience with what you're talking about, so there could be some other quirks. – yano Aug 11 '16 at 18:06

1 Answers1

4

Most flavors of *nix OSes have well defined and open ABI and mostly use ELF object file format, so it is not a problem at all for *nix.

Windows is less strictly defined and different compilers may vary in some calling conventions (for example __fastcall may not be supported by some compilers or may have different behavior, see https://en.wikipedia.org/wiki/X86_calling_conventions). But main set of calling conventions (__stdcall, _cdecl, etc) is standard enough to ensure successfull call of function compiled by one compiler from another compiler, otherwise the program won't work at all, since unlike Linux every system call in Windows is wrapped by function from DLL which you need to successfully call.

The other problem is that there is no standard common format for object files. Although most tools (MS, Intel, GCC (MinGW), Clang) use COFF format, some may use OMF (Watcom) or ELF (TinyC).

Another problem is so called "name mangling". Although it was introduced to support overloading C++ functions with the same name, it was adopted by C compilers to prevent linkage of functions defined with different calling conventions. For example, function int _cdecl fun(void); will get compiled name _fun whilst int __stdcall fun(void); will get name _fun@0. More information on name mangling see here: https://en.wikipedia.org/wiki/Name_mangling.

At last, default behavior may differ for some compilers, so yes, options may prevent successful linking of object files produced by different compilers or even by the same compiler. For example, TinyC use default convention _cdecl, whilst CLang use __stdcall. TinyC with default options may not produce code that may be linked with other because it doesn't prepend name by underscore sign. To make it cross-linkable it needs -fleading-underscore option.

But keeping in mind all said above the code may successfully be intermixed. For example, I successfully linked together code produced by Visual Studio, Intel Parallel Studio, GCC (MinGW), Clang, TinyC, NASM.

Serge Goncharov
  • 488
  • 1
  • 6
  • 13
  • Well, how can you link them successfully? Recently I'm confused with [this](https://stackoverflow.com/questions/73396450/why-cant-gcc-and-msvc-compiled-c-object-files-linked-together) too, but I fail to do so... – o_oTurtle Aug 18 '22 at 06:02
  • 1
    First, you must use pure C, because C++ name mangling is different for different compilers. Second, you should use explicit calling convention, _cdecl is preferred. Third, you should play with options to synchronize number of underscore signs in names. And at last you have to use object file format that can be parsed by the preferred linker. This task is sometimes unsolvable if you have to use a certain linker and libraries. I used TinyC as a top-level tool to call VS and GCC functions. – Serge Goncharov Aug 19 '22 at 21:47