创建.a文件

一 创建.a

  1. 创建真机.a

    • Valid Architectures设置:armv7|armv7s|arm64|i386|x86_64
    • Architectures设置: armv7|arm64
    • Build Active Architecture Only :NO
    • 用真机运行或者选择Generic iOS Device (此时)
  2. 创建模拟器.a

    • Valid Architectures设置为:armv7|armv7s|arm64|i386|x86_64
    • Architectures设置: i386|x86_64
    • Build Active Architecture Only :NO
  3. 合成支持模拟器的和真机的

    • lipo -create 真机库.a的路径 模拟器库.a的的路径 -output 合成库的名字.a

注意:

如果Valid Architectures中添加了armv7s,就一定得添加armv7

二 查看.a文件包含的文件

取出armv7平台的包:

  • lipo 查看的.a -thin armv7 -output armv7/抽出的.a

查看库中所包含的文件列表:

  • ar -t armv7/抽出的.a

三 查看 .o 的反编译代码

在 Mac 上可以用 Mac 的反编译工具的otool 这个命令来反编译 .o 文件,比如 otool -tv xx.o

四 常见模拟器&真机所使用的CPU架构

苹果 A7 处理器支持两个不同的指令集,32位 ARM 指令集(armv6 | armv7 | armv7s),64位 ARM 指令集 (arm64)

  • i386/x86_64:

    • i386 是针对 intel 通用微处理器 32位架构的,x86_64 是针对 x86 架构的 64位处理器
    • 模拟器
  • ARMv8/ARM64

    • iPhone 5s ~ iPhone X, iPad Air ~ iPad 5th
  • ARMv7s:
    • iPhone 5/5c, iPad 4th
  • ARMv7:
    • iPhone 3GS~4s, iPad 1st ~ iPad 3rd

五 Build Settings Architecture

  • Architectures

    • 指定工程支持指令集的集合,设置多个 Architecture 则会在生成的包中包含多个指令集

    • 默认 Standard architectures(armv7,arm64) (之前的Xcode版本中默认设置还包括armv7s,现在去掉了,估计是因为armv7s相较armv7优化不大,能向下兼容,而设置后还会增大二进制包的大小)

    • 模拟器

      • 选择什么生成什么架构的,如果是Standard architectures,则声称i386、x86_64
    • 真机

      • 根据 和 Valid Architectures 的交集确定最终数据包中包含的指令集。比如:armv7、armv7s、arm64
  • Valid Architectures

    • 合法的指令集
      • Architectures 和 Valid Architectures 的交集会确定最终数据包中包含的指令集
      • 默认设置为 armv7 armv7s arm64
  • Build Active Architecture Only

    • 是否只针对当前连接设备所支持的指令集编译

    • 默认 Debug 为 YES, Release 为 NO

六 lipo

lipo是管理Fat File的工具, 可以查看cpu架构, 提取特定架构,整合和拆分库文件

  • 查看信息,支持的cpu架构列表
    • lipo -info xxxx.a
  • 整合成Fat文件
    • lipo -create xxxx.a xxxx1.a -output xxxx.a
  • 提取特定的cpu架构的thin文件
    • lipo xxxx -thin cpu(armv7/arm64等) -output xxxx.a
  • 移除掉特定的cpu架构的文件
    • lipo -remove cpu(armv7/arm64等) xxxx -output xxxx

七 静态库与动态库

库(Library)是一段编译好的二进制代码,加上头文件就可以供别人使用。编译的时候只需要link一下,link(链接阶段)的不同的形式(静态或动态)决定库是静态库还是动态库

编译过程:

 源文件 -> 预编译 -> 编译 -> 汇编 -> 链接 -> 可执行文件                                                          

一般会有两种情况要用到库:

  • 某些代码需要给别人使用,但是我们不希望别人看到源码,就需要以库的形式进行封装,只暴露出头文件
  • 公司中常用且变动很少的模块可以编译成库,这样做的好处一是可以节省编译时间,二来对于代码的管理也非常方便
7.1 静态库(.a、.framework)

静态库在链接(link)阶段,会将汇编生成的目标文件.o与引用到的库一起链接打包到可执行文件中,对应的链接方式称为静态链接。一个静态库可以简单看成是一组目标文件(.o/.obj文件)的归档集合

静态库的特点:

  • 静态库嵌入App
    • 在App项目编译的时候会被编译到目标程序中,所以得到的App二进制文件会变大
    • 浪费空间和资源的弊端
    • 不同的应用程序如果调用相同的库,那么在内存里会有多份该共享库的实例
    • 静态库更新,程序需要重新编译
  • 静态库依赖的其他类库,需要手动导入
  • 减少耦合
    • 不可以包含其他静态库
  • 每一个静态库都是独立的,不会重复引用
  • StaticLibrary需要设置头文件搜索路径,Framework不需要
  • 共享运行环境(一个应用程序中)
    • 假如其运行环境中包换库中同一个类,会发生代码冲突,必须剥离其中一方的此类,然后共享此类

framework和.a两种静态库的区别

  • .a是一个纯二进制文件
    • .framework中除了有二进制文件之外还有资源文件
  • .a文件不能直接使用,至少要有.h文件配合
    • .framework文件可以直接使用。
  • .a + .h + sourceFile = .framework。
  • .a只是静态库
    • framework既可以是静态库也可以是动态库
7.2 动态库(.framework、.dylib、.tbd)

动态库在链接(link)阶段,不会被链接到目标代码中,而是在程序运行是才被载入

动态库(也称共享库)的特点:

  • 程序运行时才被载入

    • 避免浪费空间和资源的弊端
    • 不同的应用程序如果调用相同的库,那么在内存里只需要有一份该共享库的实例
    • 增量更新
    • 动态库更新,程序不需要重新编译
  • 动态库可以包含静态库,也能自动link所需要的依赖库

  • 与运行环境隔离

    • 运行环境中包换库中同一个类,不会发生冲突,同名的两个类会在各自的环境中独立运行,互不干扰,哪怕是单例类

注意:

1 苹果在iOS 8之前并不支持自己开发的framework.

2 自己开发的framework无论是动态还是静态的,都要复制到目标程序,苹果又把这种Framework叫做Embedded Framework

3 Xcode中需要导入我们自己制作的动态库时,需要在Xcode中的Build phase->Copy Files选项添加,其中destination选择“Frameworks”,不然会报错:image not found。

7.3 判断库是动态库还是静态库,用file命令
$ cd myframework.Frameworks
$ ls -l
    myframework
$ file myframework
#静态库,显示archive
> myframework.Frameworks: Mach-O universal binary with 2 architectures: [arm_v7:current ar archive] [arm64]
> myframework.Frameworks (for architecture armv7):  current ar archive

 #动态库,dynamically
> myframework: Mach-O universal binary with 2 architectures: [arm_v7] [arm64:Mach-O 64-bit dynamically linked shared library arm64]
> myframework (for architecture armv7): Mach-O dynamically linked shared library arm_v7
7.4 合并两个静态库
lipo -create 模拟器静态库(动态库) 真机静态库(动态库) -output 新静态库的名称(动态库)

注意:

  • 动态库不是合成.framework,是合成.framework里面的一个黑色文件(二进制文件),生成的也是这个黑色文件,只需将合成的黑色文件替换就好了

  • 如果制作的是动态库的话,一定要embeded binaries中将库导入一下(target —> General —> Embedded Binaries下添加你的动态链接库)

    • 或者你也可以将动态库当做一个资源文件使用在Build Phases->Copy Bundle Resources中添加,然后就可以用bundle的方式使用动态库了
  • 如果库中包含系统的分类,一定要在target linker flag 里面配置-ObjC以及-all_load

    NSString *documentsPath = [NSString stringWithFormat:@"%@/Documents/FWPaySdk.framework/FWPaySdk",NSHomeDirectory()];  
     NSError *err = nil;  
     NSBundle *bundle = [NSBundle bundleWithPath:documentsPath];  
     if ([bundle loadAndReturnError:&err]) {  
         NSLog(@"bundle load framework success.");  
     } else {  
         NSLog(@"bundle load framework err:%@",err);  
     }  
    
     Class worder = NSClassFromString(@"FWorder");  
      FWorder * order = (FWorder *)[[worder alloc] init];

八 Framework、.a、.dylib/.tbd

8.1 .Framework(框架)

  • Headers

    • Framework需要暴露的头文件
  • binary文件

    • 整个Framework的核心,所有代码都被编译成了这样一坨二进制文件,
    • 添加的依赖库不会被编译进来,用的时候需要重新link其他依赖库。
  • .bundle

    • 资源文件都打包放在这里。在制作Framework的时候不可以把图片直接放在项目中,否则制作好之后图片是一张一张的出现在项目中非常乱,需要新建一个bundle将图片放进去,这里的bundle提供整个SDK的图片资源
    • 图片放进bundle之后不可以用[UIImage ImageWithName:]读取图片。要先找到bundle包再拿图片
    
    #define BUNDLE_NAME @"Resources.bundle"
    
    
    
    #define BUNDLE [NSBundle bundleWithPath: [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent: BUNDLE_NAME]]
    
    
    
    #define LOADIMAGE(name) [UIImage imageWithContentsOfFile:[[BUNDLE resourcePath] stringByAppendingPathComponent:name]]
    

  • Info.plist和Modules

    • 记录Framework的版本等相关信息,一般都会删掉

注意:

1 Framework是动态库还是静态库,取决于编译成的Mach-O(就是那个二进制文件)

2 Buiding Setings -> Mach-O Type: 默认选择的是Dynamic Library(动态库),选择Static Library是静态库

8.2 .a

  • 这类静态库与Framework基本类似,在打包成.a文件的同时,还需要提供头文件,而Framework编译完成暴露的头文件都已经放好了

8.3 .dylib/.tbd

  • 基本上都是系统提供的动态库

九 如何选择使用Framework还是StaticLibrary

  • 假如不想在同一个App中包含多份三方库(减小包大小),可以使用StaticLibrary,库本身和App共享第三方库。但是产出物的结构可能会比较乱。
  • 假如不想考虑和App的代码冲突问题,库本身独立使用需要的库,想提供比较好的库结构,可以使用Framework。但是假如库本身和App都使用了同一个三方库,会存在两份三方库,会增加包大小。

十 iOS自动化版本号和编译号

agvtool

  • 是一个增加版本号的命令行工具

版本号(Version)

  • 给用户看的,用于标明当前的发行版本
  • 存储在 Info.plist 文件的 CFBundleShortVersionString (Bundle versions string, short)

编译号(Build)

  • 内部使用的,用于标明未发行或者已内部发行的应用程序
  • 存储在 Info.plist 文件的 CFBundleVersion (Bundle version)

注意:如果应用程序包含了多个目标(target),agvtool 工具将会把所有目标都设置为同一个版本号和编译号。

10.1 启用 agvtool

  • 设置 Current Project Version 为选定的值
    • Xcode 工程文件project.pbxproj包含了 CURRENT_PROJECT_VERSION (Current Project Version)编译设定,这个编译设定指定了当前工程的版本。agvtool 会搜索此编译选项。如果这个值存在就运行,否则不运行,这个值用来更新编译号
  • 设置 Versioning System 为 Apple Generic
    • 默认情况下苹果不使用任何版本系统,设置为 Apple Generic 确保 Xcode 包含全部的 agvtool 生成的版本信息

10.2 设置版本和编译号

  • 进入到包含 .xcodeproj 工程文件的目录
  • 更新版本号
/*
注意: 
如果存在多个Xcode需要选择一个,否则报错。 
sudo xcode-select -switch /Applications/Xcode.app/Contents/Developer
*/
 agvtool new-marketing-version  2.1
  • 更新编译号
//自动更新编译号
 agvtool next-version -all  
//更新编译号
 agvtool new-version -all 2.1
  • 查看版本号
agvtool what-marketing-version
  • 查看当前编译号
agvtool what-version

十一 其他:

1 User Head Search Paths 和Head Search Paths的区别

共同点

  • 用来存放 Project 中头文件的搜索根源,没有被add到项目里的头文件

区别

  • Xcode设置了Header Search Paths,则一定会去搜索的。

  • UserHeader Search Paths只有在Always Search User Paths(是否搜索用户路径)为Yes时才会被搜索

    • <> 是从系统目录空间 (对应 Header Search Paths)中搜索文件,只在Header Search Paths 中搜索
    • “” 是从用户目录空间(对应 User Header Search Paths)中搜索文件,如果没有则去Header Search Paths 搜索

2 iOS Code Sign On Copy

xcode中embed的framework,都是需要签名的。如果在生成framework时,签过名了,就不用在选上 code sign on copy选项了。如果没有签过名,必须选上,不然无法在真机上运行!

  • Optional
    • 根据系统版本选择加载framework
  • Require
    • 直接加载framework

对于链接的系统动态库而言,由于ios的系统是在不断的升级中,必然会引入不少新功能和新API,而大多数都是会以.framework的方式提供给开发者。如果开发者使用了这些新引入的.framework,那么因为app的用户的系统版本不是统一的,所以用户机器上不一定都存在该动态库,此时就应该把链接的这些新的.framework改成Optional的,然后在程序代码中去动态判断用户版本,来启动对应的新功能,如果不修改成Optional而保持Required的话,在部分不存在该动态库用户的机器上,就会导致app一启动就退出,因为找不到对应的动态库

4 iOS动态库Framework没有import相应文件的提示 或 Could not build module

原因是没有把对外部公开的类,放到public里面

注意:如果Public中的头文件,import了其他的头文件,也要放倒public里

这里写图片描述

参考

1 xcode6不再构建arm7s

2.iOS开发——制作同时支持armv7,armv7s,arm64,i386,x86_64

3.iOS Device Compatibility Reference

4.App Distribution Guide

5.iOS Build Settings Architectures

6.关于Xcode “Build Setting”中的Architectures详解

7 WWDC 2014 Videos

8 使用CocoaPods开发并打包静态库

10 iOS 最新framework和.a静态库制作及使用全解(含工程套工程,多工程联调)

11 iOS 静态库,动态库与 Framework)

12 App Extension Programming Guide

13 iOS静态库SDK制作(包含第三方静态库)

14 Automating Version and Build Numbers Using agvtool

你可能感兴趣的:(常用,ios开发)