美文网首页IOS开发基础iOS 相关移动开发
ios10 Xcode8打包framework的正确姿势

ios10 Xcode8打包framework的正确姿势

作者: 874b526fa570 | 来源:发表于2017-06-30 15:22 被阅读4558次

    目前我们公司所有的SDK都采用了framework的方式,不再采取静态库的姿势,所以我今天也利用工作之余的时间学习一下这个创建framework的姿势,虽然这个过程非常非常简单,但是没人指导你,自己摸索还是需要浪费点时间的,走更着我的脚步一起去看看怎么打包自己的第一个 framework.
    先声明本文都属于操作部分,并且最基础,至于理论部分是参考文档的,还有其他的理论都会在后面更新!

    理论基础: 大神请跳过

    1. 库

    库是源代码经过编译,形成的二进制代码,别人项目中使用我们的库的时候,库在参与编译的时候,直接link就OK了,按照link的方式,可以把库分为静态库和动态库

    2. 静态库

    静态库在编译的时候会被直接拷贝一份,复制到目标程序里,这段代码在目标程序里就不会再改变了。
    一般以.a 和 .framework为文件后缀名
    这种做法是牺牲应用“体量”来节省编译时间。

    3. 动态库

    与静态库相反,动态库在编译时并不会被拷贝到目标程序中,目标程序中只会存储指向动态库的引用。等到程序运行时,动态库才会被真正加载进来。
    动态库的优点是,不需要拷贝到目标程序中,不会影响目标程序的体积,而且同一份库可以被多个程序使用(因为这个原因,动态库也被称作共享库)。
    同时,编译时才载入的特性,也可以让我们随时对库进行替换,而不需要重新编译代码。动态库带来的问题主要是,动态载入会带来一部分性能损失,使用动态库也会使得程序依赖于外部环境。如果环境缺少动态库或者库的版本不正确,就会导致程序无法运行
    以.tbd(之前叫.dylib) 和 .framework 为文件后缀名
    苹果系统为我们提供了很多动态链接库,我们可以在我们项目工程中查看一下

    177C31E7-5036-4C34-A9ED-31A402D2B5D0.png

    4. Framework

    Framework 是一种打包方式,将库的二进制文件,头文件和有关的资源文件打包到一起,方便管理和分发。
    Framework只是一种打包方式,其本身和静态、动态无关!
    但Cocoa Touch Framework 的实际内容为 Header + 动态链接库 + 资源文件

    5. 对Framework认识的误区

    误区①:.framework是动态库,.a是静态库,前面已经讲过,不再赘述
    误区②:有人说“自定义的动态库苹果审核不通过”,那我打的framework是不是通不过审核?
    任何没有时间前提的结论都是耍流氓!!!
    在 iOS 8 / iOS6之前,iOS 平台不支持使用动态 Framework,开发者可以使用的 Framework 只有系统的framework,这种限制可能是出于安全的考虑
    换一个角度讲,因为 iOS 应用都是运行在沙盒当中,不同的程序之间不能共享代码,同时动态下载代码又是被苹果明令禁止的,没办法发挥出动态库的优势,实际上动态库也就没有存在的必要了
    但是,码农总是喜欢折腾的,一方面骨子里面有一种“你不让我做我偏要做的倔强”,另一方面用framework确实比用.a加头文件的方式简单,所以这一时期的开发者用了很多“奇淫技巧”来制作framework,这就有了Fake Framework 和 Real Framework的区分
    在 iOS 8 / iOS6后,iOS平台添加了动态库的支持,同时, Xcode 6 也原生自带了 Framework 支持,注意,前后两个维度的不同是两件事,不要混淆。。。

    那么,为什么 iOS 8 要添加动态库的支持?
    主要的理由大概就是 Extension 的出现。Extension 和 App 是两个分开的可执行文件,同时需要共享代码,这种情况下动态库的支持就是必不可少的了。但是这种动态 Framework 和系统的 UIKit.Framework 还是有很大区别;还有就是为了支持swift
    虽然同样是动态框架,但是和系统 framework 不同,app 中的使用的 Cocoa Touch Framework 在打包和提交 app 时会被放到 app bundle 中(App 和 Extension 的 Bundle 是共享的),运行在沙盒里,而不是系统中。也就是说,不同的 app 就算使用了同样的 framework,但还是会有多份的框架被分别签名,打包和加载,因此苹果又把这种 Framework 称为 Embedded Framework,也正是代码签名机制,通过AppStore发布的APP是无法通过替换服务端下发framework的方式来进行热更新!



    正文:
    今天我们将采取“Aggregate+脚本”制作framework,配置选中手动配置的方式,后面会考虑使用 xcconfig 来默认设置

    1, 配置环境,开源头文件

    打开xcode 创建framework项目


    44AB0935-E961-49E5-82AD-E03DC95F43AC.png 07D7A1BD-E9F6-4BC4-BC5D-29A577B82B7F.png 606913CA-35D5-4314-8AB0-689DD2B4E8F2.png

    必须更改的两个注意点:

    3FCD6DB8-5505-4720-9528-F5214CACF394.png 597EC445-25AD-4A6C-BDEA-2945F0A366BE.png

    最后你还要更改SDK最低支持的版本,这个和项目更改系统支持的版本一样,不再赘述
    到此基本配置基本完成,也实现了项目的闭源

    2, 添加自动打包脚本环境,实现自动打包

    E44CD8EE-0618-45E7-81BD-4D84185D3639.png 0E1796A9-4893-42AC-B02B-59C27D72A670.png 06E693D7-6ED0-488B-BEF3-D14744F69C2E.png 60C7C4FA-87B1-4ACB-A058-E719E007B4BE.png F0D97DDB-A0D2-4C7F-890D-6AFE992842DD.png D9F6BE79-76AA-4C2C-891D-AA35AB4DF777.png

    常见的错误:
    1, 没有改成静态,不支持动态


    75229607-E8BD-445E-8759-D034C0E56E5C.png

    2, Defines Module 必须改成NO
    3, 支持bitcode的frame操作

    如果自己想要制作支持 Bitcode 的 Framework,
    1, 工程中开启 Enable Bitcode 
    2, Build Setting 中 Other Linker Flags 中加入 -fembed-bitcode。
    3, Build Setting 中 Other C Flags 中加入 -fembed-bitcode。
    
    
    同时支持模拟器真机的配置 09D9AD5076E38257F8398340E801E019.jpg 静态库和自己项目同时开发的方案 6211AA11499C3FB2A3E25532AD8DCFE6.jpg

    上文中会用到自动打包的 shell 脚本,我使用的是公司其他大神写的根据项目需求配置的脚本,这里就不开源了, 大家可以使用以下脚本,也可以实现自动打包

    #!/bin/sh
    #要build的target名
    TARGET_NAME=${PROJECT_NAME}
    if [[ $1 ]]
    then
    TARGET_NAME=$1
    fi
    UNIVERSAL_OUTPUT_FOLDER="${SRCROOT}/${PROJECT_NAME}/"
    
    #创建输出目录,并删除之前的framework文件
    mkdir -p "${UNIVERSAL_OUTPUT_FOLDER}"
    rm -rf "${UNIVERSAL_OUTPUT_FOLDER}/${TARGET_NAME}.framework"
    
    #分别编译模拟器和真机的Framework
    xcodebuild -target "${TARGET_NAME}" ONLY_ACTIVE_ARCH=NO -configuration ${CONFIGURATION} -sdk iphoneos BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}" clean build
    xcodebuild -target "${TARGET_NAME}" ONLY_ACTIVE_ARCH=NO -configuration ${CONFIGURATION} -sdk iphonesimulator BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}" clean build
    
    #拷贝framework到univer目录
    cp -R "${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${TARGET_NAME}.framework" "${UNIVERSAL_OUTPUT_FOLDER}"
    
    #合并framework,输出最终的framework到build目录
    lipo -create -output "${UNIVERSAL_OUTPUT_FOLDER}/${TARGET_NAME}.framework/${TARGET_NAME}" "${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${TARGET_NAME}.framework/${TARGET_NAME}" "${BUILD_DIR}/${CONFIGURATION}-iphoneos/${TARGET_NAME}.framework/${TARGET_NAME}"
    
    #删除编译之后生成的无关的配置文件
    dir_path="${UNIVERSAL_OUTPUT_FOLDER}/${TARGET_NAME}.framework/"
    for file in ls $dir_path
    do
    if [[ ${file} =~ ".xcconfig" ]]
    then
    rm -f "${dir_path}/${file}"
    fi
    done
    #判断build文件夹是否存在,存在则删除
    if [ -d "${SRCROOT}/build" ]
    then
    rm -rf "${SRCROOT}/build"
    fi
    rm -rf "${BUILD_DIR}/${CONFIGURATION}-iphonesimulator" "${BUILD_DIR}/${CONFIGURATION}-iphoneos"
    #打开合并后的文件夹
    open "${UNIVERSAL_OUTPUT_FOLDER}"
    

    相关文章

      网友评论

        本文标题:ios10 Xcode8打包framework的正确姿势

        本文链接:https://www.haomeiwen.com/subject/fhzbcxtx.html