Objective-C Compiler and Runtime FAQ
Objective-C Compiler and Runtime FAQ
An Objective-C implementation comes in two components; a compiler and a runtime library. The compiler is responsible for parsing the source code and produces a binary that contains calls to the functions in the runtime library. This library is responsible for things like message sending and introspection.
How Many Runtimes Are there?
If you have used Objective-C on Mac OS X, then you will have used one or both of Apple's two Objective-C runtimes. The Apple legacy runtime is based on the version implemented by NeXT back in the '80s, although it has seen some improvements since that time and is often referred to as the NeXT runtime. Apple's modern runtime is a complete rewrite, introduced with OS X 10.5. The modern runtime is required for Objective-C 2 and is the default on 64-bit platforms.
The implementation of Objective-C produced by NeXT was based on GCC and as such NeXT was required to release the relevant compiler changes. The NeXT Objective-C runtime was not open sourced (it was later, after Apple bought NeXT, but the code is not particularly portable and so is not used on platforms other than Darwin) and so the GNU project created a new one, generally referred to as the GNU runtime.
In 2009, a fork of this was committed to GNUstep subversion repository as libobjc2. This contains a lot of new features and removes a lot of legacy code, but is not yet considered production ready. Unlike the original GNU runtime (which will be referred to as the GCC runtime, for differentiation), this can be built outside of the GCC tree and distributed independently. The GNUstep runtime supports two ABIs. One is compatible with the GCC runtime, the other is new and is designed to support Objective-C 2.
Which Runtime Should I use?
If you are using a recent version of GCC to compile your code then you should have a copy of the Objective-C runtime library that came with your compiler.
If you are using a very old version of GCC then you may need to use a newer version of GNU runtime. If you experience problems with the version of runtime that came with your compiler, then you should install libobjc from GNUstep subversion (libs/libobjc/trunk). This is a copy of version 1.6 of the GCC runtime which is modified to build outside the GCC tree.
For more advanced features, currently only supported if you compile with Clang, you will need the GNUstep runtime. This is not currently considered production ready. It should work as a drop-in replacement for the GCC runtime, but some of the advanced features are not well-tested.
What is or was the Étoilé Runtime?
The Étoilé Runtime is a research prototype that was originally intended to succeed the GNU runtime. After some time, it was determined that porting GNUstep to a completely new - and radically differently designed - runtime would be a massive undertaking, as would providing all of the related compiler support. It was also decided that two incompatible ABIs would not benefit anyone. The author of the Étoilé runtime is the maintainer of the GNUstep runtime and has back-ported most of the improvements from the Étoilé runtime to the GNUstep runtime.
Which Compiler Should I Use?
The history of Objective-C in GCC is somewhat complicated. Originally, NeXT was forced to release the original Objective-C front end in order to comply with the GPL. This code was not quite compatible with the GNU runtime and so it was modified. NeXT did not adopt these modifications and so each release of GCC by NeXT, and then Apple, contained changes that needed back-porting to the main branch of GCC.
For a long time, GCC was the only compiler that worked with GNUstep. Unfortunately, the GCC team has not invested much effort in Objective-C in the last few years and it currently lags behind Apple's version by a significant amount.
As of version 4.3, the Free Software Foundation changed the license of GCC to version 3 of the GNU General Public License. This means that future versions will not be shipped by Apple. OS X 10.6 ships with three compilers:
- Apple's fork of GCC 4.2.1
The latter two use the Low-Level Virtual Machine (LLVM) for code generation. This is a BSD-licensed compiler infrastructure used by several other projects. LLVM-GCC is a hybrid, using Apple's version of GCC for parsing and LLVM for optimisation and native code generation. Clang is a new front end for LLVM.
Currently, LLVM-GCC is based on Apple's GCC and so does not support the GNU runtime. There is an effort underway to rewrite LLVM-GCC as a plug in for GCC 4.5, at which point it should support as much Objective-C as GCC currently does.
Unlike GCC, Clang features a clean abstraction layer between the runtime-specific and runtime-agnostic parts of the compiler. This means that adding support for new features on the GNU runtime is simply a matter of implementing the relevant methods in the CGObjCGNU class. This means that Clang is able to support almost everything on the GNUstep runtime that it does on either of the Apple runtimes. Note, however, that Clang only recently reached version 1.0 status. Current subversion builds are more stable, but things like generating debugging info are still somewhat unreliable.
Which Bits of Objective-C 2 Work?
The answer to this question depends on the combination of compiler and runtime library that you are using. Currently, no features of Objective-C 2 work with GCC.
If you compile with Clang then you have access to declared properties, fast enumeration, and blocks. Note that both of these require some support from the runtime. This must be provided either by the GNUstep runtime or by the ObjectiveC2 framework, which you can acquire from Étoilé subversion. For blocks to work, you must also compile with -fblocks.
If you compile with the -fobjc-nonfragile-abi flag then you will use the new ABI. This is only supported with the GNUstep runtime. This adds:
- Property introspection
- Introspection on optional protocol methods
- Non-fragile instance variables
- Forwarding proxy support
Unlike Apple's non-fragile ABI, it is possible to mix code compiled for our fragile and non-fragile ABIs with some caveats. Message sending from code compiled with the fragile ABI will not be able to take advantage of forwarding proxies. If you subclass a non-fragile ABI class with a class compiled with the fragile ABI then you will not receive any benefits; the class compiled with the fragile ABI must be able to see all of the instance variables in the superclass at compile time or things will break. Some benefits will be obtained the other way around, however. A class compiled for the fragile ABI will always be able to access its own instance variables safely when the superclass changes, even if the superclass layout changes. It will, however, only be able to safely access instance variables declared in superclasses safely if the superclass is also compiled with the non-fragile ABI or if the superclass instance variable layout does not change.
Can I use Apple's Runtime APIs?
You not only can, but should!
With OS X 10.5, Apple introduced a new set of APIs for interacting with the runtime. These hid the implementation details - previously all public - behind a set of public functions, implemented on both the modern and legacy runtimes.
These functions are supported by the GNUstep runtime and can also be used with the GCC runtime if you link against Étoilé's ObjectiveC2 framework.
From release 1.20.0 of the base library onwards the new runtime APIs are built in to the GNUstep base library (the Étoilé ObjectiveC2 framework is incorporated into base and extended/improved) so that the new APIs can be used with both old and new runtimes.
What About Garbage Collection?
GNUstep has supported garbage collection via the Boehm GC for some years. Efforts are underway to bring this to closer compatibility with Apple's new implementation.