前面我们已经了解到了多个点.o文件是怎么链接的,今天关注一下静态库的结构和链接的过程。
先写个简单的静态库
// DemoFramework.h
#import <Foundation/Foundation.h>
@interface DemoFramework : NSObject
@end
// DemoFramework.m
#import "DemoFramework.h"
@implementation DemoFramework
- (void)codingLife {
NSLog(@"codingLife");
}
@end
// GoodBoy.h
#import <Foundation/Foundation.h>
@interface GoodBoy : NSObject
- (void)xuanGao;
@end
// GoodBoy.m
#import "GoodBoy.h"
@implementation GoodBoy
- (void)xuanGao {
NSLog(@"落叶方知秋");
}
@end
好了编译一下生成.a文件,MachOView ,查看一下.a文件
这里可以看到有两个对应.o文件,
start : !<arch>\n 类似于魔书,这样人家就知道这是一个.a文件使用.a文件的结构解析它
-
SymTab Header: 符号表头部
- size: 符号表的大小
Symbol Tabel: 符号表 ,这里的符号表只暴露了一些类的符号表,细节的符号表藏在.o文件中
Object header : .o文件头部信息
.o 文件
MachOView 会crash,记得把修改UI的操作调用到主线程即可,也可以选择命令行工具
现在尝试使用一下这个.a文件
#import "ViewController.h"
#import "GoodBoy.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[[GoodBoy new] xuanGao];
}
@end
这里只import "GoodBoy.h" 以及使用GoodBoy Class。 使用Hopper Disassembler查看一下app执行文件
这里可以看到
[GoodBoy xuanGao] 符号,却找不到 [DemoFramework codingLife] 符号,所以推测在链接时候DemoFramework.o文件并没有链接进入执行文件.
修改一下code
#import "ViewController.h"
#import "GoodBoy.h"
#import "DemoFramework.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[[GoodBoy new] xuanGao];
}
再次反汇编执行文件发现同样的结果,可见import 不会对最终结果产生影响
再次修改code,这次开始使用DemoFramework 对象
#import "ViewController.h"
#import "GoodBoy.h"
#import "DemoFramework.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[[GoodBoy new] xuanGao];
NSLog(@"%@",[DemoFramework new]);
}
@end
再观察一下,这次可以找到codingLife的符号表
结论: 静态库是一系列.o文件的集合,只有被执行文件所使用的.o文件才会最终绑定到执行文件上面。这么做有利于减少执行文件的大小。
注: 可以观察最后执行文件的大小得到同样的结果。