×

如何打包静态库文件

96
大亮baby
2016.07.05 09:42* 字数 2854

原文链接
如何打包静态库文件为iOS?</br></br>

在之前的辅导中,你学习了如何循环利用knob control,但是,如何让别的开发开发者简单的重复利用它并没有讲O</br></br>

一种方式是直接分享源码,然而这样不是很优雅,有一些实现细节你并不想分享出来,而且,开发者也许并不想看到什么东西,因为它们只是想你的代码和她的代码融为一体。</br>

另外的方式是将你的代码编译为静态库,然后将静态库添加到工程中,这样的要求你分发公共头文件当你用到的时候。</br>

你需要一个简单的方法编译代码,然后他需要各个工程之间重复利用,你需要的是以后将头文件和静态库组合起来,这样你就可以把它添加到项目中迅速使用了。</br>
这个辅导就是专注这个这个事情,你将学习通过用framework帮助你解决这个具体的问题,os x系统对这个已经有了很好的支持,因为
xcode 提供一个模版,这个模版包括默认的build target,模版也可以包括下面的文件图片,声音,字体,你可以创建创建 framework为iOS,但是他有点复杂,如果你继续学习的如何绕过这些坑。</br>
当你继续往下学习,你会创建创建一个静态库项目用xcode,创建一个app依赖这静态库,初次学习怎么将一个静态库文件转化为一个羽翼丰满的framework,最后你会学习怎么打包一些图片在你的framework的resource bundle中</br>
</br>这次讲解主要目的在于解释如何创建framework,因此不像这个站点的别的教程,整篇教程只有很少量的Objective-C 代码,这里主要是示范一下我们之前讲的。</br>
这里下载RWKnobControl代码开始,当你看完了创建framework的过程,你会知道怎么用它。</br></br>
所有的代码,做这个项目的工程文件Github上都有,和别的教程的代码分开提交的。
一个framework是一堆资源,他将一个静态库和她的头文件转化为Xcode易于导入的你的工程的结构。</br>
在osx上,可以创建链接framework,通过动态链接,framework 可以被更新不用应用重新链接它们,在runtime中,一个单一的library代码被整个进程共享,这样减少了内存的使用提高了系统难过的表现,像你看到的一样,这是个有用的东西。</br></br>
在iOS中,你不能通过这种方式添加动态可以到系统中,只有苹果提供的framework可以动态链接。</br></br>
然而这样并不意味着rameworks和iOS没有关系的,为了在不同的app中使用静态链接framework静态的包裹代码仍然是一种方便的方式。</br></br>
由于一个framework是一个一站式的工厂对于一个静态库来说,这篇教程的第一件事情就是创建和适应静态库,当教程讲到创建一个framework的时候,你就知道是怎么回事了,不会再云里雾里了。
打开Xcode创建一个新的静态库文件通过点击File\New\Project,然后选择iOS\Framework,再选择Library\Cocoa Touch Static Library。

图片
图片
</br></br>
Name the product RWUIControls and save the project to an empty directory.</br>
命名为RWUIControls然后将项目保存到一个空的文件夹</br></br>
</br></br>
A static library project is made up of header files and implementation files, which are compiled to make the library itself.</br>
一个静态库工程主要有头文件和实现文件组成,实现文件被编译成静态库文件。</br></br>
为了让别的开发者用起来更简单,你将让她最终只要导入一个头文件就可以使用到你想要公开的所有类。</br></br>
当创建静态库项目的时候,Xcode添加RWUIControls.h 和RWUIControls.m,你不需要去实现这些文件,所以右击RWUIControls.m选择删除,把他拖到垃圾箱中。</br></br>
Open up RWUIControls.h and replace the contents with the following:</br>
打开RWUIControls.h然后将内容替换为下面的:</br></br>

#import <UIKit/UIKit.h>

这个导入UIKit的头文件,这个头文件是库自己需要的,当你创建
不同的类的时,你将要这些头文件添加到这个文件中,这样才能确保他们库文件的使用者可以使用。</br></br>
这个工程你将要创建的依赖于 UIKit,但是Xcode并不会默认去链接,为了修复这个问题,添加UIKit作为依赖,选择工程在导航栏,在中心的位置,选择RWUIControls target
</br></br>
点击Build Phases然后增加Link Binary with选项,点击加号添加新的framework,在点击添加之前你要还找到UIKit.</br></br>


</br></br>
一个静态库不可用,除非和头文件结合在一起,头文件是在binary中有什么类和方法的清单。</br></br>
接着你需要在运行添加一个新的阶段,他将会收集公开的头文件,然后把他放在编译器能拿到的地方,最后,你将会拷贝这些到framework</br></br>
当仍然在看着Build Phases,选择Editor\Add Build Phase,然后再选择Add Copy Headers Build Phase。
注意点:如果你发现那个位置选项是灰色的,试试点击已经存在的
build phases下面的空白区域,然后再试试</br></br>


</br></br>
拖拽RWUIControls.h从导航栏的位置到到 Copy Headers中,这将会保证头文件对于用你库的人来说可用。</br>
</br></br>
注意:这个似乎是很显然的,但是很重要在你的公共的头文件中被include的所有文件应该被公开,要不然,开发者尝试用你的库的时候就会编译出错。当Xcode读公开的头文件然后发现一些头文件没有公开,这样对于谁都是不好的。`应该是在头文件又include也应该暴露出来,说的应该是这个意思,翻译尝试一下,mark`</br></br>
现在你已经创建了你的工程,是时候去添加功能到库里了,由于这篇教程重点是描述怎么创建一个framework,而不是怎么创建一个ui control,你将会借用上一篇教程的代码,在你之前下载的zip文件中你会发现一个RWKnobControl文件夹,将他拖拽到RWUIControls项目中。</br></br>

</br></br>
选择copy items 到目标文件夹中,在合适的位置打上勾确保新的文件被添加到新的文件被添加到目标库中</br></br>


</br></br>
这样操作会将实现文件放在编译列表中,默认的会将头文件驾到Project group选项中,这样意味着它们是私有的。 </br></br>
</br></br>
注意:当你出问题的时候你会对这三个列表的疑惑的,Public 和你想的一样,Private headers仍然是暴露的,这个有一点小小误导,Project headers 一些特殊的文件对你的项目来说。然而你往往更多的发现你的头文件要么在Public组或者 Project groups中。</br></br>
现在你需要暴露control主头文件,RWKnobControl.h,有几种方式做这件事,第一种方式拖拽文件从the Project 分组到the Public在 Copy选项卡中。</br></br>
</br></br>
或者,你可以在编辑这个文件时改变membership在Target Membership选项卡中,当你要继续要添加或者开发库时会更方便。</br></br>
</br></br>
注意:当你继续添加新的类文件到库中时,记得更新它们的membership,尽量让他们头文件在public越少越好,确保剩余的部分在 Project group中。</br></br>
对你的control头文件另外一件事情是要把它添加到库的主头文件中,当开发者使用的时候只需要包含下面你看到的头文件就可以了,而不需要整理他们需要的各个头文件。
#import <RWUIControls/RWUIControls.h>

Therefore, add the following to RWUIControls.h:</br>
然后,添加下面到RWUIControls.h中</br>

// Knob Control
#import <RWUIControls/RWKnobControl.h>

Configuring Build Settings(配置Build Settings)

你现在非常快到了创建项目把它配置,然后创建为静态库,然而需要一系列的配置去保证静态库的使用者方便使用。</br></br>
第一件是你需要提供一个字典以你将要copy的公共头文件命名,这个将确保你在使用头文件的时候找到头文件的准确位置。</br></br>
在项目导航栏点击项目,然后选择RWUIControls static library target,选择Build Settings选项,然后搜索 public header,在Public Headers Folder Path 双击,在后面弹出框中写下面的东东。</br></br>


</br></br>
You’ll see this directory later.</br>
然后你会看到字典</br></br>
现在你需要改变一些别的设置,特别是编译成二进制的库文件,编译器给你删除那些你永远不会用的代码的机会。你也可以是debug的符号,方法名字,和别的和debug相关的信息。</br></br>
由于你正在创建一个给别人用的framework,最好的方式是禁用两者,然后让使用者决定那个是最好的对于项目,为了做这些,像之前那样使用search field,更新下面的设置。</br></br>
build然后运行,并没有看到更多的,然而项目文件仍然运行的非常好没有任何警告和错误。</br>
为了build,选择target为iOS设备然后按下cmd+B执行编译,一旦完成,libRWUIControls.a在Project Navigator中的就会从红色变成黑色,标志他已经存在,�右击libRWUIControls.a,然后show in finder 。</br></br>


</br></br>
在这个文件夹中你可以看到静态库在文件夹中,那个文件夹你指定为公共的头文件,包括RWUIControls,注意你设定的在public可以在这里看到,和你期望的一样。</br></br>

Creating a Dependent Development Project(创建一个独立的项目)

为iOS开发一个UI控件库是极为困难的当你不能真正看到你在做什么,,这似乎是现在的情况。</br></br>
没有人想让你盲目工作,你将会选择创建一个依赖于之前库文件的新的项目。用例子的app将让你能够开发一个framework。事实上,这个app的代码会和库文件完全分开,这将会有一个更清晰的结构。</br></br>
关闭静态库项目,然后创建新的项目通过File/New/Project,然后创建Single View Application,新的项目命名为UIControlDevApp,设置类前缀为RW ,然后只是用于iphone,最后把项目保存在你用于RWUIControls相同的文件夹。</br></br>
把RWUIControls.xcodeproj从finder中拖到UIControlDevApp 作为依赖的库文件。</br></br>


</br></br>
现在你可以从应用程序的项目浏览静态库项目,它意味着你可以在库中编辑代码,并运行示例应用程序来测试更改,这样很完美。</br></br>
注意:你不可以一个工程在两个不同的窗口打开。如果你发现你无法浏览库文件,要去检查你没有另一个Xcode窗口打开。</br></br>
并不是重新创建应用程序从上一个教程,你可以简单地复制代码。首先,选择main.storyboard,RWViewController.h和RWViewController.m通过右键单击并选择“删除”删除它们,然后选择要移动到trash。然后从你下载的压缩文件 复制devapp文件夹,然后在Xcode将要用到的文件拖到UIControlDevApp group。</br></br>


</br></br>
Now you’re going to add the static library as a build dependency of the example app:</br>
现在你将把静态库文件作为示例app的依赖。</br></br>
在Project Navigator选择UIControlDevApp project。
</br></br>找到UIControlDevApp target的Build Phases选择框。</br></br>

选择Target Dependencies并点击加号显示选项。</br></br>
找到RWUIControls静态库选择并添加,这样一个动作意味这当编译 dev app时Xcode会重新检查静态库文件是否需要重新编译。</br></br>
为了链接到静态库本身,请使用“库”面板扩展 Link Binary,然后再次单击“+”。从工作区组选择libRWUIControls.a然后单击“添加.</br></br>
This action makes it so that Xcode will link it against the static library, just as it links against system frameworks like UIKit.</br></br>
这一行为使得让Xcode将项目与静态库就像和链接系统的UIKit这样的frameworks 一样链接起来。</br></br>


</br></br>
Build and run to see it in action. If you followed the previous tutorial on building a knob control, you’ll recognize the simple app before your eyes.</br></br>
编译和运行,如果你跟随之前的building a knob control教程,有一个简单的app出现在你的面前。</br></br>
</br></br>
使用嵌套的项目,这样做的好处是,你可以继续搞你的库文件,也样也从来没有离开示例应用程序的项目,即使你保持在不同的地方的代码。每次生成项目时,你也检查你有公共/项目成员头设置正确。如果缺少任何必需的标头中的示例应用程序将无法建立。

Building a Framework

你可能会不耐烦地敲击你的脚趾,并想知道framework从哪里来。可以理解,因为到目前为止,你已经做了很多工作,但也看不到framework。</br></br>
好了,事情将会很快改变了。您还没有创建了一个框架的原因是因为框架几乎是一个静态库和头文件的集合 - 到目前为止,你已经创建了这么多。</br></br>
有一些事情让framework显得不同。</br></br>
文件夹目录结构。框架具有由Xcode中识别的特殊文件夹结构。您将创建一个构建任务,这个构建任务会为你创建这些结构。</br></br>
The Slices。目前,当你构建库,这只是对当前所需的cpu体系结构,即I386 ,ARM7等。为了一个框架是有用的,它需要包括建立对所有在其上需要运行架构。您将创建一个新的product,这将建立所需的所有架构,并将其放置在框架。</br></br>
这一部分将会有出现很多脚本魔力,但是我们进行的很慢,原没有看起来那么复杂</br></br>

Framework Structure

像前面提到的一样,一个framework有一些特殊的结构像下面这样</br></br>


</br></br>
现在,您将添加一个脚本会在静态库构建过程中创建这样的文件夹结构。选择在Project Navigator的RWUIControls项目,并选择RWUIControls静态库的目标。选择 Build Phases选项卡,然后选择编辑器中添加一个新的脚本 Editor/Add Build Phase/Add Run Script Build Phase.</br></br>


</br></br>
这会在build phases创建一个新的面板,新的面板允许你在构建过程中运行在某个时刻任意Bash脚本。如果你想改变该脚本在构建过程中运行的时间,可以拖动面板在列表位置。对于framework项目,上运行脚本在最后,所以你可以把它放在默认位置。</br></br>

通过双击脚本重命名面板标题,将它换成Build Framework。</br></br>
粘贴下面的Bash脚本到script field</br></br>

set -e

export FRAMEWORK_LOCN="${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.framework"

# Create the path to the real Headers die
mkdir -p "${FRAMEWORK_LOCN}/Versions/A/Headers"

# Create the required symlinks
/bin/ln -sfh A "${FRAMEWORK_LOCN}/Versions/Current"
/bin/ln -sfh Versions/Current/Headers "${FRAMEWORK_LOCN}/Headers"
/bin/ln -sfh "Versions/Current/${PRODUCT_NAME}" \
             "${FRAMEWORK_LOCN}/${PRODUCT_NAME}"

# Copy the public headers into the framework
/bin/cp -a "${TARGET_BUILD_DIR}/${PUBLIC_HEADERS_FOLDER_PATH}/" \
           "${FRAMEWORK_LOCN}/Versions/A/Headers"
           ```
这个脚本首先创建RWUIControls.framework /版本/ A /头目录,然后创建一个框架所需的三个symbolic links.
- Versions/Current => A
- Headers => Versions/Current/Headers
- RWUIControls => Versions/Current/RWUIControls</br></br>
最后,公共头文件复制到从你前面指定位置到Versions/A/Headers目录下。 -a参数保证了修改时间不更改作为复制的一部分,从而防止不必要的重建</br></br>
现在,选择RWUIControls静态库scheme和iOS设备编译,然后使用CMD + B 。</br></br>
![](http://upload-images.jianshu.io/upload_images/2268803-4e85585f54677bb5.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)</br></br>
右键选择该RWUIControls项目中libRWUIControls.a静态库,并再次选择在Finder中显示。</br></br>
![](https://cdn2.raywenderlich.com/wp-content/uploads/2014/02/ios_framework_static_lib_view_in_finder.png)</br></br>
此编译文件夹目录下,你可以访问RWUIControls.framework ,并确认目录结构存在并且正确。</br></br>
![](https://cdn5.raywenderlich.com/wp-content/uploads/2014/02/ios_framework_created_framework_directory_structure-700x366.png)</br></br>
这是在完成框架的路径上的一次飞跃,但你会发现,没有一个静态库在那里。这就是你要下一个进行的地方。
###Multi-Architecture Build
iOS应用程序需要在许多不同的架构上运行:
</br></br>用在最老的iOS 7支持的设备</br></br>
在iPhone 5和5C使用
</br></br> 对于iPhone 5S的64位ARM处理器
- i386: For the 32-bit simulator</br></br>
为32位的模拟器
- x86_64: Used in 64-bit simulator</br></br>
适用于64位模拟器</br></br>
每种架构都需要不同的binary文件,当你创建一个应用程序时,Xcode将建立与你当前架构相适应正确运行的binary文件。例如,如果你要求它在模拟器中运行,那么它只会建立i386版本(或x86_64 64位)。
这意味着创建可以很快的。当你archive应用程序或运行程序在release状态下,那么的Xcode将建立三个ARM体系结构,从而使应用在大多数设备上运行。那另外的创建呢?</br></br>
当然,当你建立你的框架,你会希望开发人员能够使用它的所有可能的架构,对不对?当然,你这样做,因为这将意味着你可以赢取你的同行的尊重和敬佩。</br></br>
因此,你需要做的是让Xcode构建五个架构。然后创建一个包含所有架构的臃肿的库文件,啊哈!</br></br>
注:这其实显现创建一个静态库的依赖关系的示例应用程序的另一个原因:该库只建立由示例应用程序所需的架构,如果有新的变化只需要重新build。这是为什么你兴奋?这意味着开发周期尽可能快。```
该框架将在RWUIControls项目中使用新的target来创建。要创建它,选择在Project Navigator的RWUIControls项目,然后点击下面的Add Target 。</br></br>
![](https://cdn4.raywenderlich.com/wp-content/uploads/2014/02/ios_framework_add_target_button.png)</br></br>
Navigate to iOS/Other/Aggregate, click Next and name the target Framework.</br></br>
![](https://cdn1.raywenderlich.com/wp-content/uploads/2014/02/ios_framework_select_aggregate_target.png)</br></br>
Note:为什么使用集合(Aggregate)目标来创建一个framework呢?为什么这么不直接?因为OS X对库的支持更好一些,事实上,Xcode直接为每一个OS X工程提供一个Cocoa Framework编译目标。基于此,你将使用集合编译目标,作为Bash脚本的连接串来创建神奇的framework目录结构。你是不是开始觉得这里的方法有些愚蠢了?</br></br>
为了确保每当这个新的framework目标被创建时,静态链接库都会被编译,你需要往静态库目标中添加依赖(Dependency)。在库工程中选择Framework目标,在Build Phases中添加一个依赖。展开Target Dependencies面板,点击 + 按钮选择RWUIControls静态库。</br></br>
![](http://upload-images.jianshu.io/upload_images/2268803-0325b17c69b5e46d.gif?imageMogr2/auto-orient/strip)</br></br>
这个目标的主要编译部分是多平台编译,你将使用一个脚本来做到这一点。和你之前做的一样,在Framework目标下,选择Build Phases栏,点击Editor/Add Build Phase/Add Run Script Build Phase,创建一个新的Run Script Build Phase。</br></br>
![](http://upload-images.jianshu.io/upload_images/2268803-56036e594459eb27.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)</br></br>
双击Run Script,重命名脚本的名字。这次命名为MultiPlatform Build。

在脚本文本框中粘贴下面的Bash脚本代码:</br></br>
          set -e
        # If we're already inside this script then die
        if [ -n "$RW_MULTIPLATFORM_BUILD_IN_PROGRESS" ]; then
          exit 0
        fi
        export RW_MULTIPLATFORM_BUILD_IN_PROGRESS=1

        RW_FRAMEWORK_NAME=${PROJECT_NAME}
        RW_INPUT_STATIC_LIB="lib${PROJECT_NAME}.a"
        RW_FRAMEWORK_LOCATION="${BUILT_PRODUCTS_DIR}/${RW_FRAMEWORK_NAME}.framework"
-  set –e确保脚本的任何地方执行失败,则整个脚本都执行失败。这样可以避免让你创建一个部分有效的framework
- 接着,用RW_MULTIPLATFORM_BUILD_IN_PROGRESS变量决定是否循环调用脚本,如果有该变量,则退出。
- 然后设定一些变量。该framework的名字与项目的名字一样。也就是RWUIControls,另外,静态lib的名字是libRWUIControls.a。
接下来,用脚本设置一些函数,这些函数一会项目就会用到,把下面的代码加到脚本的底部。</br></br>
        function build_static_library {
            # Will rebuild the static library as specified
            #     build_static_library sdk
            xcrun xcodebuild -project "${PROJECT_FILE_PATH}" \
                             -target "${TARGET_NAME}" \
                             -configuration "${CONFIGURATION}" \
                             -sdk "${1}" \
                             ONLY_ACTIVE_ARCH=NO \
                             BUILD_DIR="${BUILD_DIR}" \
                             OBJROOT="${OBJROOT}" \
                             BUILD_ROOT="${BUILD_ROOT}" \
                             SYMROOT="${SYMROOT}" $ACTION
        }

        function make_fat_library {
            # Will smash 2 static libs together
            #     make_fat_library in1 in2 out
            xcrun lipo -create "${1}" "${2}" -output "${3}"
        }

- build_static_library把SDK作为参数,例如iPhone7.0,然后创建静态lib,大多数参数直接传到当前的构建工作中来,不同的是设置ONLY_ACTIVE_ARCH来确保为当前SDK构建所有的结构
- make_fat_library使用lipo将两个静态库合并为一个,其参数为两个静态库和结果的输出位置。从这里了解更多关于lipo的知识。
为了使用这两个方法,接下来脚本将定义更多你要用到的变量,你需要知道其他SDK是什么,例如,iphoneos7.0应该对应iphonesimulator7.0,反过来也一样。你也需要找到该SDK对应的编译目录。</br></br>
把下面的代码添加到脚本的底部。
        # 1 - Extract the platform (iphoneos/iphonesimulator) from the SDK name
        if [[ "$SDK_NAME" =~ ([A-Za-z]+) ]]; then
          RW_SDK_PLATFORM=${BASH_REMATCH[1]}
        else
          echo "Could not find platform name from SDK_NAME: $SDK_NAME"
          exit 1
        fi

        # 2 - Extract the version from the SDK
        if [[ "$SDK_NAME" =~ ([0-9]+.*$) ]]; then
          RW_SDK_VERSION=${BASH_REMATCH[1]}
        else
          echo "Could not find sdk version from SDK_NAME: $SDK_NAME"
          exit 1
        fi

        # 3 - Determine the other platform
        if [ "$RW_SDK_PLATFORM" == "iphoneos" ]; then
          RW_OTHER_PLATFORM=iphonesimulator
        else
          RW_OTHER_PLATFORM=iphoneos
        fi

        # 4 - Find the build directory
        if [[ "$BUILT_PRODUCTS_DIR" =~ (.*)$RW_SDK_PLATFORM$ ]]; then
          RW_OTHER_BUILT_PRODUCTS_DIR="${BASH_REMATCH[1]}${RW_OTHER_PLATFORM}"
        else
          echo "Could not find other platform build directory."
          exit 1
        fi
All four of these statements are very similar, they use string comparison and regular expressions to determine RW_OTHER_PLATFORM and RW_OTHER_BUILT_PRODUCTS_DIR.</br></br>
The four if statements in more detail:
上面四句声明都非常相似,都是使用字符串比较和正则表达式来确定RW_OTHER_PLATFORM和RW_OTHER_BUILT_PRODUCTS_DIR。</br></br>
The four if statements in more detail:</br></br>
1.SDK_NAME将指代iphoneos7.0和iphonesimulator6.1,这个正则表达式取出字符串开头不包含数字的那些字符,因此,其结果是iphoneos 或 iphonesimulator</br></br>
2.这个正则表达式取出SDK_NAME中表示版本用的数字,7.0或6.1等。
3.这里用简单的字符串比较来将iphonesimulator 转换为iphoneos,反过来也一样。</br></br>
4.从构建好的工程的目录路径的末尾找出平台名称,将其替换为其他平台。这样可以确保为其他平台构建的目录可以被找到。这是将两个静态库合并的关键部分。</br></br>
现在你可以启动脚本为其他平台编译,然后得到合并两静态库的结果。</br></br>
在脚本最后添加下面的代码:
        # Build the other platform.
        build_static_library "${RW_OTHER_PLATFORM}${RW_SDK_VERSION}"

        # If we're currently building for iphonesimulator, then need to rebuild
        #   to ensure that we get both i386 and x86_64
        if [ "$RW_SDK_PLATFORM" == "iphonesimulator" ]; then
            build_static_library "${SDK_NAME}"
        fi

        # Join the 2 static libs into 1 and push into the .framework
        make_fat_library "${BUILT_PRODUCTS_DIR}/${RW_INPUT_STATIC_LIB}" \
                         "${RW_OTHER_BUILT_PRODUCTS_DIR}/${RW_INPUT_STATIC_LIB}" \
                         "${RW_FRAMEWORK_LOCATION}/Versions/A/${RW_FRAMEWORK_NAME}"
首先,调用你之前定义好的函数为其他平台编译</br></br>
如果你现在正在为模拟器编译,那么Xcode会默认只在该系统对应的结构下编译,例如i386 或 x86_64。为了在这两个结构下都进行编译,这里调用了build_static_library,基于iphonesimulator SDK重新编译,确保这两个结构都进行了编译。
最后调用make_fat_library将在当前编译目录下的静态lib同在其他目录下地lib合并,依次实现支持多结构的FAT静态库。这个被放到了framework中。</br></br>
The final commands of the script are simple copy commands. Add the following to the end of the script:</br></br>
脚本的最后是简单的拷贝命令,将下面代码添加到脚本最后:</br></br>
        # Ensure that the framework is present in both platform's build directories
        cp -a "${RW_FRAMEWORK_LOCATION}/Versions/A/${RW_FRAMEWORK_NAME}" \
              "${RW_OTHER_BUILT_PRODUCTS_DIR}/${RW_FRAMEWORK_NAME}.framework/Versions/A/${RW_FRAMEWORK_NAME}"

        # Copy the framework to the user's desktop
        ditto "${RW_FRAMEWORK_LOCATION}" "${HOME}/Desktop/${RW_FRAMEWORK_NAME}.framework"
第一条命令确保framework在所有平台的编译目录中都存在.</br></br>
第二条将完成的framework拷贝到用户的桌面上,这一步是可选的,但我发现这样做可以很方便的存取framework。</br></br>
选择Framework集合方案(aggregate scheme),按下cmd+B编译该framework。</br></br>
![](http://upload-images.jianshu.io/upload_images/2268803-5f46efe7e4d39b11.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)</br></br>
This will build and place a RWUIControls.framework on your desktop.</br></br>这一步将构建并在你的桌面上存放一个RWUIControls.framework。</br></br>
![](http://upload-images.jianshu.io/upload_images/2268803-e9ad1173f452ecd4.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)</br></br>
In order to check that the multi-platform build worked, fire up a terminal and navigate to the framework on the desktop, as follows:</br></br>
为了检查一下我们的多平台编译真的成功了,启动终端,导航到桌面上的framework,像下面一样</br></br>
        $ cd ~/Desktop/RWUIControls.framework
        $ RWUIControls.framework  xcrun lipo -info RWUIControls
第一条指令导航到framework中,第二行使用lipo指令从RWUIControls静态库中得到需要的信息,这将列出存在于该库中的所有片段</br></br>。![](https://cdn4.raywenderlich.com/wp-content/uploads/2014/02/ios_framework_architectures_in_fat_library.png)</br></br>
这里你可以看到,一共有五种片段:i386, x86_64, arm7, arm7s 和 arm64,正如你在编译时设定的那样。如果你之前使用lipo –info指令,你可以看到这些片段的一个分组。
###自己的补充
前面的设置只能生成三种架构,如果需要生成五种架构,还需要按下面的截图添加一些设置。</br>

![Snip20160705_1.png](http://upload-images.jianshu.io/upload_images/2268803-f13a58c9ebee40e2.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
ios
Web note ad 1