What is a non-fragile ABI?

2020-02-24 04:10发布

问题:

It may seem implied that everyone knows what a "Non Fragile ABI" is - considering the frequency and matter-of-fact-nature to which it is referred to - within Xcode. For example...

Subscript requires size of interface node which is not constant in non-fragile ABI

or

Select the Objective-C ABI version to use. Available versions are 1 (legacy "fragile" ABI), 2, (non-fragile ABI 1), and 3 (non-fragile ABI 2).

That said... What is a non-fragile ABI? (and why isn't it called something less-abstract / explained more clearly?)

回答1:

The non-fragile ABI refers to the ability to add instance variables to a class without requiring recompilation of all subclasses.

I.e. in v1 (there really aren't true versions of ObjC), if Apple were to add an instance variable to, say, NSView (on Cocoa, 32 bit), then every subclass of NSView (or subclass of subclass) would have to be recompiled or they would blow up. v2 and v3 fix this.

It is explained in detail in this weblog post.

The documentation you are referring to is in the llvm/clang man page. Pretty rare place to be for most developers most of the time; unless you are writing a Makefile that is driving the compiler directly, there isn't much reason to read that page (unless spelunking -- which is quite educational, of course).

It is written in the style of a Unix man page and, no surprise, is a bit... obtuse. For almost all tasks, it is best to stick to the higher level documentation. I.e. the Xcode build settings documentation is general quite a bit less obtuse.



回答2:

After some poking around, one of the best summaries / pieces of advice on the subject is the following…

The non-fragile ABI allows for things like changing the ivars of a superclass without breaking already compiled subclasses (among other things). It's only supported on 64-bit on the Mac though, because of backwards compatibility concerns which didn't allow them to support it on existing 32-bit architectures.

It goes on to say, basically.. that if Xcode, which often is configured to build for the "Active Architecture Only", aka 64-bit only.. one may run into issues when switching to a "Release" scheme, which is usually set to build for both (63bit/32bit) architectures, aka "Universal"..

You may you want to use ARC on the Mac, I'm pretty sure you'll have to drop 32-bit support to do so. You can change the targeted architectures in the build settings for your target in Xcode.

In my own experience, I believe that what the non-fragile ABI benefits us with is an abbreviated syntax, and patterns such as…

//  source.h  - readonly public properties.  
@interface SuperClassy : NSObject
@property (readonly) NSArray *cantTouchThis;
@end
// source.m  set readonly properties, internally.  
@implementation SuperClassy
// look, no @synthesize… just use _ivarName.
 -(void) touchIt:(NSArray*)a { _cantTouchThis = a; }    
@end
int main(int argc, const char * argv[]) {
    SuperClassy *it = [SuperClassy new];
    // you cannot set it.cantTouchThis = @[anArray].
    [it touchIt:@[@"cats"]];  
    // but you can via a method, etc.
    NSLog(@"%@", it.cantTouchThis);
}

NSLOG ➜ ( cats )