创建第一个库

由于公司业务需要,希望把原来直接加入到工程中的C++代码封装成库,供第三方使用。在这里做个总结:

  1. 创建动态库还是静态库
    我们知道静态库的目的是对功能的封装,静态库中的函数是要通过静态链接器跟工程源码链接在一起形成最终的可执行文件。而动态链接库的向我们的应用提供了一种调用外部代码的方式,使得我们的应用在链接的时候只需要“接入”动态链接库的地址而非源码,这样减小了可执行文件的体积。但是由于苹果的沙箱机制,iOS App无法直接调用除系统之外的沙箱外部的代码,所以我们在XCode中虽然创建的是动态库,实际上是静态库的效果。Framework帮我们将头文件、可执行文件、资源文件等封装在了一起,是苹果推荐的方式。
    静态库和动态库
  2. 如何打包
    通过XCode只能一次编译模拟器版本或者真机版本,无法同时编译两个版本。我们可以创建一个聚合target,并为之添加脚本,来解决需要分别编译并手动合并两个版本的麻烦。
    这里写图片描述
  3. 为库增加bitcode
    在模拟器运行以及真机环境执行时,都不会真正编译带有bitcode的中间代码。只有在打包(Archieve)时才会编译出bitcode中间代码。
    3.1. 如果是通过XCode直接打包的话,需要做三个修改:
    (1) 将库工程的BitCode Enabled 设置为YES。
    (2)将-fembed-bitcode添加到Other C flags中。
    (3)将-fembed-bitcode添加到Other linker flags中。
    做完这三项才能打出含有bitcode的库。
    3.2. 如果是通过脚本打包,则需要在xcodebuild命令中增加OTHER_CFLAGS=”-fembed-bitcode”参数。
    3.3. 如何检查打出的包是否已包含bitcode。通过目标文件显示工具otool(object file displaying tool),如果其中包含LLVM的内容,就可以认为包含了bitcode。
    这里写图片描述
    PS:如果是针对静态库.a的话,要检查的是是否包含bitcode,命令是:otool -arch armv7 -l xxx | grep bitcode | wc -l
  4. 打包脚本(网上找的,暂时运行良好)

    # 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" OTHER_CFLAGS="-fembed-bitcode" -target "${FMK_NAME}" -sdk iphoneos clean build
    xcodebuild -configuration "Release" OTHER_CFLAGS="-fembed-bitcode" -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}/"
    cp -R "${SIMULATOR_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}"
  5. 如何使用库
    5.1. 将库加入到Embedded Binary中。
    5.2. 可能在打包导出这一步会报错:
导出命令:
xcodebuild -exportArchive -archivePath "${archive_path}" -exportPath "${export_dir}" -exportOptionsPlist "${plist_file}" || Failed "export fail" 

我得到的错误日志:

2017-11-07 21:43:37.446 xcodebuild[7258:7118830] [MT] IDEDistribution: -[IDEDistributionLogging _createLoggingBundleAtPath:]: Created bundle at path '/var/folders/x8/c9m8j_0141s50hkpy58844_w0000gn/T/Mara_2017-11-07_21-43-37.445.xcdistributionlogs'.
./xcodebuild_safe.sh: line 4:  7258 Segmentation fault: 11  xcodebuild "$@"
Failed: export fail

发现打包后…xcdistributionlogs这个目录是空的,进到这个目录后会有这几个文件,在最后一个IDEDistributionPipeline.log中找到了最可疑的error,手动将.framework中的CFBundleSupportedPlatforms key删除,就可以啦。
这里写图片描述

这里写图片描述

之后遇到的问题

1,无法输出日志

2,无法调试
将sdk工程添加到主工程,将sdk工程作为主工程的依赖工程,增加链接库之后,发现还是无法debug。后来重新做了一遍framework才可以了。
3,修改了库中的一个暴露的.h的文件名后报错。
报错bridge-header.h中找不到该头文件。clean,删除derived data,重新添加sdk工程都不行。最终还是把名字换回去了。
4,报错 no such module xxx
需要在build setting的framework search path中指定framework所在的路径。
5,在主工程链接时报错 undefined archtecture armv7。
发现是sdk工程的deployment sdk版本默认是最新的11.2,改为跟主工程一样即可。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值