Unity Infinity.Build
文章目录
需求
DONE
- 生成可以在 iOS 上直接安装的 ipa 包。
- Debug Release 版本选择。
- 有默认配置,可以通过命令行修改预设参数。
TODO
- Android 版本的打包。
- 支持上传到 Fir.im、蒲公英 等等。
- 记录环境信息,包括:Unity 版本、Xcode 版本、Ruby 版本。
- 记录所有程序输出的日志,方便查找错误。
- 可以使用指定版本构建。
- 计时,记录每一步消耗的时间。
过程
语言
这种打包脚本使用操作系统自带的脚本语言最方便。第一选择是 Python,但是之前写过类似的,这次就想换 Ruby 尝试一下,最终决定使用 Ruby 来编写这个工具。 Ruby 本身用起来非常简单,OS X 自带的 Ruby 版本 2.0.0,已经非常成熟了。
提示:使用 ls
这种语法调用时请不要使用中文路径,中文在路径中会消失,而不管 Ruby 源文件是否是 utf-8 编码。
提示:在使用字符串时需要双引号使用,以方便在其中嵌入变量,同时应对所有命令中变化的值使用 \" 引用,防止为空时出错。此处不应使用 \',在 shell 中,\' 并不会对字符串中的内容进行转义!
Unity
从命令行调用参考官方文档 Unity - Manual: Command line arguments 即可。 Unity 内部需要辅助静态函数来打包,这里使用到了之前写的一个库:networm/Infinity.BuildInUnity3d
BuildInUnity3d 库的作用就是套一层封装,同时配合 Build 库实现构建 Debug 与 Release 版本。
因为 Unity 不支持传递自定义参数,即使传递了自定义参数,使用 System.Environment.GetCommandLineArgs()
也无法获取,最终变通方法是使用不同的构建函数:BuildPlayerDevelop()
与 BuildPlayerRelease()
。
提示:Unity 的日志输出可以重定向到标准输出(即终端中),只要在调用时指定参数 -logFile $stdout
。
Xcode
xcode 构建这里麻烦一些,涉及到的步骤较多:
- 安装 mobileprovision
- 创建并解锁 keychain
- 导入 p12 开发者私钥与证书
- 编译、打包
codesign
有关如何禁止 codesign 签名时弹窗,网上有很多方案,但是只有代码,并没有解释得很清楚。
codesign 在签名时会使用两样东西:keychain 与 private key。其中 private key 存储在 keychain 中。
codesign 在签名时会寻找系统指定的 keychain 搜索列表。不要被 codesign 的 --keychain filename
选项蒙蔽,这个选项要求 filename
必须在 keychain 搜索列表中。
用户有一个默认的 login.keychain
,密码是用户自己的密码,如果导入 p12 时导入到 login.keychain
中就必须要求要么用户输入密码,要么将密码写死在脚本中,这样很危险,而且无法做到开包即用。
这里使用的一个变通方法:
- 首先创建一个 keychain 并解锁。
- 将 p12 导入到新建的 keychain 中并通过
-T /usr/bin/codesign
参数指定 codesign 使用的私钥。 - 再通过
security list-keychains -s
命令将创建的 keychain 设置为用户的 keychain 搜索列表。 - 直接使用 codesign 或通过 xcodebuild 间接使用 codesign 签名。
- 将用户的 keychain 搜索列表设置为默认的 login.keychain。
- 删除创建的 keychain。
第 5 步强烈建议做,如果不做的话,用户打开 钥匙链
应用时,只能看到刚创建的“keychain”,而看不到默认的“登录”。
提示:创建 keychain 后建议解锁,否则在 300 秒超时后 codesign 在签名时会要求解锁。
提示:import p12 时一定要指定 -T /usr/bin/codesign
否则 codesign 在执行时会提示对话框询问是否允许使用私钥。
mobileprovision
mobileprovision 安装很简单,将其拷贝到 ~/Library/MobileDevice/Provisioning Profiles
目录中,并将其改名为 $UUID.mobileprovision
。
其中的 UUID 可以通过
grep "UUID" ${IOS_PROVISIONING_FILE_PATH} -A 1 --binary-files=text 2>/dev/null |grep string|sed -e 's/^[[:blank:]]<string>//' -e 's/<\/string>//'
命令获取。
但是在 Ruby 中直接调用并不会获取正确的结果,所以此处使用 nokogiri
xml 库来读取 UUID。
iOS 布署方式
- app-store 是发布到 App Store 的方式(注意:TestFlight 使用的是 app-store,而不是 ad-hoc)。
- ad-hoc 是发布给其他人使用的方式。
- development 是开发者布署到自己的测试设备上的方式。
提示:提交到 iTunes Connect 中的应用的 Build 版本号每一个都要不一样,否则会提示重复,所以在每次构建前都要设置 –build-version 参数。 因为这个 Build 版本号存放在 Xcode 项目的 Info.plist 中,可以使用 PlistBuddy 修改。
提示:在构建 app-store 与 ad-hoc 时要求的 exportOptionsPlist 中有一个 team ID,可以从导入的 P12 中直接提取。
Source Code
GitHub: networm/Infinity.Build
GitHub: networm/Infinity.BuildInUnity3d
LICENSE
MIT LICENSE
参考资料
- iOS Provisioning Profile(Certificate)与Code Signing详解 - 曾梦想仗剑走天涯 - 博客频道 - CSDN.NET
- CircleCI-iOS-TestFlight-Sample/add-key.sh at master · thorikawa/CircleCI-iOS-TestFlight-Sample
- Ruby function to extract a provisioning profile UUID from a .mobileprovision file and to dynamically generate an xcconfig file · GitHub
- ruby - How do I parse a YAML file? - Stack Overflow
- YAML.rb is YAML for Ruby | Cookbook
- iOSprovisioningprofiles/mobileprovisioning.rb at master · KONDENSATOR/iOSprovisioningprofiles
- Class: OptionParser (Ruby 2.0.0)
- 详解Shell脚本实现iOS自动化编译打包提交 - Just My Blog