iOS static library,load dynamic libraryy和framework有什么区别

1092人阅读
IOS-深入(182)
在Xcode 4.3中如果是新建一个Mac OS X的项目,可以看见“Framework & Library”内有各种各样的Library及Framework的模板,当然,这些都可以是静态链接或者动态链接的。
但是如果新建的是iOS的项目,在“Framework && Library”内的模板就少得可怜,就只有一个“Cocoa Touch Static Library”,顾名思义就是一个静态链接库模板。
静态链接库用起来的颇为麻烦,libxml2就是一个例子,首先要加入linker内让linker找到符号,然后还需要配置Header让compiler可以找到这些符号的定义。基于这种不人性化操作,苹果在自己的平台上推出了一种新的引用方式,那就是Framework。
Framework其实就是将Header及Library打包在一起方便使用,在苹果的官方文档,Framework还可以嵌套打包,其称为Umbrella Framework,不过其不建议普通用户这样做而已。我们平常使用的QuartzCore、UIKit、CoreFoundation等均打包为Framework。
可惜的是,因为没有模板,所以不能简单地创建一个Framework,但是一个开源的模板项目可以帮到我们:。
这个模板分开两块:Fake Static Framework 和 Real Static Framework,安装及使用方法在github上的项目有详细教程(其实很简单,运行一个脚本就OK)。
看到名字开始会很疑惑,这东西还能有Fake和Real的?
原来,苹果出于某种原因的考虑,在Xcode上禁用了iOS项目引入非官方Framework的功能,所以这里的Framework分成了两种。
Fake的是通过一个bundle模拟Framework,这个不需要对Xcode进行任何改动,只需要添加一个项目模板即可,但是使用这个模板并且开启ARC时候会出现问题,这个后面会说道。
Real的生成出来的product就是一个真真正正的Framework,但是由于Xcode不支持在iOS上使用自定义Framework,所以需要向Xcode内加入两个xcspec文件以启用支持。
将两个模板都安装完成后,可以看见iOS中的“Framework & Library”多出了两个Framework的模板。看看名字,里面均有一个“Static”,这表示生成的Framework都是静态的,因为苹果是禁止开发者向iOS内添加动态库的,这样就可以保证所有应用的依赖均来源于苹果内部,降低开发难度也可以保证应用不会因为缺少依赖库而Crash。所以,无论Static Framework或者Static Library,最终所有的符号均会被内联到程序中,跟直接在项目内编写代码是一样的。
既然生成的二进制都是一样的,为什么还要提取一个库出来呢?虽然iOS上二进制是不可共享的,但是代码是可以共享的,可以将经常使用的组件提出成一个公共库,再供给程序使用,这样可以有效减低程序内的代码量。(说离题了。。。)
下面说说 Static Library、Fake Static Framework、Real Static Framework 使用需要注意的事项以及其优劣,特别是在Deployment Target 在 iOS 5.0以下时候容易出现的问题。
Static Library:
简单的静态链接库,其使用Libtool生成静态链接库文件,不会因为开启iOS 4.0以下版本的ARC而强制将libarclite链接至静态链接库;但是,其使用较为麻烦,不方便发布。
Static Library在生成的静态库时候会加上一个参数-arch_only armv7(使用模拟器时是:-arch_only i386),即使这个库只可用于模拟器或者真实设备,现在貌似暂时没有办法设置其同时支持armv7和i386。
Fake Static Framework:
这个不是一个真正的Framework,实际类型是Core Foundation Bundle,所以叫做Fake Framework。
因为其生成的目标是CFBundle,所以Xcode使用Ld命令生成目标静态库,这样在工程内的Link Binary with Libraries不能有系统的Framework和Library,一旦引入系统的库,Ld命令会将引入库的所有符号内联到当前工程中,当其它工程引用这个静态库的时候就会出现Duplicate symbol define的错误!
基于这个原因,在Deployment Target低于5.0而且开启ARC的时候可能会出现Duplicate symbol define: objc_retainObject()的错误,出现这个错误的原因如下:
1. Fake Static Framework使用Ld命令生成库,而不是使用Libtool生成库,当Framework工程的Deployment Target低于5.0而且开启ARC的时候编译器会向程序写入内存管理方面的代码,而Ld命令会将libarclite库内对应的函数(如objc_retainObject())的定义加入到当前的静态库中。
2. 在引用Framework的工程中,如果Deployment Target低于5.0而且开启ARC,同1道理,Ld命令会向项目内引入libarclite库并将定义加入当前项目,但是由于在引入的Framework中已经包含有相关符号,所以会出现Duplicate symbol define。
解决方案如下:在Fake Static Framework生成的时候将Deployment Target改为5.0或更高,在编写代码的时候将其改回对应版本(因为5.0以下的不支持weak关键字,改回低版本有利于IDE的提示);或者将引用Framework的工程的Deployment Target改为5.0或更高,但是这样则会失去对低版本的支持。
Real Static Framework:
这个是一个真正的Framework,其生成的文件实际类型就是Framework。其内部包含的静态库是由Libtool生成的,所以不存在ARC的问题,而且可以在Link Binary with Libraries中加入系统的Framework,其只会在生成的库中加入对应Framework或Library的引用,而不会将定义也加入其中。
但是,由于苹果的限制,Xcode不支持Real Static Framework直接引用,需要加入两个xcspec文件才可以使用,但是使用这个方式的Framework会将不会存在上述两个静态库的n问题,是现时来说最方便的库
&&相关文章推荐
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:708132次
积分:11256
积分:11256
排名:第1282名
原创:331篇
转载:90篇
评论:85条
文章:15篇
阅读:19201
文章:17篇
阅读:17072
文章:17篇
阅读:66610
(1)(1)(1)(1)(1)(2)(1)(1)(1)(1)(1)(6)(3)(8)(5)(13)(23)(21)(14)(21)(19)(5)(29)(25)(39)(54)(33)(91)1761人阅读
有没有写SDK或者要将一些常用的工具类做成Framework的经历? 你或许自己写脚本完成了这项工作,相信也有很多的人使用 iOS-Universal-Framework ,随着Xcode 6的发布,相信小伙伴们已经都知道了,Xcode 6支持做Framework了. 同时iOS-Universal-Framework开发者也宣布不在继续维持此项目的开发,建议开发者使用Xcode 6制作,目前网上也有很多制作iOS Framework的资料,但大多都不够详细,接下来本文会详情介绍一下在Xcode
6下制作iOS Framework.
关于静态库和动态库的概念,网上资料很多,这里不做叙述,只讲解制作过程。
创建iOS动态库
新建工程并选择默认Target为Cocoa Touch Framework, 如图:
做编码工作,在这里我简单的写了一个Utils的类,并写了一个log方法
设置开放的头文件:Framework中有些类可能是一些私有的辅助工具,不需要使用者看到,在这里只需要把开放出去的类放到Public下, 如图
这样生成的Framework的Headers目录下也只能看到Public的头文件
编码完成之后,直接Run就能成功生成Framework文件了,选择 xCode-&Window-&Organizer-&Projects-&Your Project, 打开工程的Derived Data目录,这样就能找到生成的Framework文件了,如图
新建测试工程,使用生成的Framework
将Framework文件导入到测试工程,调用Framework中的代码
MyUtils&*utils&=&[MyUtils&new];&
[utils&log:@&didFinishLaunchingWithOptions&];
运行报错(Reason: Image Not Found)
为什么会这样的?因为我们做的是动态库,在使用的时候需要额外加一个步骤,要把Framework同时添加到‘Embedded Binaries’中
注意: 在XCode&6之前是没有这个选项的(我没发现),所以理论上XCode 5及之前的版本无法使用Xcode&6下生成的Framework动态库。
到这里,假定你整个过程都是使用的模拟器做的,那看上去会很顺利。这时候尝试将测试工程部署到真机上,问题来了
ld: warning: ignoring file /work/ios/MyFrameworkTest/MyFrameworkTest/MyFramework.framework/MyFramework, file was built for x86_64 which is not the architecture being linked (armv7): /work/ios/MyFrameworkTest/MyFrameworkTest/MyFramework.framework/MyFramework
Undefined symbols for architecture armv7:
& &_OBJC_CLASS_$_MyUtils&, referenced from:
& & & objc-class-ref in AppDelegate.o
ld: symbol(s) not found for architecture armv7
clang: error: linker command failed with exit code 1 (use -v to see invocation)
为什么会这样?错误提示已经很明显了,因为我们制作动态库的时候,选的设备是模拟器,如果选真机的话,那生成的库也只能在真机上使用,那我们该怎样制作一个通用的动态库呢? 简单的方法是分别生成模拟器和真机上运行的库,然后在合并,这个方法,在每次生成动态库的时候,过程都会很繁琐,下面我们用一个脚本来自动完成它。
制作通用动态库
新建Aggregate Target
添加script到新建的Target
#&Sets&the&target&folders&and&the&final&framework&product.
#&如果工程名称和Framework的Target名称不一样的话,要自定义FMKNAME
#&例如:&FMK_NAME&=&&MyFramework&
FMK_NAME=${PROJECT_NAME}
#&Install&dir&will&be&the&final&output&to&the&framework.
#&The&following&line&create&it&in&the&root&folder&of&the&current&project.
INSTALL_DIR=${SRCROOT}/Products/${FMK_NAME}.framework
#&Working&dir&will&be&deleted&after&the&framework&creation.
WRK_DIR=build
DEVICE_DIR=${WRK_DIR}/Release-iphoneos/${FMK_NAME}.framework
SIMULATOR_DIR=${WRK_DIR}/Release-iphonesimulator/${FMK_NAME}.framework
#&-configuration&${CONFIGURATION}
#&Clean&and&Building&both&architectures.
xcodebuild&-configuration&&Release&&-target&&${FMK_NAME}&&-sdk&iphoneos&clean&build
xcodebuild&-configuration&&Release&&-target&&${FMK_NAME}&&-sdk&iphonesimulator&clean&build
#&Cleaning&the&oldest.
if&[&-d&&${INSTALL_DIR}&&]
rm&-rf&&${INSTALL_DIR}&
mkdir&-p&&${INSTALL_DIR}&
cp&-R&&${DEVICE_DIR}/&&&${INSTALL_DIR}/&
#&Uses&the&Lipo&Tool&to&merge&both&binary&files&(i386&+&armv6/armv7)&into&one&Universal&final&product.
lipo&-create&&${DEVICE_DIR}/${FMK_NAME}&&&${SIMULATOR_DIR}/${FMK_NAME}&&-output&&${INSTALL_DIR}/${FMK_NAME}&
rm&-r&&${WRK_DIR}&
open&&${INSTALL_DIR}&
选中新建的Target,Run, 如果没有异常的话,会自动弹出生成的Framework文件
这样生成的动态库就能同时支持模拟器和真机了。
Xcode 6下制作通用静态库
上面我们也提到了,这样生成的动态库恐怕很难在Xcode 5上使用,那我们为什么非要用动态库呢,一般情况下不是用静态库就好了吗? So Easy!只需要修改一个参数即可生成静态库了。
使用静态库的话,就可以把Framework从‘Embedded Binaries’中删除了. 亲测在Xcode&5下可用。把新生成的库导入到测试工程,试试在模拟器和真机上运行,一切OK.
不巧,如果你用的真机是iPhone5 C, 那悲剧又要发成了,生成的Framework竟然不支持armv7s,不知是Xcode&6的bug,还是因为苹果认为使用armv7s的设备太少,可以不支持了.Xcode&新建工程,默认的Architectures竟然不包含armv7s.
想要生成的库支持armv7s,把armv7s添加到Architectures中,重新生成Framework即可
判断一个Framework支持哪些架构
我们该怎么验证生成的Framework支持哪些平台呢,总不能一个个测试吧?当然不用.下面的命令是加上armv7s前后生成的framework的对比
Yearsdembp:Products&Years$&lipo&-info&./MyFramework.framework/MyFramework&
Architectures&in&the&fat&file:&./MyFramework.framework/MyFramework&are:&i386&x86_64&armv7&arm64&
Yearsdembp:Products&Years$&lipo&-info&./MyFramework.framework/MyFramework&
Architectures&in&the&fat&file:&./MyFramework.framework/MyFramework&are:&armv7&armv7s&i386&x86_64&arm64
4、建立一个真机和模拟器通用的framework
首先用finder找到framework所在的位置
然后找到framework中的文件,例如这里的 &Kalagame-library,并且纪录其路径 &os_frame_path
同样方法打开另一个文件夹,纪录其中库的路径,simulator_frame_path
然后打开控制台,输入&lipo -create os_frame_path& simulator_frame_path& -output &newframe
这样就完成了模拟器和真机版本framework的合并,用finder找到这个newframe,然后把newframe改名字(例如这里的Kalagame-library),并放回到framework文件夹中,替换原来的文件。
1. lipo -create /Users/chengdeluo/Library/Developer/Xcode/DerivedData/MyFramework-dkfgbkcpzmnceoenwrpehqyoopof/Build/Products/Debug-iphoneos/MyFramework.framework/MyFramework&
/Users/chengdeluo/Library/Developer/Xcode/DerivedData/MyFramework-dkfgbkcpzmnceoenwrpehqyoopof/Build/Products/Debug-iphonesimulator/MyFramework.framework/MyFramework& -output /Users/chengdeluo/Desktop/newFramework
2. 接下来用finder找到这个newFramework,然后把newframe改名字为:MyFramework ,并放回到framework文件夹中,替换原来的(MyFramework)文件。
使用框架时的各种坑&
1. 如果框架本身要引用到.dylib(动态链接库), (通常会报错: include of non=modular header inside framework 'Hbb_FileFramework.unzip')那么你需要做如下配置:
应用工程需要配置 allows non-modular includes in framework modules 为YES&
2. 如果你的静态frameowrk/静态库(.a)中包含有category文件(如:NSString+StackSymbol.h)
那么你恭喜你要继续配置,就是这么麻烦, 但是没办法
应用工程 project -& target -& build settings -& linker -& other linker flags&
中添加 -force_load&$(SOURCE_ROOT)/UseOfHbb_LogDemo/Hbb_Log.framework/Hbb_Log
注意: 这里是加载框架Hbb_Log.framework里的名为Hbb_Log的文件, 你可以看成框架源代码的打包文件
3. 如果框架工程中警告:&
那么只是叫你把真机和模拟器生成的工程合并起来
4. 如果框架工程中出现declaration of must be imported from module before it is required
或者 duplicate file.. 等编译错误的话, 很可能框架工程本身引用到框架本身, 照成定义重复.
我们这种情况常发生在 在一个工程里, 有2个target, 一个target用来生成静态framework, 另一个则是用来使用这个静态框架, 这个时候如果是使用不当就会出现上述情况.&
解决方法: 将framework所属的类全部拖入framework工程文件夹中, 并在.h和.m选中 framework target, 注意千万不要选择demo target, 一个都不要
在demo中这样使用框架
project -& demo target -& general -& linked frameworks and libraries 加入该静态framework&
2. 编译静态framework, 模拟器和真机都要
3. 在代码中导入要使用的头文件如:
#import&&HbbLogFramework/Hbb_Logger.h&
然后就可以尽情使用了
5. 真机运行前警告:&App installation failed
The application does not have a valid signature.
解决办法:&
处理办法是: project -& target -& Hbb_LogDemo(框架工程) &-& general -& embed binary 删除框架引用
6. 所有操作必须使用clean才能使用, 否则将不准确
7. static 的 framework 不能在访问框架内部的资源文件(也就是bundle文件), 所以如果framework中如果需要使用到资源文件,
那么需要同时创建一个bundle文件, 将资源文件放入其中, 使用时: framework和bundle文件一同拉入工程, 才可以使用.
8. framework的代码本身含有category文件, 并且demo外部也引用了含有category文件的库
连坑不断, 唉, 没办法, 谁叫我是coder呢
project -& target -& Hbb_LogDemo(框架工程) -& build settings -& linking -& other linker flags&
-force_load
$(BUILT_PRODUCTS_DIR)/Hbb_ShareFramework.framework/Hbb_ShareFramework
Hbb_ShareDemo/libWeiboSDK/libWeiboSDK.a
注意: 框架应该排在前面, 顺序不对的话, 在真机上同样没效果的,切记!!
&$(BUILT_PRODUCTS_DIR)是产品框架生成根目录
8.2 如果同时有多个框架需要配置-force_load
那么应该这么写:&
-force_load
Hbb_ShareFramework.framework/Hbb_ShareFramework
ManyFrameworkDemo/libWeiboSDK/libWeiboSDK.a
-force_load
Hbb_LogFramework.framework/Hbb_LogFramework
9.Missing sumodule 'Hbb_LocalDataBaseFramework.HP_FMDBOperator'
解决方案: 所有公开的类 (标识为public), 必须在Hbb_LocalDataBaseFramework.h中导入, 这是这个框架的头文件, 否则就会有这样的警告
10.&dyld: Library not loaded:&& Reason: image not found
dyld: Library not loaded: @rpath/Hbb_LocationFramework.framework/Hbb_LocationFramework
& Referenced from: /private/var/mobile/Containers/Bundle/Application/78571-ECDB-4BC7-B440-AECCF28B20C7/Hbb_LocationDemo.app/Hbb_LocationDemo
& Reason: image not found
证明你创建的是动态的framework, 我们要改成静态的
解决方案: project -& framework target -& build settings -&linking -& Mach-O Type 改为 static
默认是dynamic
11. 引用到libxml2.dylib动态库
框架文件本身要加入libxml2.dylib, 并且还要配置search paths -&header search paths 中加入&/usr/include/libxml2
12. 框架的.h文件中声明多个类interface,&而没有@implementation
这个时候需要为这多个interface声明 &@implementation, 不能直接写.h文件里,&而是需要创建.m文件实现这多个@interface
如: Hbb_IMComm.h
&*&&登陆信息
@interface&Hbb_IMLoginParam :TIMLoginParam
那么就需要创建一个Hbb_IMComm.m文件, 并且在其中编写如下代码:
@implementation&Hbb_IMLoginParam
13.参考自:&真机运行出现&file was built for archive which is not the architecture being linked (armv7s)&报错
原因是在在真机上生成真机自身architecture, 没有生成别的型号的architecture, 比如我在iphone5s上生成了framework, 放在ipad mini上就运行不了
解决方法:
找到项目的Build Settings- & Build Active Architecture Only,将其从NO&设为&YES
14. 声明为public的头文件, 不需要全部导入到xxx_framework.h文件中
&&相关文章推荐
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:43949次
排名:千里之外
原创:24篇
转载:28篇
(2)(1)(1)(1)(8)(2)(2)(1)(2)(2)(1)(1)(6)(3)(10)(3)(4)(3)(1)iOS开发-动态和静态FrameWork - 推酷
iOS开发-动态和静态FrameWork
开发中我们会使用到第三方的SDK,有的时候也会将整个系统的公用的功能的抽象出来成为FrameWork,我们只需要暴露对外的接口,使用者只需要调用接口,对于内部实现的过程不需要维护,可以以 库的形式进行封装,只暴露出头文件。库(FrameWork)是编译好的二进制文件,编译的时候只需要 Link 一下,提高浪费编译时间,库分为 静态库和动态库。
静态库即静态链接库(Windows 下的 .lib,Linux 和 Mac 下的 .a)。之所以叫做静态,是因为静态库在编译的时候会被直接拷贝一份,复制到目标程序里,这段代码在目标程序里就不会再改变了。 静态库的好处很明显,编译完成之后,库文件实际上就没有作用了。目标程序没有外部依赖,直接就可以运行。当然其缺点也很明显,就是会使用目标程序的体积增大。
动态库 动态库即动态链接库(Windows 下的 .dll,Linux 下的 .so,Mac 下的 .dylib)。与静态库相反,动态库在编译时并不会被拷贝到目标程序中,目标程序中只会存储指向动态库的引用。等到程序运行时,动态库才会被真正加载进来。
动态库的优点是,不需要拷贝到目标程序中,不会影响目标程序的体积,而且同一份库可以被多个程序使用(因为这个原因,动态库也被称作 共享库 )。同时,编译时才载入的特性,也可以让我们随时对库进行替换,而不需要重新编译代码。动态库带来的问题主要是,动态载入会带来一部分性能损失,使用动态库也会使得程序依赖于外部环境。如果环境缺少动态库或者库的版本不正确,就会导致程序无法运行(Linux 下喜闻乐见的 lib not found 错误)。
xCode6之后制作动态库相比之前简单很多,xCode7基本上沿袭了xCode6的操作,细节方面有差别。在 iOS 8 之前,iOS 平台不支持使用动态 Framework,开发者可以使用的 Framework 只有苹果基础的 UIKit.Framework,Foundation.Framework 等。 iOS 8/Xcode 6 推出之后,iOS 平台添加了动态库的支持,同时 Xcode 6 也原生自带了 Framework 支持(动态和静态都可以),iOS8多了&Extension ,Extension 和 App 是两个分开的可执行文件,同时需要共享代码,这种情况下动态库的支持就是必不可少的了。但是这种动态 Framework 和系统的 UIKit.Framework 还是有很大区别。系统的 Framework 不需要拷贝到目标程序中,我们自己做出来的 Framework 哪怕是动态的,最后也还是要拷贝到 App 中(App 和 Extension 的 Bundle 是共享的),因此苹果又把这种 Framework 称为Embedded FrameWork.
1.新建动态库File→New→Target→Cocoa Touch FrameWork:
2.项目名称DynamicLibrary,同时我们新建两个测试文件FEUIImage,TestImage:
3.在Dynamic.h中导入头文件:
#import &UIKit/UIKit.h&
//! Project version number for DynamicLibrary.
FOUNDATION_EXPORT double DynamicLibraryVersionN
//! Project version string for DynamicLibrary.
FOUNDATION_EXPORT const unsigned char DynamicLibraryVersionString[];
// In this header, you should import all the public headers of your framework using statements like #import &DynamicLibrary/PublicHeader.h&
#import &DynamicLibrary/FEUIImage.h&
4.将FEUIImage和TestImage设置为Public供外部访问:
5.cmb+b编译项目,编辑成功之后将项目移动到项目中进行测试:
6.通过FEDevice项目找到编译之后的DynamicLibrary.framwork文件
通用动态库
我们将上面的DynamicLibrary.framework移动的其他项目中是可以直接使用的,但是运行的时候会出错, &错误信息如下:
Undefined symbols for architecture x86_64:
&_OBJC_CLASS_$_FEUIImage&, referenced from:
objc-class-ref in ViewController.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
错误信息跟动态的指令集和目标项目的指令集版本有关系,我们可以简单的了解下Achitectures和设备之间的关系,iPhone一直以来都是Arm处理器,Arm是处理器是移动设备上占用率最大的处理器。 在iOS模拟器上运行的是x86指令集,只有在真机上才会执行arm指令集,每个指令集对应不同的机型设置:
都是arm处理器的指令集。通常指令是向下兼容的。在模拟器运行时,iOS模拟器运行的是x86指令集。只有在真机上,才会对执行arm指令集。
armv6:iPhone,iPhone 2G/3G,iPod 1G/2G,xCode4.5已经不支持armv6指令集;
armv7 :iPhone 3GS,iPhone4,iPhone 4s,iPad,iPad2,iPad3(The New iPad),iPad mini,iPod Touch 3G,iPod Touch4,由于iPhone4s的占有率,目前是指令集的最低版本;
armv7s:iPhone5, iPhone5C,iPad4和iPod5;
arm64:iPhone5s,iPhone6,iPhone6 Plus,iPad Air,iPad mini2(iPad mini with Retina Display),iPhone6s,iPhone6s Plus
我们可以通过lipo命令查看发现i386是mac版指令集:
lipo -info DynamicLibrary.framework/DynamicLibrary
Non-fat file: DynamicLibrary.framework/DynamicLibrary is architecture: i386
1.如果用真机调试的话,同样会发生程序错误,所以需要将同样的代码同时支持模拟器和真机,两份库聚合一下,回到DynamicLibrary.frameWork项目,通过File→New→Target→Other→Aggregate:
2.执行编译脚本地址,先选中DynamicLibrary-Universal,添加脚本地址:
/${PROJECT_DIR}/DynamicLibrary/ios-framework-universal-script.sh
3.设置脚本内容,同时设置DynamicLibrary-Universal的依赖项(Target Dependencies)为DynamicLibrary:
ios-build-framework-script.sh
DynamicLibrary 博客园-FlyElephant
博客园:/xiaofeixiang/
Created by keso on 16/1/17.
Copyright & 2016年 FlyElephant. All rights reserved.
### Avoid recursively calling this script.
if [[ $UF_MASTER_SCRIPT_RUNNING ]]
export UF_MASTER_SCRIPT_RUNNING=1
### Constants.
UF_TARGET_NAME=${PROJECT_NAME}
FRAMEWORK_VERSION=&A&
UNIVERSAL_OUTPUTFOLDER=${BUILD_DIR}/${CONFIGURATION}-universal
IPHONE_DEVICE_BUILD_DIR=${BUILD_DIR}/${CONFIGURATION}-iphoneos
IPHONE_SIMULATOR_BUILD_DIR=${BUILD_DIR}/${CONFIGURATION}-iphonesimulator
### Functions
## List files in the specified directory, storing to the specified array.
# @param $1 The path to list
# @param $2 The name of the array to fill
list_files ()
filelist=$(ls &$1&)
while read line
eval &$2[\${#$2[*]}]=\&\$line\&&
done &&& &$filelist&
### Take build target.
if [[ &$SDK_NAME& =~ ([A-Za-z]+) ]]
SF_SDK_PLATFORM=${BASH_REMATCH[1]} # &iphoneos& or &iphonesimulator&.
echo &Could not find platform name from SDK_NAME: $SDK_NAME&
### Build simulator platform. (i386, x86_64)
echo &========== Build Simulator Platform ==========&
echo &===== Build Simulator Platform: i386 =====&
xcodebuild -project &${PROJECT_FILE_PATH}& -target &${TARGET_NAME}& -configuration &${CONFIGURATION}& -sdk iphonesimulator BUILD_DIR=&${BUILD_DIR}& OBJROOT=&${OBJROOT}& BUILD_ROOT=&${BUILD_ROOT}& CONFIGURATION_BUILD_DIR=&${IPHONE_SIMULATOR_BUILD_DIR}/i386& SYMROOT=&${SYMROOT}& ARCHS='i386' VALID_ARCHS='i386' $ACTION
echo &===== Build Simulator Platform: x86_64 =====&
xcodebuild -project &${PROJECT_FILE_PATH}& -target &${TARGET_NAME}& -configuration &${CONFIGURATION}& -sdk iphonesimulator BUILD_DIR=&${BUILD_DIR}& OBJROOT=&${OBJROOT}& BUILD_ROOT=&${BUILD_ROOT}& CONFIGURATION_BUILD_DIR=&${IPHONE_SIMULATOR_BUILD_DIR}/x86_64& SYMROOT=&${SYMROOT}& ARCHS='x86_64' VALID_ARCHS='x86_64' $ACTION
### Build device platform. (armv7, arm64)
echo &========== Build Device Platform ==========&
echo &===== Build Device Platform: armv7 =====&
xcodebuild -project &${PROJECT_FILE_PATH}& -target &${TARGET_NAME}& -configuration &${CONFIGURATION}& -sdk iphoneos BUILD_DIR=&${BUILD_DIR}& OBJROOT=&${OBJROOT}& BUILD_ROOT=&${BUILD_ROOT}&
CONFIGURATION_BUILD_DIR=&${IPHONE_DEVICE_BUILD_DIR}/armv7& SYMROOT=&${SYMROOT}& ARCHS='armv7 armv7s' VALID_ARCHS='armv7 armv7s' $ACTION
echo &===== Build Device Platform: arm64 =====&
xcodebuild -project &${PROJECT_FILE_PATH}& -target &${TARGET_NAME}& -configuration &${CONFIGURATION}& -sdk iphoneos BUILD_DIR=&${BUILD_DIR}& OBJROOT=&${OBJROOT}& BUILD_ROOT=&${BUILD_ROOT}& CONFIGURATION_BUILD_DIR=&${IPHONE_DEVICE_BUILD_DIR}/arm64& SYMROOT=&${SYMROOT}& ARCHS='arm64' VALID_ARCHS='arm64' $ACTION
### Build device platform. (arm64, armv7)
echo &========== Build Universal Platform ==========&
## Copy the framework structure to the universal folder (clean it first).
rm -rf &${UNIVERSAL_OUTPUTFOLDER}&
mkdir -p &${UNIVERSAL_OUTPUTFOLDER}&
## Copy the last product files of xcodebuild command.
cp -R &${IPHONE_DEVICE_BUILD_DIR}/arm64/${PROJECT_NAME}.framework& &${UNIVERSAL_OUTPUTFOLDER}/${PROJECT_NAME}.framework&
### Smash them together to combine all architectures.
lipo -create
&${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/i386/${PROJECT_NAME}.framework/${PROJECT_NAME}& &${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/x86_64/${PROJECT_NAME}.framework/${PROJECT_NAME}& &${BUILD_DIR}/${CONFIGURATION}-iphoneos/armv7/${PROJECT_NAME}.framework/${PROJECT_NAME}& &${BUILD_DIR}/${CONFIGURATION}-iphoneos/arm64/${PROJECT_NAME}.framework/${PROJECT_NAME}& -output &${UNIVERSAL_OUTPUTFOLDER}/${PROJECT_NAME}.framework/${PROJECT_NAME}&
### Create standard structure for framework.
# If we don't have &Info.plist -& Versions/Current/Resources/Info.plist&, we may get error when use this framework.
# MyFramework.framework
# |-- MyFramework -& Versions/Current/MyFramework
# |-- Headers -& Versions/Current/Headers
# |-- Resources -& Versions/Current/Resources
# |-- Info.plist -& Versions/Current/Resources/Info.plist
# `-- Versions
|-- MyFramework
|-- Headers
`-- MyFramework.h
`-- Resources
|-- Info.plist
|-- MyViewController.nib
`-- en.lproj
`-- InfoPlist.strings
`-- Current -& A
echo &========== Create Standard Structure ==========&
mkdir -p &${UNIVERSAL_OUTPUTFOLDER}/${PROJECT_NAME}.framework/Versions/${FRAMEWORK_VERSION}/&
mv &${UNIVERSAL_OUTPUTFOLDER}/${PROJECT_NAME}.framework/${PROJECT_NAME}& &${UNIVERSAL_OUTPUTFOLDER}/${PROJECT_NAME}.framework/Versions/${FRAMEWORK_VERSION}/&
mv &${UNIVERSAL_OUTPUTFOLDER}/${PROJECT_NAME}.framework/Headers& &${UNIVERSAL_OUTPUTFOLDER}/${PROJECT_NAME}.framework/Versions/${FRAMEWORK_VERSION}/&
mkdir -p &${UNIVERSAL_OUTPUTFOLDER}/${PROJECT_NAME}.framework/Resources&
declare -a UF_FILE_LIST
list_files &${UNIVERSAL_OUTPUTFOLDER}/${PROJECT_NAME}.framework/& UF_FILE_LIST
for file_name in &${UF_FILE_LIST[@]}&
if [[ &${file_name}& == &Info.plist& ]] || [[ &${file_name}& =~ .*\.lproj$ ]]
mv &${UNIVERSAL_OUTPUTFOLDER}/${PROJECT_NAME}.framework/${file_name}& &${UNIVERSAL_OUTPUTFOLDER}/${PROJECT_NAME}.framework/Resources/&
mv &${UNIVERSAL_OUTPUTFOLDER}/${PROJECT_NAME}.framework/Resources& &${UNIVERSAL_OUTPUTFOLDER}/${PROJECT_NAME}.framework/Versions/${FRAMEWORK_VERSION}/&
ln -sfh &Versions/Current/Resources/Info.plist& &${UNIVERSAL_OUTPUTFOLDER}/${PROJECT_NAME}.framework/Info.plist&
ln -sfh &${FRAMEWORK_VERSION}& &${UNIVERSAL_OUTPUTFOLDER}/${PROJECT_NAME}.framework/Versions/Current&
ln -sfh &Versions/Current/${PROJECT_NAME}& &${UNIVERSAL_OUTPUTFOLDER}/${PROJECT_NAME}.framework/${PROJECT_NAME}&
ln -sfh &Versions/Current/Headers& &${UNIVERSAL_OUTPUTFOLDER}/${PROJECT_NAME}.framework/Headers&
ln -sfh &Versions/Current/Resources& &${UNIVERSAL_OUTPUTFOLDER}/${PROJECT_NAME}.framework/Resources&
### Open the universal folder.
open &${UNIVERSAL_OUTPUTFOLDER}&
上面的脚本内容在脚本执行的过程中,会依次编译出支持 i386、x86_64、arm64、armv7、armv7s 的包,然后把各个包中的库文件通过 lipo 工具合并为一个支持各平台的通用库文件,再基于最后一个 xcodebuild 命令打出的包的结构(arm64/DynamicLibrary.framework)和这个通用库文件生成一个支持各个平台的通用 Framwork;最后编译之后会弹出framework的位置:
4.设置了通用库之后,还需要在Genral下Embedded Binaries添加一下动态库:
动态 Framework 是开发中优先考虑的代码打包方式,但是为了兼容一些低版本系统对动态库的限制,我们需要打包静态库来使用,实现起来比较简单,在原有的DynamicLibrary项目 &Build Settings 下设置 Mach-O Type 值为 Static Library,可以编译出静态库。
设置为静态库之后动态库的最后一步Embedded Binaries就不用再添加了,如果已经添加建议删除~
已发表评论数()
请填写推刊名
描述不能大于100个字符!
权限设置: 公开
仅自己可见
正文不准确
标题不准确
排版有问题
主题不准确
没有分页内容
图片无法显示
视频无法显示
与原文不一致}

我要回帖

更多关于 load dynamic library 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信