iOS开发-自动打包初步探究

最近项目进入版本开发末期,每天都有至少两到三次给测试打包的要求,由于项目用的又是用React Native写的,所以每次打包就非常麻烦,需要先将React Native的代码打包拖入iOS的文件夹中,然后再使用Xcode打包,打包好之后还要将打好的包导出,最后再把ipa包上传到蒲公英上供测试下载。这一系列操作都中每一个耗时都不少,而且还需要人一直在关注着走到哪一步,然后继续往下操作,不仅耽误时间,而且麻烦的要死,所以一个自动打包的脚本就显得非常有必要了。

xcodebuild

说到自动打包,最重要的一点就是需要依赖于xcodebuild了。xcodebuild是苹果发布的自动构建工具,可以通过在terminal中输入命令来达到我们在Xcode中点击运行等很多操作。

OK废话不多说,xcodebuild要怎么使用呢?

其实很简单,在terminal中输入 man xcodebuild 或者 xcodebuild --help就可以看到xcodebuild支持的命令了。

xcodebuild.png

这里边基本上每个命令都会用相应的解释,这里我们就列出几个比较常用的命令参数:

参数 说明
-project name.xcodeproj 在当前目录下有多个项目是需要指定改参数
-target targetname 如果不指定的话默认会构建第一个target
-alltargets 表示同时构建所有的target
-workspace name.xcwordspace 构建workspace,需要指定scheme
-scheme schemename 指定对应的scheme,构建workspace时必选
-destination destinationspecifier 通过描述使用对应的设备,默认使用当前scheme所匹配的设备
-destination-timeout timeout 搜索对应设备时需要的时间,可以设置搜索超时时间,默认为30s
-configuration configurationname 使用对应的配置进行构建,configurationname一般为Debug或Release
-arch architecture 指定构建的包所支持的指令集 arm64、armv7、armv7s
-sdk sdkfullpath sdkname 针对指定的SDK选择合适的构建工具构建,如-sdk iphoneos
-showsdks 列出所有的SDK,一般列出的后面会跟上版本号,-sdk不写版本号默认为所有版本
-list 列出当前项目所有的 Targets、Build、Configurations、Schemes
-derivedDataPath path 构建成功时相关的缓存文件默认路径
-archivePath xcarchivepath 设置导出的.xcarchive文件的路径
参数 说明
build 构建target,当没有其他action指定时,这是xcodebuild默认的一个action
build-for-testing 构建target和对应的相关单元测试,需要指定scheme
analyze 构建和分期target或scheme,需要指定scheme
archive 存档对应的构建scheme,需要指定scheme
test 从SYMROOT目录测试scheme,需要指定scheme和可选的destination
install 构建target然后安装到target的安装目录和发布目录(DSTROOT)
clean 从构建目录(SYMROOT)删除构建时的products和一些中间文件

有了xcodebuild的解释,再加上上边这些解释,应该已经清楚要怎么来通过terminal来编译、打包、导出我们的项目了吧?还不懂?没关系,我写几个常用的给你看。

对了对了,补上一个Xcode的project的架构图应该能看的更清楚一些:

xcode.png

打包命令

xcodebuild archive -workspace wallet.xcworkspace -scheme wallet -archivePath wallet.xcarchive

打包可以使用xcodebuild archive


xcodebuild archive -workspace(或-project) 工作空间名.xcworkspace

 -scheme 项目名称

 -configuration 构建配置

 -archivePath 导出archive包存储路径

 CODE_SIGN_IDENTITY=证书

 PROVISIONING_PROFILE=描述文件UUID

其中:

  • 1.workspace/project: 就是项目的名称,如果使用cocospod的一般为workspace,加上后缀就可以使用了。

  • 2.scheme:一般情况下也是项目名称,可以通过xcodebuild -list获取。

  • 3.configuration:可以选择Debug或Release模式,一般打包给测试的话使用Release比较好。

  • 4.archivePath:导出archive所存储的路径,这个不用多说。

  • 5.CODE_SIGN_IDENTITY:证书的Identity,稍等我们来讲一下如何获取这个。

  • 6.PROVISIONING_PROFILE:描述文件的UUID,稍等我们来将一下如何获取。

其中如果使用workspace时,scheme是必须填写的,而project则不需要,configuration默认为Release也可以省略,CODE_SIGN_IDENTITY和PROVISIONING_PROFILE也可以使用默认的配置不指定。其他都为必填项。

获取scheme

cd到项目目录下,通过xcodebuild -list就可以获取当前项目的scheme。

xcodebuild-list.png

获取 CODE_SIGN_IDENTITY

打开钥匙串->选中你的证书->右键->显示简介,你的证书的标题就是CODE_SIGN_IDENTITY了。

获取 PROVISIONING_PROFILE

使用


xcodebuild -target <target> -configuration <configuration> -showBuildSettings

命令就可以看到当前项目的 PROVISIONING_PROFILE 了。

导出打包后的ipa

上边的打包操作看懂后,xcodebuild的操作你应该就完全懂了吧?还不懂???

再来一个

导出打包后的ipa文件。

可以使用xcodebuild -exportArchive

xcodebuild -exportArchive -archivePath wallet.xcarchive -exportPath . -exportOptionsPlist "$workspace"/build.plist


xcodebuild -exportArchive -archivePath archive文件的地址.xcarchive 

 -exportPath 导出的文件夹地址 

 -exportOptionsPlist exprotOptionsPlist.plist 

 CODE_SIGN_IDENTITY=证书 

 PROVISIONING_PROFILE=描述文件UUID

其中-archivePath和exportPath以及-exportOptionsPlist是必须要传入的,其他两个和之前一样,可以不必穿进去。前两个参数都是路径,就不多说了,接下来着重介绍一下这个plist文件。

exprotOptionsPlist.plist

这个plist文件标注了导出包时的一些设定,其实就是在我们使用Xcode导出包时需要选择的一些东西。


<?xml version="1.0" encoding="UTF-8"?>

 <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">

 <plist version="1.0">

 <dict>

 <key>teamID</key>

 <string>UA11AAJJKK8</string> //TeamID

 <key>method</key>

 <string>ad-hoc</string> //ad-hoc打包

 <key> compileBitcode</key> //是否编译bitcode

 <false/>

 </dict>

 </plist>

在文档中还有一些其他的key和解释,这里就直接贴出来不做多解释了。


Available keys for -exportOptionsPlist:

 compileBitcode : Bool

 For non-App Store exports, should Xcode re-compile the app from bitcode? Defaults to YES.

 embedOnDemandResourcesAssetPacksInBundle : Bool

 For non-App Store exports, if the app uses On Demand Resources and this is YES, asset packs are embedded in the app bundle so that the app can be tested without a server to host asset packs. Defaults to YES unless onDemandResourcesAssetPacksBaseURL is specified.

 iCloudContainerEnvironment

 For non-App Store exports, if the app is using CloudKit, this configures the "com.apple.developer.icloud-container-environment" entitlement. Available options: Development and Production. Defaults to Development.

 manifest : Dictionary

 For non-App Store exports, users can download your app over the web by opening your distribution manifest file in a web browser. To generate a distribution manifest, the value of this key should be a dictionary with three sub-keys: appURL, displayImageURL, fullSizeImageURL. The additional sub-key assetPackManifestURL is required when using on demand resources.

 method : String

 Describes how Xcode should export the archive. Available options: app-store, ad-hoc, package, enterprise, development, and developer-id. The list of options varies based on the type of archive. Defaults to development.

 onDemandResourcesAssetPacksBaseURL : String

 For non-App Store exports, if the app uses On Demand Resources and embedOnDemandResourcesAssetPacksInBundle isn't YES, this should be a base URL specifying where asset packs are going to be hosted. This configures the app to download asset packs from the specified URL.

 teamID : String

 The Developer Portal team to use for this export. Defaults to the team used to build the archive.

 thinning : String

 For non-App Store exports, should Xcode thin the package for one or more device variants? Available options: <none> (Xcode produces a non-thinned universal app), <thin-for-all-variants> (Xcode produces a universal app and all available thinned variants), or a model identifier for a specific device (e.g. "iPhone7,1"). Defaults to <none>.

 uploadBitcode : Bool

 For App Store exports, should the package include bitcode? Defaults to YES.

 uploadSymbols : Bool

 For App Store exports, should the package include symbols? Defaults to YES.

写一个打包的脚本

因为我这边的情况是需要打包RN,然后打包项目最后传到蒲公英上,所以我就先就针对这个流程写一个脚本,如果你的需求跟我不一样,这个脚本可能还需要你自己来修改一下。

打包ReactNative代码

打包RN的代码主要会生成一个.jsbundle文件和图片asset文件夹。


react-native bundle --entry-file index.js --platform ios --dev false --bundle-output ios/main.jsbundle --assets-dest ios/

打包iOS项目并导出ipa包

这里有了前边的铺垫应该不需要再赘述太多了,直接上命令了,其中‘[]’中的内容需要替换成你自己的项目名称。


cd ios

xcodebuild archive -workspace [workspace name].xcworkspace -scheme [scheme name] -archivePath [xcarchive name].xcarchive              

# ad-hoc、enterprise、development、app store

cat << EOF > ../build.plist

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">

<plist version="1.0">

<dict>

 <key>method</key>

 <string>$1</string>

 <key>compileBitcode</key>

 <false/>

</dict>

</plist>

EOF

xcodebuild -exportArchive -archivePath [xcarchive name].xcarchive -exportPath . -exportOptionsPlist "$workspace"/build.plist

上传到蒲公英

蒲公英有提供专门的API接口,可以直接通过这个接口传入相应的参数,就可以将ipa包直接传到蒲公英上了。

上传接口的接口文档在这里

脚本如下,同样[]中的内容需要你自己替换。


curl -F 'file=@wallet.ipa' -F '_api_key=[your apiKey]' -F 'appKey=[your appKey]' https://www.pgyer.com/apiv2/app/upload

脚本

将上述的主要内容加上一些辅助的代码,写成一个shell脚本就为:


#!/bin/sh 

if [ -z "$1" ] 

then 

 echo "输入参数:ad-hoc、enterprise、development、app store"

fi

workspace=`pwd`

cd "$workspace"

echo "开始编译RN"

react-native bundle --entry-file index.js --platform ios --dev false --bundle-output ios/main.jsbundle --assets-dest ios/

echo "开始打包iOS"

cd ios

xcodebuild archive -workspace [workspace name].xcworkspace -scheme [scheme name] -archivePath [xcarchive name].xcarchive              

# ad-hoc、enterprise、development、app store

cat << EOF > ../build.plist

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">

<plist version="1.0">

<dict>

 <key>method</key>

 <string>$1</string>

 <key>compileBitcode</key>

 <false/>

</dict>

</plist>

EOF

xcodebuild -exportArchive -archivePath [xcarchive name].xcarchive -exportPath . -exportOptionsPlist "$workspace"/build.plist

echo "上传到蒲公英"

curl -F 'file=@wallet.ipa' -F '_api_key=[your apiKey]' -F 'appKey=[your appKey]' https://www.pgyer.com/apiv2/app/upload

echo "成功!"

这时候调用****sh package.sh + [method]**** 传入打包的参数就可以了,如果一般传入到蒲公英或者fir需要打development的包就直接传入development即可。

使用ApplicationLoader上传到App Store(8.17补充)

之前说了使用蒲公英集成,但是如果需要传到App Store时还是很麻烦,这时候我们需要用到Xcode中的ApplicationLoader工具,ApplicationLoader是用来提交二进制文件到AppStore的小工具。

ApplicationLoader在终端中是通过altool使用,在Xcode中可以通过点击Xcode左上角Xcode -> Open Developer Tool -> Application Loader打开。

altool工具的路径是/Applications/Xcode.app/Contents/Applications/Application\ Loader.app/Contents/Frameworks/ITunesSoftwareService.framework/Support/altool

具体的使用可以通过验证+上传两个命令使用:

$ altool --validate-app -f file -u username [-p password] [--output-format xml]

$ altool --upload-app -f file -u username [-p password] [--output0format xml]

其中这几个参数的意义:

参数 意义
--validate-app 需要验证的应用
--upload-app 需要上传的应用
-f file 需要验证或上传的应用的路径和文件名
-u username itunesConnect的用户名(Apple ID账号)
-p password itunesConnect的密码 (Apple ID密码)
-- output-format [xml normal] 需要Application Loader以结构化的XML格式还是非结构化的文本格式返回输出信息。

最后

这里只是对iOS自动打包一个初步的使用,还可以使用Jenkins等工具进行更高自动化的CI持续集成,本篇文章也仅限个人学习使用,如果有什么不正确的地方也请各位大神多多指教。

参考文档

关于xcodebuild

Xcode Build Settings Reference

关于iOS自动化打包的一些分享

使用Jenkins进行持续集成
iOS 应用打包命令一览

iOS一键搞定自动打包并发布到AppStore和Fir

使用xcodebuild打包 导出ipa 上传蒲公英或者提交AppStore

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,293评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,604评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,958评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,729评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,719评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,630评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,000评论 3 397
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,665评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,909评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,646评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,726评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,400评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,986评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,959评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,996评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,481评论 2 342

推荐阅读更多精彩内容