I was wondering, why is it exactly that binaries made with different versions of gcc are incompatible, or is it more with calling the API? I just notice that Windows is able to run applications compiled many years ago, and they can be created with a multitude of different compilers, so how do they do it?
The BeOS was built on a C++ framework, which meant that (outside of the kernel) pretty much everything in the system consisted of C++ libraries.
Now C++ itself has a number of unusual features – such as name mangling, virtual tables, etc. – that are not specified in the language spec itself as to how they should be implemented. Thus each C++ compiler was free to figure out how they wanted to implement the internals for those features.
Gcc decided upon their own implementations when they first developed a C++ compiler many years go. And this is what Be used to develop the Intel version of the BeOS when it came out. Thus all of the BeOS Intel binaries were dependent upon the C++ ABI (application binary interface) that gcc used at the time.
Gcc decided to change this with version 3. That is, their C++ compiler, from version 3.0 and afterwards, generated a different binary format. This switch occurred shortly before Be Inc. went out of business (but way too late for Be to do anything about it). Since Be’s source code was proprietary, the community was stuck with a bunch of binaries (libraries and programs) that were only compatible with the output of older versions of gcc’s C++ compiler.
This is what Haiku inherited. And that’s why we have two sets of libs today – one for version 2.9.5 (the last gcc version before they made the switch) and the current version of gcc (which is changing all the time, but is at 4.x generation). This way we can compile code with new compilers, yet still generate backwards compatible binaries as well.
For other operating systems, this isn’t a problem. Either their system code was written in C instead (e.g. Linux, BSDs) and C doesn’t have these ABI quirks, or, in the case of Windows and Mac, the companies are still around and keep their toolchains constantly up-to-date. The situation with the BeOS is truly unique, AFAIK.
Just to qualify a bit (because I just remembered…)
When the first Intel versions of the BeOS came out, Be used the PE format. This was R3.
Then, in R4, they decided to change to ELF. That’s when they switched to the gcc C++ compiler (away from Metrowerks, I believe). This was a big brew-hah at the time because it broke all the existing Intel binaries, but Be felt that it had to be done.
Now, if only gcc had already changed their C++ ABI by this point, then all this binary incompatibility jazz (that we’re stuck with today) would have been completely avoided.
Or even if gcc had changed their ABI a short time after this, it still could have been avoided. Either Be could have set a migration path for developers to switch over, or they could have just laid down the gauntlet and said “sorry guys, but you’ll have to recompile all your sources again with the new compiler”.
But, alas, it was not to be. Sigh.
Also, I want to make one more comment about Windows.
Microsoft has developed all their own binary formats for exectuables and libraries. Therefore, they were in a position to make sure each new one was compatible with former ones. From MZ, to LE, to PE (not sure if I got those names right… anyway) they made each new format capable of handling the older one. You can say many things about Microsoft (good and bad), but they’ve always been good about maintaining backwards compatility with their older formats.
The other side to this, though, is that MS, by its sheer clout, could guarantee this compatibility. They had complete control over the design of the binary formats – it was their baby. Afterwards, they could then go to compiler makers and say “support this format”. If you want to produce Windows binaries, you have to support Microsoft’s formats. Period.
A small company like Be was in no position to do this. Even if they had developed their own “Be executable format”, how likely is it that they could have forced any compiler vendor to generate this format. Be would have been stuck writing their own compiler, and that’s not what they were in business to do. And even if they had gotten Metrowerks (or somebody) to actually write a compiler that generated this special Be executable format, how long would this support have lasted after Be went belly up? No, not very long.
So Be did the sensible thing and used existing, quality development tools. They could not do anything about unforseen changes in compiler formats by these external toolmakers. Few companies can control this situation the way that Microsoft can.
In other words, compairing Microsoft’s ability to keep compatibility of binaries among many generations of Windows to other companies (especially small ones like Be) is not really fair.
Very well explained, thank you. So, are these changes enough to break compatibility with libraries etc. but not enough to stop a gcc4 executable running on the gcc2 system or does the kernel figure out which it is and do stuff accordingly? Also, am I right in thinking that there are features in gcc4 that gcc2 simply doesn’t have due to improvements in the language, hence why many apps need gcc4 hybrid systems to work?