iOS 应用打包命令一览
文章转载自:http://www.jianshu.com/p/5d59966eaecc
文章排版部分根据自己的理解做了一些修改。
各种命令的简介
使用命令打包iOS 应用一般会用到 xcodebulid
和 xcrun
。
xcodebuild
主要是用来编译工程。
xcrun
则是打包出ipa安装包。
altool
适用于提交到AppStore
的。
想要知道更多关于xcodebuild
命令参数,则可以使用xcodebuild -help
查看;
想要知道更多关于xcrun
命令参数,则可是用xcrun -help
查看。
另外,官方文档中有对 Workspace、Project、Scheme、Target更详细的讲解,地址是:Xcode Concepts
altool
这个工具实际上是ApplicationLoader,打开Xcode-左上角Xcode-Open Developer Tool-Application Loader,altool的路径是:
/Applications/Xcode.app/Contents/Applications/Application\ Loader.app/Contents/Frameworks/ITunesSoftwareService.framework/Support/altool
如果使用时,报如下错误:
altool[] *** Error:
Exception while launching iTunesTransporter: Transporter not found at path: /usr/local/itms/bin/iTMSTransporter.
You should reinstall the application.
建立软链:
ln -s /Applications/Xcode.app/Contents/Applications/Application\ Loader.app/Contents/itms /usr/local/itms
如果想要在脚本中修改或者读取plist
文件的内容,可以使用PlistBuddy
,PlistBuddy
是Mac里一个用于命令行下读写plist文件的工具,在/usr/libexec/目录下。
下面是一段读取与修改 plist 中版本号的shell脚本:
#!/bin/sh
# PlistBuddy程序的绝对路径
PlistBuddyPath=/usr/libexec/PlistBuddy
# 工程中的plist 文件路径
appInfoPlistPath="/Volumes/SourceCode/showstart_ios/ShowStart_3.0/Info.plist"
# 读取bundleShortVersion 版本号
bundleShortVersion=$($PlistBuddyPath -c "print CFBundleShortVersionString" ${appInfoPlistPath})
# 读取bundleVersion 版本号
bundleVersion=$($PlistBuddyPath -c "print CFBundleVersion" ${appInfoPlistPath})
# 在终端中打印版本号
echo "$bundleShortVersion"
echo "$bundleVersion"
buildNumber="3.69"
# 重新设置 plist文件中的bundleVersion版本号
bundleVersion=$($PlistBuddyPath -c "Set :CFBundleVersion $buildNumber" ${appInfoPlistPath})
# 再次读取bundleVersion 版本号
bundleVersion=$($PlistBuddyPath -c "print CFBundleVersion" ${appInfoPlistPath})
# 打印版本号
echo "$bundleVersion"
Xcode 8之前的打包命令
在Xcode 8之前打包,都是使用xcodebuild
+xcrun
来打包ipa包。比如:
xcodebuild -workspace XXX -scheme XXX -configuration Release
xcrun -sdk iphoneos PackageApplication -v "/XXX/XXX.app" -o "/XXX/XXX"
需要注意的是,如果我们同时安装了多个Xcode,比如我这里同时安装的Xcode 7 和 Xcode 8,使用 xcodeuild
+xcrun
来打包ipa包 时,会出现如下错误:
2016-11-07 13:43:04.724 xcodebuild[22235:709735] CoreSimulator is attempting to unload a stale CoreSimulatorService job. Detected Xcode.app relocation or CoreSimulatorService version change. Framework path (/Applications/Xcode.app/Contents/Developer/Library/PrivateFrameworks/CoreSimulator.framework) and version (209.19) does not match existing job path (/Applications/Xcode_8.app/Contents/Developer/Library/PrivateFrameworks/CoreSimulator.framework/Versions/A/XPCServices/com.apple.CoreSimulator.CoreSimulatorService.xpc/Contents/MacOS/com.apple.CoreSimulator.CoreSimulatorService) and version (303.8).
2016-11-07 13:43:04.982 xcodebuild[22235:709735] Failed to locate a valid instance of CoreSimulatorService in the bootstrap. Adding it now.
2016-11-07 13:43:04.996 xcodebuild[22235:709735] *** Assertion failure in -[SimServiceContext reloadServiceIfMovedOrAbortIfWeAreInvalid], /BuildRoot/Library/Caches/com.apple.xbs/Sources/CoreSimulator/CoreSimulator-209.19/CoreSimulator/SimServiceContext.m:536
** INTERNAL ERROR: Uncaught exception **
Uncaught Exception: The loaded com.apple.CoreSimulator.CoreSimulatorService job does not match our expectations: pathOfLoadedJob: /Applications/Xcode_8.app/Contents/Developer/Library/PrivateFrameworks/CoreSimulator.framework/Versions/A/XPCServices/com.apple.CoreSimulator.CoreSimulatorService.xpc/Contents/MacOS/com.apple.CoreSimulator.CoreSimulatorService, our frameworkPath: /Applications/Xcode.app/Contents/Developer/Library/PrivateFrameworks/CoreSimulator.framework
我在stackoverflow上找到了解决方案:
在终端中执行如下命令:
launchctl remove com.apple.CoreSimulator.CoreSimulatorService || true
stackoverflow 上答案地址:
CoreSimulator is attempting to unload a stale CoreSimulatorService job
Random build failures on Teamcity
关于 xcodebuild
+xcrun
的更多 参数 和介绍,在上面简介中已经列出,这里就不再赘述了。
Xcode 8 以及 之后的打包命令
安装Xcode 8之后,使用xcodebuild
+xcrun
打包时, 会提示 让我们使用 -exportArchive
命令来构建。
关于 -exportArchive
,在 xcodebuild -help
中有如下提示:
xcodebuild -exportArchive -archivePath <xcarchivepath> -exportPath <destinationpath> -exportOptionsPlist <plistpath>
······
-exportOptionsPlist PATH specifies a path to a plist file that configures archive exporting
如何获取工程的CODE_SIGN_IDENTITY
和PROVISIONING_PROFILE
右键 xxx.xcodeproj
显示包内容 然后打开project.pbxproj
文件
command F
搜索 CODE_SIGN_IDENTITY
和 PROVISIONING_PROFILE
PROVISIONING_PROFILE
使用uuid
或者名称都可以。
因为我这里打包用的Release
模式所以,我在查找CODE_SIGN_IDENTITY
和PROVISIONING_PROFILE
都是找的Release模式配置。
使用atool时 最终输出的xml 中包含 success-message表示成功,如果包含product-errors表示失败。
我们可以将要执行的命令,写进一个shell脚本文件中,这样更方便执行。
给一个文件添加执行权限的命令是:
chmod +x xcodebuild.sh
还有更多其他的文件权限,如 读、写权限。可以看Linux 命令中的 第10条 chmod 命令
进入脚本所在的目录,执行脚本,有两种方式
// 第一种
sh xxxx.sh
// 第二种
./xxxx.sh
脚本中执行if 条件判断的格式:
if []
then
.......//执行的命令
else
.......//执行的命令
fi
完整的脚本如下:
#!/bin/sh
echo "~~~~~~~~~~~~~~~~开始执行脚本~~~~~~~~~~~~~~~~"
# 开始时间
beginTime=`date +%s`
DATE=`date '+%Y-%m-%d-%T'`
#需要编译的 targetName
TARGET_NAME="xxxx"
#编译模式 工程默认有 Debug Release
CONFIGURATION_TARGET=Release
#编译路径
BUILDPATH=~/Desktop/${TARGET_NAME}_${DATE}
#archivePath
ARCHIVEPATH=${BUILDPATH}/${TARGET_NAME}.xcarchive
#输出的ipa目录
IPAPATH=${BUILDPATH}
#证书名
CODE_SIGN_IDENTITY="xxxxx"
#描述文件
PROVISIONING_PROFILE_NAME="xxxx"
#苹果账号
AppleID="xxxx"
AppleIDPWD="xxxx"
#导出ipa 所需plist
ADHOCExportOptionsPlist=./ADHOCExportOptionsPlist.plist
AppStoreExportOptionsPlist=./AppStoreExportOptionsPlist.plist
ExportOptionsPlist=${ADHOCExportOptionsPlist}
# 是否上传蒲公英
UPLOADPGYER=false
# 是否上传AppStore
UPLOADAPPSTore=false
echo "~~~~~~~~~~~~~~~~选择打包方式~~~~~~~~~~~~~~~~"
echo " 1 ad-hoc (默认)"
echo " 2 AppStore "
# 读取用户输入并存到变量里
read parameter
sleep 0.5
method="$parameter"
# 判读用户是否有输入
if [ -n "$method" ]
then
if [ "$method" = "1" ]
then
PROVISIONING_PROFILE_NAME="xxxx"
ExportOptionsPlist=${ADHOCExportOptionsPlist}
elif [ "$method" = "2" ]
then
UPLOADAPPSTore=true
PROVISIONING_PROFILE_NAME="xxxx"
ExportOptionsPlist=${AppStoreExportOptionsPlist}
else
echo "参数无效...."
exit 1
fi
else
ExportOptionsPlist=${ADHOCExportOptionsPlist}
fi
if [ $UPLOADAPPSTore = false ]
then
echo "~~~~~~~~~~~~~~~~是否上传蒲公英~~~~~~~~~~~~~~~~"
echo " 1 不上传 (默认)"
echo " 2 上传 "
read para
sleep 0.5
if [ -n "$para" ]
then
if [ "$para" = "1" ]
then
UPLOADPGYER=false
elif [ "$para" = "2" ]
then
UPLOADPGYER=true
else
echo "参数无效...."
exit 1
fi
else
UPLOADPGYER=false
fi
fi
echo "~~~~~~~~~~~~~~~~开始编译~~~~~~~~~~~~~~~~~~~"
echo "~~~~~~~~~~~~~~~~开始清理~~~~~~~~~~~~~~~~~~~"
# 清理 避免出现一些莫名的错误
xcodebuild clean -workspace ${TARGET_NAME}.xcworkspace \
-configuration \
${CONFIGURATION} -alltargets
echo "~~~~~~~~~~~~~~~~开始构建~~~~~~~~~~~~~~~~~~~"
#开始构建
xcodebuild archive -workspace ${TARGET_NAME}.xcworkspace \
-scheme ${TARGET_NAME} \
-archivePath ${ARCHIVEPATH} \
-configuration ${CONFIGURATION_TARGET} \
CODE_SIGN_IDENTITY="${CODE_SIGN_IDENTITY}" \
PROVISIONING_PROFILE="${PROVISIONING_PROFILE_NAME}"
echo "~~~~~~~~~~~~~~~~检查是否构建成功~~~~~~~~~~~~~~~~~~~"
# xcarchive 实际是一个文件夹不是一个文件所以使用 -d 判断
if [ -d "$ARCHIVEPATH" ]
then
echo "构建成功......"
else
echo "构建失败......"
rm -rf $BUILDPATH
exit 1
fi
endTime=`date +%s`
ArchiveTime="构建时间$[ endTime - beginTime ]秒"
echo "~~~~~~~~~~~~~~~~导出ipa~~~~~~~~~~~~~~~~~~~"
beginTime=`date +%s`
xcodebuild -exportArchive \
-archivePath ${ARCHIVEPATH} \
-exportOptionsPlist ${ExportOptionsPlist} \
-exportPath ${IPAPATH}
echo "~~~~~~~~~~~~~~~~检查是否成功导出ipa~~~~~~~~~~~~~~~~~~~"
IPAPATH=${IPAPATH}/${TARGET_NAME}.ipa
if [ -f "$IPAPATH" ]
then
echo "导出ipa成功......"
else
echo "导出ipa失败......"
# 结束时间
endTime=`date +%s`
echo "$ArchiveTime"
echo "导出ipa时间$[ endTime - beginTime ]秒"
exit 1
fi
endTime=`date +%s`
ExportTime="导出ipa时间$[ endTime - beginTime ]秒"
# 上传AppStore
if [ $UPLOADAPPSTore = true ]
then
altoolPath="/Applications/Xcode.app/Contents/Applications/Application\ Loader.app/Contents/Frameworks/ITunesSoftwareService.framework/Versions/A/Support/altool"
${altoolPath} --validate-app \
-f ${IPAPATH} \
-u ${AppleID} \
-p ${AppleIDPWD} \
-t ios --output-format xml
if [ $? = 0 ]
then
echo "~~~~~~~~~~~~~~~~验证ipa成功~~~~~~~~~~~~~~~~~~~"
${altoolPath} --upload-app \
-f ${IPAPATH} \
-u ${AppleID} \
-p ${AppleIDPWD} \
-t ios --output-format xml
if [ $? = 0 ]
then
echo "~~~~~~~~~~~~~~~~提交AppStore成功~~~~~~~~~~~~~~~~~~~"
else
echo "~~~~~~~~~~~~~~~~提交AppStore失败~~~~~~~~~~~~~~~~~~~"
fi
else
echo "~~~~~~~~~~~~~~~~验证ipa失败~~~~~~~~~~~~~~~~~~~"
fi
else
# 上传蒲公英
if [ $UPLOADPGYER = true ]
then
echo "~~~~~~~~~~~~~~~~上传ipa到蒲公英~~~~~~~~~~~~~~~~~~~"
curl -F "file=@$IPAPATH" \
-F "uKey=xxxxx" \
-F "_api_key=xxxx" \
-F "password=xxxxx" \
-F "isPublishToPublic=xxxx" \
https://www.pgyer.com/apiv1/app/upload --verbose
if [ $? = 0 ]
then
echo "~~~~~~~~~~~~~~~~上传蒲公英成功~~~~~~~~~~~~~~~~~~~"
else
echo "~~~~~~~~~~~~~~~~上传蒲公英失败~~~~~~~~~~~~~~~~~~~"
fi
fi
fi
echo "~~~~~~~~~~~~~~~~配置信息~~~~~~~~~~~~~~~~~~~"
echo "开始执行脚本时间: ${DATE}"
echo "编译模式: ${CONFIGURATION_TARGET}"
echo "导出ipa配置: ${ExportOptionsPlist}"
echo "打包文件路径: ${ARCHIVEPATH}"
echo "导出ipa路径: ${IPAPATH}"
echo "$ArchiveTime"
echo "$ExportTime"
exit 1
iOS 应用打包命令一览的更多相关文章
- 关于 iOS 批量打包的总结
关于 iOS 批量打包的总结 本文作者: 伯乐在线 - Tsui YuenHong .未经作者许可,禁止转载!欢迎加入伯乐在线 专栏作者. 如果你曾经试过做多 target 的项目,到了测试人员要 ...
- ios自动打包-fastlane 安装、使用、更新和卸载
ios自动打包使用fastlane 1.首先安装xcode 首先检查是否已经安装 Xcode 命令行工具,fastlane 使用 xcodebuild 命令进行打包,运行 xcode-select - ...
- 40、IOS自动打包-Python脚本
第一种:基于编译的打包 编译工程--找到.app文件--新建Payload文件夹--拷贝.app到Payload文件夹--压缩成zip--更改后缀名为ipa--完成! 第二种(有问题,暂时不需要看) ...
- 如何将 iOS 工程打包速度提升十倍以上
如何将 iOS 工程打包速度提升十倍以上 过慢的编译速度有非常明显的副作用.一方面,程序员在等待打包的过程中可能会分心,比如刷刷朋友圈,看条新闻等等.这种认知上下文的切换会带来很多隐形的时间浪费. ...
- 使用BUCK进行iOS项目打包
关于BUCK BUCK是Facebook开源的快速打包工具,可以用于多种语言及平台的项目打包,例如:C.C++.Java.iOS.Android等等.用于大型的iOS.Android项目,可以显著提升 ...
- IOS自动化打包介绍
IOS自动化打包介绍 标签: app打包 , Ios打包 , iphone打包 , iphone自动化打渠道包 分类:无线客户端技术, 贴吧技术 摘要 随着苹果手持设备用户的不断增加,ios应 ...
- iOS自动化打包上传的踩坑记
http://www.cocoachina.com/ios/20160624/16811.html 很久以前就看了很多关于iOS自动打包ipa的文章, 看着感觉很简单, 但是因为一直没有AppleDe ...
- iOS 自动化打包发布(Fastlane+ Jenkins+蒲公英)
安装 Xcode 命令行工具:xcode-select --install 安装 fastlane:sudo gem install fastlane --verbose 安装成功后查看版本:fast ...
- Mac Jenkins+fastlane 简单几步实现iOS自动化打包发布 + jenkins节点设置
最近在使用jenkins 实现ios自动化打包发布蒲公英过程实践遇到了一些坑,特意记录下来方便有需要的人. 进入正题: 一.安装Jenkins 1.Mac上安装Jenkins 遇到到坑 因为 Jenk ...
随机推荐
- SQL类型注入
前言: 继续进行未完成的sql注入学习 今天学习了各类型注入.前来进行总结. 目录: 数字型注入 字符型注入 提交注注入 GET注入 POST注入 COOKIE注入 正文: 数字型注入:www.xxx ...
- 拿来主义:layPage分页插件的使用
布衣之谈 所谓插件,大概就是项目中可插可拔的比较小功能化的组件:这些功能组件若能力可及,自己也可以完成——也即自己造轮子,但翻看各种技术社区,相关领域的神人们往往会有更好的实现方案贡献出来,这个时候你 ...
- iframe交互(一)父页面自动高度
//父页面源码 <body style="border:1px solid red;width:200px;height:500px;" onload="IFram ...
- java四种访问控制权限:public ,default,protected,private
四种访问权限的控制 范围 private default protected public 同一个类中 √ √ √ √ 相同包不同类 × √ √ √ 不同包的子类中 × × √ √ 不同包非子类 × ...
- linux 基本使用命令
arch 显示机器的处理器架构(1) uname -m 显示机器的处理器架构(2) uname -r 显示正在使用的内核版本 dmidecode -q 显示硬件系统部件 - (SMBIOS / DMI ...
- [COGS 2287][HZOI 2015]疯狂的机器人
Description 题库链接 现在在二维平面内原点上有一只机器人,他每次可以选择向右走,向左走,向下走,向上走和不走(每次如果走只能走一格).机器人不能走到横坐标是负数或者纵坐标是负数的点上. 给 ...
- 素数密度_NOI导刊2011提高(04)
题目描述 给定区间[L, R](L <= R <= 2147483647,R-L <= 1000000),请计算区间中素数的个数. 输入 两个数 L 和 R. 输出 一行,区间中素数 ...
- 【LSGDOJ1836】: 量化交易 贪心
题目描述 applepi 训练了一个可以自动在股票市场进行量化交易的模型.通常来说,applepi 写出的模型,你懂得,就好比一架印钞机.不过为了谨慎起见,applepi还是想先检查一下模型的效果.a ...
- POJ2774 很长的信息
Description Little cat在Byterland的首都读物理专业.这些天他收到了一条悲伤地信息:他的母亲生病了.担心买火车票花钱太多(Byterland是一个巨大的国家,因此他坐火车回 ...
- ●BZOJ 2251 [2010Beijing Wc]外星联络
题链: http://www.lydsy.com/JudgeOnline/problem.php?id=2251 题解: 后缀数组,倍增,RMQ 题意:把重复次数超过 1次的子串按字典序输出它们重复的 ...