
寫在前面
相信很多做APP開發(fā)的朋友都經(jīng)歷過這種情況:開發(fā)完成進(jìn)入測試階段會有很多各種的ipa包需要build,如果公司有個好的體貼的QA的話,那可以把打包的工作交給他,如果沒有就只能開發(fā)來做了!什么開發(fā)版的正式服、測試服ipa,什么企業(yè)版的正式服、測試服ipa,什么...... 如果用XCode自帶Archive的話我們需要點點點,期間還得等等等,然后還得上傳各種ftp,蒲公英,etc. 所以有個腳本來幫助一次性打包并上傳是極好的。
XCode打包
首先
在開發(fā)者網(wǎng)站注冊APPID并且生成稱對應(yīng)的證書,描述文件,并且將證書和描述文件下載下來,證書導(dǎo)入鑰匙串,描述文件導(dǎo)入XCode。至于怎么生成證書和描述文件就不啰嗦啦。
然后
在xcodeproj
- ->General 配置好設(shè)置的APPID,選擇對應(yīng)的Team(如果不勾選xcode自動管理簽名可不用填)
- ->BuildSettings->Signing 配置好對應(yīng)的Debug、Release證書
- ->Scheme->Edit Scheme 選擇對應(yīng)的的Debug或者Release
- ->調(diào)整好其他一些配置屬性,比如:版本號,一些自定義宏等
最后
- ->Product-Archive wait。。。。。。
- ->Archive完成一般會有選擇是Upload App Store還是選擇Export,通常來說還是Export個ipa到本地
- ->Export 選擇是生成何種類型的ipa,有四個選項根據(jù)需要選擇,如果需要多種選擇可以直接重復(fù)Export,不用重新Archive
- ->選擇ipa類型,選擇對應(yīng)的Team,Next,Next,wait。。。選擇存儲位置,Export
Shell腳本
像這樣一步一步配置,一步一步點擊,還得wait,還得rebuild,again,again。。。像這種頻繁手動修改配置是很不安全滴,作為一個開發(fā)者,時間很寶貴的好伐,這種重復(fù)的勞動完全可以省略嘛。
是時候說到正題了
首先
分析一下腳本需要做的工作有哪些:
- 修改General配置
- 修改自定義的一些配置
- 修改BuildSetting配置
- 修改Scheme-Archive-Build Configuration
- 執(zhí)行Archive
- 選擇Export類型 設(shè)置存儲位置
然后
針對各種工作做出應(yīng)對
- 利用PlistBuddy
General配置和一些自定義配置都可以放置在Plist文件里面進(jìn)行,這樣看起來清晰明了減少出錯。在修改這些配置的時候我們可以利用Mac自帶的PlistBuddy。
針對不同的配置我們可以創(chuàng)建不同的配置文件,然后遍歷這些文件,一個配置文件打次包就好了 - xcodebuild
xcodebuild命令是本腳本的主要部分,通過修改其參數(shù)可以對BuildSettings以及Scheme、Target等進(jìn)行配置
干就完了
- 熟悉了解PlistBuddy用法
在終端中輸入/usr/libexec/PlistBuddy --help查看,比較簡單,細(xì)心可看懂。 -
創(chuàng)建文件結(jié)構(gòu)
其中build.sh是執(zhí)行腳本,module文件夾很顯然里面放置的是不同的配置啦,各個配置下的config.plist是要修改的配置,里面包含各個要修改的屬性;exportPlist.plist是必須要有的配置文件,可以為空,但必須有;xxxx.mobileprovision是各個配置對應(yīng)的描述文件,如果使用xcode里面配置的可以沒有。
- 開始Coding
- 創(chuàng)建一些全局方便使用,比如PlistBuddy位置,xcodebuild位置等
plistBuddy="/usr/libexec/PlistBuddy" #PlistBuddy位置
xcodebuild="/usr/bin/xcodebuild" #xcodebuild位置
security="/usr/bin/security" #security 用來訪問鑰匙串
codesign="/usr/bin/codesign" #簽名工具
shellPath=`pwd` #當(dāng)前路徑
projectPath="$shellPath/.." #工程路徑
pbxprojFile='' #xcodeproj文件路徑
projTypeIsWorkSpace=true #工程文件類型 默認(rèn).xcworkspace
buildTime=$(date +%Y-%m-%d-%H-%M) #時間
- 既然我們要對xcode項目進(jìn)行打包,那么我們首先要得有.xcodeproj文件吧,工程文件都沒有還打個毛線包?。?/li>
if [[ "$xcodeProject" == '' ]]; then
xcodeProject=`find "$projectPath" -maxdepth 1 -type d -name "*.xcodeproj"`
fi
projectExtension=`basename "$xcodeProject" | cut -d'.' -f2`
if [[ "$projectExtension" != "xcodeproj" ]]; then
echo "Xcode project 應(yīng)該帶有.xcodeproj文件擴(kuò)展,.${projectExtension}不是一個Xcode project擴(kuò)展!"
exit 1
else
pbxprojFile="$xcodeProject/project.pbxproj"
if [[ ! -f "$pbxprojFile" ]]; then
echo "項目文件:\"$pbxprojFile\" 不存在"
exit 1;
fi
echo "發(fā)現(xiàn)pbxproj:$pbxprojFile"
fi
- 由于現(xiàn)在許多工程都是通過workSpace來進(jìn)行管理的,所以需要先檢查判斷是否是workspace工程
# 這里通過在.xcodeproj文件所在文件夾下是否有以.xcworkspace后綴的文件來判斷
xcworkspace=`find "$xcodeProject/.." -maxdepth 1 -type d -name "*.xcworkspace"`
if [[ -d "$xcworkspace" ]]; then
projTypeIsWorkSpace=true
echo "發(fā)現(xiàn)xcworkspace:$xcworkspace"
else
projTypeIsWorkSpace=false;
fi
- update到最新代碼(手動更新可以刪除此段)
cd ..
echo ${pwd}
svn update
svnVersion=`svnversion |sed 's/^.*://' |sed 's/[A-Z]*$//'`
echo $svnVersion
先cd到工程所在路徑,由于我們是svn管理代碼的所以執(zhí)行svn update 可能需要輸入svn密碼,然后獲取到svnVersion是用來標(biāo)記代碼版本。
- 是時候表演真正的技術(shù)了
此處是腳本的主要部分,主要有一下幾個部分:
遍歷module文件夾獲取各個配置里面的config文件;
根據(jù)配置文件利用PlistBuddy修改配置;
clean工程;
Build工程;
export
for y in $shellPath/module/*;
do
#==============讀取config文件====================#
configFile=$y/config.plist
if [[ "$configFile" == '' ]]; then
echo "未找到config.plist文件!"
exit 1
fi
echo "找到config.plist文件"
configurations=`"$plistBuddy" -c "print :" "$configFile"`
echo "$configurations"
appVersion=`"$plistBuddy" -c "print :appVersion:" "$configFile"`
上面是遍歷module和讀取config.plist以及其中各個key的值。
projectName=$(basename "$xcodeProject" .xcodeproj)
infoPlistPath=$projectPath/$projectName/Info.plist
echo "infoPlistPath = $infoPlistPath"
#修改Info.plist內(nèi)容
if [[ -f "$infoPlistPath" ]]; then
if [[ "$appVersion" != '' ]]; then
$plistBuddy -c "Set :CFBundleShortVersionString $appVersion" "$infoPlistPath"
fi
fi
上面是根據(jù)config.plist來修改Info.plist的例子
# =========== keychain 授權(quán) =====================#
#允許訪問證書
$security unlock-keychain -p $loginPwd "$HOME/Library/Keychains/login.keychain" 2>/tmp/log.txt
if [[ $? -ne 0 ]]; then
echo "security unlock-keychain 失敗!請檢查配置密碼是否正確"
exit 1
fi
$security unlock-keychain -p $loginPwd "$HOME/Library/Keychains/login.keychain-db" 2>/tmp/log.txt
if [[ $? -ne 0 ]]; then
echo "security unlock-keychain 失敗!請檢查配置密碼是否正確"
exit 1
fi
# =================================================#
上面是用來獲取鑰匙串的授權(quán)的,其中l(wèi)oginPwd是在config里面配置讀取的。不進(jìn)行授權(quán)有可能會影響證書的訪問,導(dǎo)致打包失敗。
#==============檢查證書和描述文件====================#
profileUUID=''
if [[ "$profileName" != "" ]]; then
profilePath=$y/$profileName.mobileprovision
if [[ ! -f "$profilePath" ]]; then
echo "描述文件 $profilePath 不存在!"
exit 1
fi
profileUUID=`$plistBuddy -c 'Print :UUID' /dev/stdin <<< $($security cms -D -i "$profilePath" 2>/tmp/log.txt)`
echo "描述文件UUID $profileUUID"
fi
# =================================================#
對于自定義證書和描述文件的如果查找不到就會構(gòu)建失敗。
# ===============檢查構(gòu)建ipa存放路徑=================#
savePath=$projectPath/build/$buildTime
if [[ ! -d "$projectPath/build" ]]; then
mkdir $projectPath/build
fi
if [[ ! -d "$savePath" ]]; then
mkdir $savePath
fi
# =================================================#
馬上就要出貨了,出貨之前一定要準(zhǔn)備好放貨的地方吧。我是根據(jù)時間生成一個文件夾,然后里面的ipa根據(jù)不同配置命名不同。
exportPlistPath=$y/exportPlist.plist
if [[ "$exportPlistPath" == '' ]]; then
echo "未找到exportPlist.plist文件!"
exit 1
fi
再檢查下必須的exportPlist.plist文件在不在。
if [[ $projTypeIsWorkSpace != true ]]; then
echo '*** 正在 清理工程 ***'
xcodebuild clean -project "${xcodeProject}" -scheme "${schemeName}" -configuration "${buildConfiguration}" -sdk $sdk
echo '*** 清理完成 ***'
echo '*** 正在 archive ***'
cmd="xcodebuild archive -archivePath ${savePath}/${schemeName}-${buildConfiguration}.xcarchive -project "${xcodeProject}" -scheme "${schemeName}" -configuration "${buildConfiguration}" -sdk $sdk"
if [[ $profileUUID != '' ]];then
cmd="$cmd" PROVISIONING_PROFILE="${profileUUID}"
fi
if [[ $certificateName != '' ]];then
cmd="$cmd" PROVISIONING_PROFILE="${profileUUID}" CODE_SIGN_IDENTITY="${certificateName}"
fi
if [[ $teamID != '' ]];then
cmd="$cmd" DEVELOPMENT_TEAM="${teamID}"
fi
$cmd
echo '*** archive done***'
echo '*** 正在 exportArchive ***'
xcodebuild -exportArchive -archivePath ${savePath}/${schemeName}-${buildConfiguration}.xcarchive \
-configuration "${buildConfiguration}" \
-exportPath ${savePath} \
-exportOptionsPlist ${exportPlistPath} \
-quiet || exit
echo '*** exportArchive done***'
上面是利用xcodebuild對xcodeproj打包的主要部分,包括clean,修改Archive參數(shù),exportArchive。
如果是workspace工程只需要修改project參數(shù)為workspace即可,如下例
xcodebuild clean -workspace "${xcworkspace}" -scheme "${schemeName}" -configuration "${buildConfiguration}" -sdk $sdk
關(guān)于更多xcodebuild的參數(shù)配置可以通過在終端中輸入xcodebuild -help查看。
if [[ $ftp != '' ]];then
echo "***開始上傳ipa到ftp服務(wù)器***"
ftp -niv<<-!
open 192.168.255.22 8888
user xxxx xxxxx
binary
hash
cd ${ftp}
lcd ${savePath}
prompt
put ${schemeName}${buildConfiguration}.ipa
close
bye
!
echo "***完成上傳ipa到ftp服務(wù)器***"
fi
最后一步上傳ftp了,由于我們使用ftp提供測試下載安裝。其他上傳蒲公英或者App Store的可以自己添加。
要結(jié)束了
腳本比較長,格式有點亂,主要是給大家提供個思想,大家可以參考下寫出自己的更完美更漂亮的。
如果有了更好的請一定要@我去學(xué)啊。[笑臉]
