iOS批量打包(shell)

寫在前面

相信很多做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
  1. 創(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)              #時間
  1. 既然我們要對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

  1. 由于現(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
  1. 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)記代碼版本。

  1. 是時候表演真正的技術(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é)啊。[笑臉]

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容