iOS 库研究

96
穿靴子的阿拉丁
2017.07.25 09:31* 字数 2107

一、linux库的创建和使用

编译过程

预处理.i , 编译.o , 汇编.s/.S , 链接.out(可执行程序)
动态库 .so
静态库 .a

预处理: 头文件的包含, 宏定义的展开,编译条件的选择
编译:经过词法分析,语法分析,把源代码翻译成中间语言,及汇编语言
汇编:把汇编代码翻译成机器代码
链接:是一个符号和地址的绑定的过程。把符号信息转换成可执行文件中的虚拟地址等。
动态链接:通过动态符号找到内存地址。
静态链接:链接后,重定位到绝对的虚拟内存地址,以便在运行时读取到该地之中的信息。

静态库

1、创建静态库

gcc -c hello.c
ar -r libhello.a hello.o

2、使用静态库

gcc test.c -lhello -L.
gcc test.c libhello.a -L.

编译参数说明
-Ipath -Lpath -lname

-Ipath
指定的头文件查找,然后到默认的系统头文件查找:
/usr/local/include
/usr/include

-lname
指定库的名字,libname.so(去掉lib,去掉.so)

-Lpath
库搜索路径

3、运行程序
不需要指定库的搜索路径。

动态库

1、创建动态库
gcc -shared hello.c -o libhello.so

2、使用动态库
gcc test.c -lhello -L.

3、运行程序
dyld: Library not loaded: libhello.so
Reason: image not found

需要指定库的搜索路径
LD_LIBRARY_PATH
export LD_LIBRARY_PATH=xxxxpath:$LD_LIBRARY_PATH

/etc/ld.so.conf指定的动态库搜索路径
默认的动态库搜索路径:
/lib
/usr/lib

查询二进制文件所依赖的库列表
gun linux上命令是ldd,freebsd drawin上是otool -L

二、iOS 库的创建和使用

https://my.oschina.net/kaqijiang/blog/649632
http://blog.ibireme.com/2013/09/18/create-ios-static-framework/
http://www.jianshu.com/p/56d5880b2e40
https://segmentfault.com/a/1190000004920754
http://www.jianshu.com/p/ad02ee195ca7

1注意理解:无论是.a静态库还.framework静态库,我们需要的都是二进制文件+.h+其它资源文件的形式,不同的是,.a本身就是二进制文件,需要我们自己配上.h和其它文件才能使用,而.framework本身已经包含了.h和其它文件,可以直接使用。

2图片资源的处理:两种静态库,一般都是把图片文件单独的放在一个.bundle文件中,一般.bundle的名字和.a或.framework的名字相同。.bundle文件很好弄,新建一个文件夹,把它改名为.bundle就可以了,右键,显示包内容可以向其中添加图片资源。

3category是我们实际开发项目中经常用到的,把category打成静态库是没有问题的,但是在用这个静态库的工程中,调用category中的方法时会有找不到该方法的运行时错误(selector not recognized),解决办法是:在使用静态库的工程中配置other linker flags的值为-ObjC。

4如果一个静态库很复杂,需要暴露的.h比较多的话,就可以在静态库的内部创建一个.h文件(一般这个.h文件的名字和静态库的名字相同),然后把所有需要暴露出来的.h文件都集中放在这个.h文件中,而那些原本需要暴露的.h都不需要再暴露了,只需要把.h暴露出来就可以了。

1、 创建、 编译

cocoa touch framework
Dynamic library(mach-o type默认此项):因为iOS沙盒限制不能在不同APP间访问动态库。使用者使用嵌入式动态库,需要添加到embedded binaries中。
Static library:静态库

cocoa touch static library
iOS .a静态库

validate architectures
真机架构.a
armv7: 3gs,4,4s
armv7s: 5,5c
arm64: 5s和以上

模拟器架构.a
i386:4,4s,5,5c
x86_64:5s和以上

build active architecture only为yes,真机build2种(armv7,arm64),模拟器build对应的1种架构

debug:调试版本, 系统本身也会有一些调试代码. 此版本体积会稍大, 运行会稍慢
release:发布版本, 系统会去除调试代码, 体积变小, 运行速度变快. 对用户来说没有明显的感觉

合并库
lipo create xx1.a xx2.a xx.a

拆分库
lipo Hyphenate.framework/Hyphenate -thin armv7 -output Hyphenate_armv7
lipo Hyphenate.framework/Hyphenate -thin arm64 -output Hyphenate_arm64

lipo -create Hyphenate_armv7 Hyphenate_arm64 -output Hyphenate

替换framework
mv Hyphenate Hyphenate.framework/

2、使用库注意事项

1)Other Linker Flags添加-ObjC:静态库里有Category方法,但是调用时报错“unrecognized selector send to instance.”
2)Other Linker Flags添加-all_load或者-force_load xxx,如果你写了一个.m文件,并且里面只有一个Category,强制加载你的库的资源,或者在.m文件增加一下代码:
YYSYNTH_DUMMY_CLASS(NSData_YYAdd)

#ifndef YYSYNTH_DUMMY_CLASS
#define YYSYNTH_DUMMY_CLASS(_name_) \
@interface YYSYNTH_DUMMY_CLASS_ ## _name_ : NSObject @end \
@implementation YYSYNTH_DUMMY_CLASS_ ## _name_ @end
#endif

3)静态库的开发者一定要把静态库中的东西全部加上Prefix来做保护:添加了静态库后,编译报错"有重复定义的符号(duplicate symbol )

3、 使用使用cocoapods插件制作静态库

能解决duplicate symbol问题

mangle symbols of depedendant
用class-dump可以验证。头文件和class类名都被加了前缀。

pod package xx.podspec
https://github.com/CocoaPods/cocoapods-packager

三、cocoapods更新

1,更新gem

homebrew(brew)-》ruby-》gem
http://www.jianshu.com/p/78c3166be2f3

2,更新cocoapods

1、升级cocoapods

sudo gem install cocoapods --pre

2、降级cocoapods
执行sudo gem uninstall cocoapods 卸载现有 cocopods

sudo gem install cocoapods -v 0.39.0

3、更新本地cocoapods库
pod repo update --verbose

4、验证
再查看本地安装过的cocopods相关东西,命令如下:
gem list --local | grep cocoapods会显示如下

gem list --local|grep cocoapods
cocoapods (1.2.0.beta.3, 1.1.1)
cocoapods-core (1.2.0.beta.3, 1.1.1)
cocoapods-deintegrate (1.0.1)
cocoapods-downloader (1.1.3, 1.1.2)
cocoapods-plugins (1.0.0)
cocoapods-search (1.0.0)
cocoapods-stats (1.0.0)
cocoapods-trunk (1.1.2, 1.1.1)
cocoapods-try (1.1.0)

四、创建自己的pod库

1、创建git源代码仓库

2、创建podspec文件pod spec create NAME

3、编辑podspec文件source,resources,source_files等,哪些源代码仓库中的内容需要pods管理,就在podspec中设置对应的规则。保证源代码仓库能被成功编译。

4、检测podspec规范是否合法有效pod spec lint xxx.podspec

5、创建私有的specs仓库
也可以把源代码库仓库同时作为specs仓库, 提交podspec文件到源码git中,不需要 6,7两步。pod 'MyKit', :git => 'https://git.coding.net/xxx/Mykit.git'

6、把specs仓库克隆到本地pod repo add NAME URL [BRANCH]NAME podspec仓库的名称URL podspec仓库的git地址

7、推送.podspec到specs仓库pod repo push REPO [NAME.podspec]REPO podspec仓库的名称,NAME podspec文件名,如果不写则默认取当前目录下的xxx.podspec文件。

8、推送.podspec到cocoapods/specspod trunk register EMAIL [NAME]pod trunk push [PATH]

9、Podfile导入pod,:git,:podspec,:path
在source中设置specs仓库git路径source 'https://git.coding.net/marin-hc/FFSpecs.git'

指向podspec文件pod 'spec1', :git => 'https://git.coding.net/xxx.git'

指向本地的podspec文件的路径pod 'spec2', :podspec => '/Users/ff/xxx.podspec'pod 'Weexplugin', :path=>'./Weexplugin/'pod 'IGListKit', :path => '../../IGListKit.podspec'

例如:pod 'XAspect', :path => './../'安装到Development Pods目录下

10、查找podspec的路径
pod spec which AFNetworking

/Users/ff/.cocoapods/repos/master/Specs/a/7/5/AFNetworking/3.1.0/AFNetworking.podspec.json

http://blog.wtlucky.com/blog/2015/02/26/create-private-podspec/

podspec语法参考:
https://guides.cocoapods.org/syntax/podspec.html

pod命令参考:
http://guides.cocoapods.org/terminal/commands.html#group_specifications

podfile语法参考:
http://guides.cocoapods.org/syntax/podfile.html

http://tips.producter.io/shi-yong-cocoapods-jin-xing-tuan-dui-xie-zuo/

11、pod package xx.podspec
Mach-O universal binary with 5 architectures: [arm_v7: current ar archive] [arm_v7s] [i386] [x86_64] [arm64]
--embedded--library
--dynamicObjects-normal/arm64/MyKit normal arm64(1 failure)

五、符号表/提取头文件

1、class-dump

用class-dump可以把未经加密的app的头文件导出来
class-dump -H testClassDump.app -o test

2、nm

符号表可以提供应用软件及其动态加载的库中引用的函数、类、方法等信息
显示目标文件的符号表,文件对象可以是静态库、动态库、编译目标文件、可执行程序等任何包含符号信息的文件类型

3、otool

查询依赖了哪些库、支持的架构信息、版本号

iOS开发笔记
Web note ad 1