聊聊Universal framework原理
来源:互联网 发布:考勤管理小软件 编辑:程序博客网 时间:2024/04/30 12:18
使用universal framework进行编译。在使用xcode7编译时发现,由于系统生成的目录有变化,导致无法生成原始脚本依赖的相关文件目录结构。
XCode7编译错误总结
- 错误A:用python脚本的universal framework。
/Users/fangying/Documents/project/XXX/DerivedData/XXX/Build/Products/Debug-iphoneos/XXX.framework/Versions/A
错误B:用shell脚本的universal framework。虽然不会编译错误,但是编译输入的framework是错误的。具体请看下图:
错误C:用shell脚本的universal framework。出现下面的错误。
iPhoneOS.platform/Developer/usr/bin/libtool: No such file or directory
iPhone平台Framework简介
xxx.framework包是iPhone平台对于资源、二进制包、头文件集合。通过这个集合包可以方便提供给使用者提供业务bundle或者SDK的功能。
对于系统提供两种framework:
- 静态framework
- 动态framework,比如系统Fundation.framework、AudioToolBox.framework等等。该framework类似与系统动态库。而对于开发者的动态framework,需要把工程设置target to 8.0以上才能支持。
对于framework,iOS系统有严格规定:
# MyFramework.framework# |-- MyFramework -> Versions/Current/MyFramework# |-- Headers -> Versions/Current/Headers# |-- Resources -> Versions/Current/Resources# `-- Versions# |-- A# | |-- MyFramework# | |-- Headers# | | `-- MyFramework.h# | `-- Resources# | |-- Info.plist# | |-- MyViewController.nib# | `-- en.lproj# | `-- InfoPlist.strings# `-- Current -> A
注意 对于Mac OS每个App都是一个bundle,对于每个bundle都有严格文件目录格式,以及严格文件名要求,这些严格要求就像App加载协议一样,系统通过该基于文件目录格式和文件名,加载、启动App。个人认为这个有利于app管理和动态部署。Mac OS重装系统,不用想Windows重装系统一样,重装系统后,Mac OS之前应用都可以正常使用,Window就完蛋了,需要重新安装,配环境变量。想想都心碎。
Universal Framework介绍
Universal Framework主要功能编译出在iOS上运行的静态framework包。
主要功能:
- 编译静态framework包
- 编译基于多架构二进制的framework包(armv7,arm64,i386,x86_64),其中只有编译achive包 or 编译命令有有 UFW_ACTION=action时,会编译4个架构的framework包
- 支持资源编译到framework中。
Universal Framework原理
其实Universal Framework原理比较简单,具体分为两点:
- 修改工程配置,编译基于静态库的framework
- 加入python脚本,把xcodebuild生成的原生framework结构,修改为iphone平台framework的文件格式
- 分别打各个架构包,利用libtool -static XXX XXX XXX XXX -o 二进制文件
比如对于相关framework集成多架构包命令如下
'/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/libtool', '-static', '/Users/fangying/Documents/project/tbguideman/DerivedData/TBGuideMan/Build/Intermediates/ArchiveIntermediates/XXX/IntermediateBuildFilesPath/XXX.build/Release-iphoneos/XXX.build/Objects-normal/armv7/XXXX.ufwbuild', '/Users/fangying/Documents/project/tbguideman/DerivedData/TBGuideMan/Build/Intermediates/ArchiveIntermediates/XXXX/IntermediateBuildFilesPath/XXXX.build/Release-iphoneos/XXXX.build/Objects-normal/arm64/XXXX.ufwbuild', u'/Users/fangying/Documents/project/tbguideman/DerivedData/TBGuideMan/Build/Intermediates/ArchiveIntermediates/XXXX/IntermediateBuildFilesPath/XXXX.build/Release-iphonesimulator/XXX.build/Objects-normal/i386/XXXX.ufwbuild', u'/Users/fangying/Documents/project/tbguideman/DerivedData/TBGuideMan/Build/Intermediates/ArchiveIntermediates/XXXX/IntermediateBuildFilesPath/XXXX.build/Release-iphonesimulator/XXX.build/Objects-normal/x86_64/XX.ufwbuild', '-o', '/Users/fangying/Documents/project/tbguideman/DerivedData/TBGuideMan/Build/Intermediates/ArchiveIntermediates/XXX/IntermediateBuildFilesPath/UninstalledProducts/XXX.framework/XXX'
Xcode编译过程
背景知识,对于xcode打包过程,是依赖于xcode ide中build phases。如图
如上图:该工程的编译顺序逻辑为:
- 编译依赖的target
- 运行该脚本
- 执行文件编译为.o
- 对于外部引用库进行link
- 拷贝public文件到指定目录
- 拷贝资源文件到指定目录
- 运行该脚本
关于该理解、可以参考编译log日志进行理解,按照编译时间顺序
- Process Info.plist
ProcessInfoPlistFile DerivedData/XXX/Build/Products/Debug-iphoneos/XXX.framework/Info.plist XXXX/Info.plist cd /Users/fangying/Documents/project/XXXXr_testing export PATH="/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin:/Applications/Xcode.app/Contents/Developer/usr/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin" builtin-infoPlistUtility /Users/fangying/Documents/project/XXXXX_testing/XXXX/Info.plist -expandbuildsettings -format binary -platform iphoneos -o /Users/fangying/Documents/project/XXXX_testing/DerivedData/XXXXX/Build/Products/Debug-iphoneos/XXX.framework/Info.plist
- Run custom shell script ‘Run Script’
PhaseScriptExecution Run\ Script DerivedData/XXX/Build/Intermediates/XXX.build/Debug-iphoneos/XXX.build/Script-D0914C4B1BAFBD01003C4371.sh cd /Users/fangying/Documents/project/XXX export ACTION=build export AD_HOC_CODE_SIGNING_ALLOWED=NO......... export variant=normal /bin/sh -c /Users/fangying/Documents/project/XXXX/DerivedData/XXXX/Build/Intermediates/XXXX.build/Debug-iphoneos/XXXXXX.build/Script-D0914C4B1BAFBD01003C4371.sh
从这段运行log,可以了解系统会把编译时中间文件以及编译的脚本都放到DerivedData/XXX/Build/Intermediates/XXX.build/Debug-iphoneos/XXX.build中
complie .m .cpp .c .mm等文件
Create static library + Create universal binary
Libtool DerivedData/XXX/Build/Intermediates/XXX.build/Debug-iphoneos/XXX.build/Objects-normal/armv7/XXX normal armv7 cd /Users/fangying/Documents/project/XXX export IPHONEOS_DEPLOYMENT_TARGET=6.0 export PATH="/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin:/Applications/Xcode.app/Contents/Developer/usr/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin" /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/libtool -static -arch_only armv7 -syslibroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS9.0.sdk -L/Users/fangying/Documents/project/XXX/DerivedData/XXX/Build/Products/Debug-iphoneos -L/Users/fangying/Documents/project/XXX/Pods/OpenSSL/lib -filelist /Users/fangying/Documents/project/XXX/DerivedData/XXX/Build/Intermediates/XXX.build/Debug-iphoneos/XXX.build/Objects-normal/armv7/XXX.LinkFileList -ObjC -framework Foundation -o /Users/fangying/Documents/project/XXX/DerivedData/XXX/Build/Intermediates/XXX.build/Debug-iphoneos/XXX.build/Objects-normal/armv7/XXX
CreateUniversalBinary DerivedData/XXX/Build/Products/Debug-iphoneos/XXX.framework/XXX normal armv7\ arm64 cd /Users/fangying/Documents/project/XXX export PATH="/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin:/Applications/Xcode.app/Contents/Developer/usr/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin" /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/libtool -static /Users/fangying/Documents/project/XXX/DerivedData/XXX/Build/Intermediates/XXX.build/Debug-iphoneos/XXX.build/Objects-normal/armv7/XXX /Users/fangying/Documents/project/XXX/DerivedData/XXX/Build/Intermediates/XXX.build/Debug-iphoneos/XXX.build/Objects-normal/arm64/XXX -o /Users/fangying/Documents/project/XXX/DerivedData/XXX/Build/Products/Debug-iphoneos/XXX.framework/XXX
- Copy 资源头文件和资源文件
CopyPlistFile DerivedData/XXX/Build/Products/Debug-iphoneos/XXX.framework/XXX-Info.plist XXX/XXX-Info.plist cd /Users/fangying/Documents/project/XXX export PATH="/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin:/Applications/Xcode.app/Contents/Developer/usr/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin" builtin-copyPlist --convert binary1 --outdir /Users/fangying/Documents/project/XXX/DerivedData/XXX/Build/Products/Debug-iphoneos/XXX.framework -- XXX/XXX-Info.plist
Universal Framework python编译过程
Universal python逻辑是使用两个进程分别编译iphoneos和iphonesimulator两个版本的。
结合上图,其中主要几点(红色表示子进程,先进行黑色流程,然后两个并行执行)
- master表示是iphoneos
- 非master表示是iphonesimulator
- achive表示是基于xcode achive打包,可以使用xcodebuild命令输入UFW_ACTION=action指明该次xcode打包是achive打包(该achive非xcode achive,只是使得逻辑进入is achive的python脚本运行逻辑)
- iphoneos编译是编译armv7,arm64 archs, iphonesimulator是编译x86_64, i386 archs
结合上图,分解几步说明下相关的流程:
1. project类是python类,描述当前打包环境、获取打包命令、执行打包命令等功能
起具体的值是通过加载
2. 保存iphone os的打包环境变量到ufw_build_state.json文件中,提供给编译simulator子进程获取环境变量使用
3. 重新获取iphoneos编程的环境变量,保证后续编译命令都是编译iphoneos包
4. 从ufw_build_state.json获得基础环境变量,然后,设定iphonesimulator相关的环境变量
5. 编译各个架构的二进制包
6. 如果是iphonesimulator的进程,执行这里,这里绑定i386+x86_64
7. 如果是iphoneos进程,执行这里,这里绑定4个架构的二进制包
- 聊聊Universal framework原理
- Universal-Framework
- iOS-Universal-Framework
- 安装iOS-Universal-Framework
- iphone中自定义Universal Framework
- Create an iOS Universal Framework
- iOS-Universal-Framework 支持XCode7
- iOS-Universal-Framework 制作 framework的问题
- 开源框架:iOS-Universal-Framework
- Building a Universal Framework for iOS
- 安装iOS Universal Framework Mk 7
- iOS Universal Static Framework 手动转 XCode Cocoa Framework
- android universal image loader 缓冲原理详解
- Universal-Image-Loader 原理和实现
- Android universal-Image-Loader原理详解
- 聊聊Dubbox(三):架构原理
- 聊聊并发--原子操作的实现原理
- 聊聊Dubbox(二):架构原理
- 多线程 —— GCD
- Java自动装箱和自动拆箱源码分析
- hdu1010 Tempter of the Bone
- 数据结构基础:数组和链表
- hdu 2199
- 聊聊Universal framework原理
- jsp forward与redirect比较
- 软件测试相关的生命周期总结
- 进程(线程)间的同步互斥问题(五) 读者-作者问题
- HDU 2896 病毒侵袭 (AC自动机)
- OVS2.3.2安装指南
- 冒泡排序
- 关于写博客这件事
- [java] 发一个企业人员管理系统的代码