最近一直在做公司的SDK项目,也就是制作我们熟知的.a文件,期间碰到了许多的困难,其实制作.a文件并不难,只是期间涉及到的知识点有些多,网上的资料介绍了比较分散,下面我把我制作一个.a文件的过程记录下来,希望看官能多提意见,多给建议.
1.了解指令集的概念
在制作.a文件之前,我们需要知道关于Apple设备的指令集的arm的概念
Arm处理器,因为其低功耗和小尺寸而闻名,几乎所有的手机处理器都基于arm,其在嵌入式系统中的应用非常广泛,它的性能在同等功耗产品中也很出色。
Armv6、armv7、armv7s、arm64都是arm处理器的指令集,所有指令集原则上都是向下兼容的,如iPhone4S的CPU默认指令集为armv7指令集,但它同时也兼容armv6指令集,只是使用armv6指令集时无法充分发挥其性能,即无法使用armv7指令集中的新特性,同理,iPhone5的处理器标配armv7s指令集,同时也支持armv7指令集,只是无法进行相关的性能优化,从而导致程序的执行效率没那么高。
需要注意的是iOS模拟器没有运行arm指令集,编译运行的是x86和i386指令集,所以,只有在iOS设备上,才会执行设备对应的arm指令集。
目前为止Apple移动设备默认指令集(2014.8.22)
-------------------------------------------------------------------------------------
armv6 设备: iPhone, iPhone2, iPhone3G, 第一代、第二代 iPod Touch
armv7 设备: iPhone3GS, iPhone4, iPhone4S
iPad, iPad2, iPad3(The New iPad), iPad mini
iPod Touch 3G, iPod Touch4
armv7s设备: iPhone5, iPhone5C, iPad4(iPad with Retina Display)
arm64 设备: iPhone5S, iPad Air, iPad mini2(iPad mini with Retina Display),及iPhone5S之后的设备
好吧如果你烦于阅读之前的问题,你可以看上表,了解了指令集的概念会对你对静态库的制作不那么迷茫.
然后我这里拿一个新浪微博制作好的.a文件查看他所支持的指令集
在终端使用lipo -info .a文件的路径,查看该.a文件所支持的指令集
支持armv7,arm64,i386,x86_64,这里发现所支持的指令集缺少额armv7s,上文中提到,iPhone5,5c,iPad4为armv7s,并向下兼容armv7的指令集,我这里猜想这里是为了使.a文件的大小精简一些所以没有生成armv7s的版本.
2.开始制作.a文件
这里我将演示如何制作一个.a文件
首先在xcode中新建一个静态库工程
建立好了项目后开始书写代码工程的结构如下,这里删除了原来系统帮我们生成的一个类,自己建立了DownLoadFile这样一个类,封装了一个可以下载的类方法
DownLoadFile.h代码
#import@interface DownLoadFile : NSObject
typedef void (^ComplateBlock)(NSData *data,NSURLResponse *resopse,NSError *error);//定义一个完成的block
+(instancetype)IinInstances:(NSString*)url andComeleteBlock:(ComplateBlock)ComplateBlock;
@property(nonatomic,strong)NSMutableURLRequest *request;
@property(nonatomic,strong)NSURLSession *session;
@property(nonatomic,strong)NSURLSessionDataTask *dataTask;
@end
我们这里封装了一个IinInstances方法为公开的方法
代码写完了之后是在BulidSetting中更改一些设置
其中要注意的是最后生成所支持的指令集的包为Architectures和Valid Architectures的交集
比如Architectures:armv7,amv7s,arm64,Valid Architectures:amv7s,arm64,最后将只会生成支持amv7s,arm64的.a文件,所支持的指令集越多,最后生成的.a文件越大。
之后是设置需要公开的头文件
点击NewHeadersPhase 选择需要公开的头文件,由于我们这里只有一个头文件,我们将它放在public里面
然后准备工作就做好了,之后就是生成自己的.a文件了,选择Generic iOS Device 生成所需要的指令集文件,点击运行.
发现下方的product的.a文件由红变化成普通文件的颜色
之后就去查看一下我们的.a文件了
打开后看到我们的.a文件,可以看到这里是生成的Debug版本的.a文件,如果需要生成release版本的话需要在xcode中设置一下,这里生成的是支持的真机.a文件,在Usr里面有你开始设置公开的头文件,现在我们查看一下我们的.a文件所支持的指令集吧.
同样是在命令行中 lipo -info +路径
支持arm7 armv7s arm64,这样就可以满足市面上绝大多数手机了
如果你还需要生成支持在模拟器上生成的.a文件,选择一个模拟器执行工程就可以生成支持模拟器上运行的.a文件了
多了一个模拟器的.a文件
同样lipo -info
支持i386 和x86_64就可以支持所有的模拟器设备了
然后将这2个.a文件合并
命令行执行 lipo -create 真机.a路径 模拟器.a路径 -output 需要合并之后的.a文件路径
需要注意的是生成的.a文件的路径要带上文件名
之后是查看新生成的.a文件的信息 lipo -info
合并成功支持了2个.a文件的并集
这样就生成了一个支持比较完整的.a文件了
测试一下你的.a文件吧
将你的.a文件加入你的工程中,像以前那样加入所需要的依赖库.在模拟器和真机上跑起来.
3注意事项
1当你的.a文件工程中含有类目的话,记得在设置里面
加上这个.
-ObjC 这个flag告诉链接器把库中定义的Objective-C类和Category都加载进来。这样编译之后的app会变大(因为加载了其他的objc代码进来)。
但是如果静态库中有类和category的话只有加入这个flag才行。
-all_Load这个flag是专门处理-ObjC的一个bug的。用了-ObjC以后,如果类库中只有category没有类的时候这些category还是加载不进来。变通方法就是加入-all_load或者-force-load。-all_laod会强制
链接器把目标文件都加载进来,即使没有objc代码。-force_load在xcode3.2后可用。但是-force_load后面必须跟一个静态库
2静态库使用资源文件需要用到bundle文件.
新建一个bundle文件如下
之后在.a文件中使用到时,和平时使用资源文件的方法一样路径为boundle/xxx/xxx
我的第一篇文章内容就是这些了,希望大家多多支持,有问题可以一起讨论!