美文网首页iOS开发iOS
iOS 制作静态库

iOS 制作静态库

作者: 海青 | 来源:发表于2016-01-29 19:20 被阅读501次

    制作静态库

    • 动态库:.dylib .framework
    • 静态库:.a .framework

    两者区别*:动态库时在程序运行时动态链接的,且可以被多个程序链接,相当于以动态库为中心,系统只会加载动态库到内存一次,这样动态库就始终只占一份内存,而静态库是提前把需要编译的实现文件编译为二进制文件,每个程序都需要复制一份,这是在使用静态库就决定了的特性,我们需要把静态库复制到工程文件内,供我们程序使用,而在制作时静态库时,我们可以选择暴露哪些文件给使用者,当然大部分都只需暴露头文件,我们当然也可以暴露实现文件,供我们参考学习,了解其中原理,众使我们修改了该文件的内容也没关系,因为该文件已经在制作静态库时已经编译成二进制文件,我们使用时不会再次编译该文件,资源文件如图片等也是可以我们替换,因为编译时只是简单的COPY,所以我们可以替换SVProgressHUB里的error或success成我们个性化的图片。苹果官方不允许我们App包含动态库。

    .a.framework的区别:
    制作.a 都需要我们手动在Header Search Paths加头文件搜索路径
    制作 .framework不需要

    制作.framework静态库

    我们先说.framework 的制作过程,我们新建项目选择iOS的framwork / library ,建好后默认有一个头文件,这不是我们需要的,直接删掉,这里我们可以任意建文件夹和文件,把我们需要的功能库搭建好后,我们在Build phase > Headers > public 内添加我们需要暴露的文件,这样我们就建好了,然后我们分别选着模拟器 和 Generic iOS Device 来构建我们的product ,只有当我们构建完Generic iOS Device才能看到product内的target由红色变为黑色,这说明文件存在,构建完毕,然后我们右键 show in finder 找到编译好的文件,当然,这个文件只包含armv7 和arm64 架构的。我们还需要在Mach-type修改类型为Static Library,当然我们也可以制作动态库,只是不能发布。如果你制作动态库就需要在Embedded Binaries 内添加库。

    对于这几种CPU架构分类:

    真机:

    3gs ~ 4s :armv7

    5 ~5c :armv7s

    5s~ 6plus:arm64

    模拟器:

    4s~5 : i386

    5s~6plus : x86_64

    所以我们需要合并这几种包,并且都是debug包,我们一般发布给别人Release包,这需要我们Edit Scheme 选择Run > info >build configuration 为Release。Release包会比debug包要小一点,因为编译时作了代码优化,运行效率会高一点,但不会明显提高。

    为了保证都能运行,我们还需要合并包,这里的包是.framework 文件里的同名的无扩展名的二进制文件,使用下面命令合并,更多使用方法( man lipo

    lipo -create test1 test2 -output test3

    然后替换之前任意一个同名的二进制文件,这里多次强调同名,因为系统就是根据根据静态库名在静态库内寻找二进制文件,不然会报找不到该文件的错误。

    这样我们直接把替换二进制文件后的.framework文件拖进我们其它工程直接使用。

    当然如果我们还需要在静态库内使用资源文件,我们使用Bundle,在该项目内Add Target ,选择OSX 内的Bundle,我们需要删除一系列,修改sdk,修改product name等等。

    制作.a静态库

    类似制作.framework静态库,我们新建项目XHQ_StaticFramework,选择Cocoa Touch Static Library
    这时可以看到两个文件夹:XHQ_StaticFrameworkProduct , Xcode 为我们自动建好的XHQ_StaticFramework(.h/.m)文件,一般我们只需要头文件,头文件写下我们所有需要公开的头文件,其它全部删掉,以便客户使用时只需引入这个头文件。Product存放我们生成的二进制文件。这里我们引入<UIKit/UiKit.h>框架,(网上多个版本都提到需要在Build Phrases >Link Binary With Libraries 内添加UIKit.framework,但是作者没有添加也能正常使用,如果你知道原因请告诉我,谢谢!)

    我们在XHQ_StaticFramework 文件夹下建好我们自己的代码库后,把需要公开的头文件加到Build Phases >Headers ,如果你没有这个目录,你需要手动Editor > Add Build Phases> Add Headers Build Phases 来添加。(提示:如果无法选择,你需要点击Build Phases 空白处后再重复上面的步骤。)

    点开 Headers 默认是有三个文件目录: public&&private&&project, 其中pulic和private都是放对外公开的文件,两者区别就是存储的路径可能不一样,我们可以在Packaging> Private/Public Headers Folder Path设置路径。这里我们设置为include/$(PROJECT_NAME),project 存放我们私有的文件。

    然后我们需要在Build Settings设置一些值:

    Dead Code Stripping > NO(去掉不会执行到的代码)

    Strip Style > Debugging Symbols

    Strip Debug Symbol During Copy > NO(去掉Debug相关符号)

    Strip Linked Product > NO

    这样做是为了后期产生bug时,我们能通过符号文件定位到我们需要的类的信息, 但是如果是iOS 或者 OSX则配置完全相反。相关文章

    我们编译成功后就可以正常使用。使用时我们有两种方式

    一种是在其它项目中拖进该项目,在新项目中添加依赖 Build Phases > Target Dependencies添加.a静态库,然后就是link library 内添加.a静态库;

    上面的方式适合我们自己内部使用,好处就是可以动态的修改静态库的文件,Xcode会根据是否需要重新编译来生成静态文件,而其实我们可以是直接使用生成的.a静态库和包涵头文件的include文件夹,只不过我们每次都需要配置Search Headers Paths,这种方式适合给外部使用。

    使用脚本生成集成包

    相信上面的这些分别生成支持不同架构的包已经让你精疲力竭,我们有更加方便的方法制作通用的包,那就是使用脚本来构建支持多个架构的包.首先我们在前面制作framework的基础上添加
    Aggragate target,然后在Build Phases 内添加 Run Script
    把下面代码添加进去。直接运行,然后生成的包目录会自动打开。

    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}" ];then
    
    rm -rf "${INSTALL_DIR}"
    
    fi
    
    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}"
    

    参考文章

    相关文章

      网友评论

        本文标题:iOS 制作静态库

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