使用universal framework进行编译。在使用xcode7编译时发现,由于系统生成的目录有变化,导致无法生成原始脚本依赖的相关文件目录结构。
/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
xxx.framework包是iPhone平台对于资源、二进制包、头文件集合。通过这个集合包可以方便提供给使用者提供业务bundle或者SDK的功能。
对于系统提供两种framework:
对于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主要功能编译出在iOS上运行的静态framework包。
主要功能:
其实Universal Framework原理比较简单,具体分为两点:
比如对于相关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 ide中build phases。如图
如上图:该工程的编译顺序逻辑为:
关于该理解、可以参考编译log日志进行理解,按照编译时间顺序
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
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中
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
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 python逻辑是使用两个进程分别编译iphoneos和iphonesimulator两个版本的。
结合上图,其中主要几点(红色表示子进程,先进行黑色流程,然后两个并行执行)
结合上图,分解几步说明下相关的流程:
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个架构的二进制包