iOS批量打包(shell)

写在前面

相信很多做APP开发的朋友都经历过这种情况:开发完成进入测试阶段会有很多各种的ipa包需要build,如果公司有个好的体贴的QA的话,那可以把打包的工作交给他,如果没有就只能开发来做了!什么开发版的正式服、测试服ipa,什么企业版的正式服、测试服ipa,什么...... 如果用XCode自带Archive的话我们需要点点点,期间还得等等等,然后还得上传各种ftp,蒲公英,etc. 所以有个脚本来帮助一次性打包并上传是极好的。

XCode打包

首先

在开发者网站注册APPID并且生成称对应的证书,描述文件,并且将证书和描述文件下载下来,证书导入钥匙串,描述文件导入XCode。至于怎么生成证书和描述文件就不啰嗦啦。

然后

在xcodeproj

  • ->General 配置好设置的APPID,选择对应的Team(如果不勾选xcode自动管理签名可不用填)
  • ->BuildSettings->Signing 配置好对应的Debug、Release证书
  • ->Scheme->Edit Scheme 选择对应的的Debug或者Release
  • ->调整好其他一些配置属性,比如:版本号,一些自定义宏等

最后

  • ->Product-Archive wait。。。。。。
  • ->Archive完成一般会有选择是Upload App Store还是选择Export,通常来说还是Export个ipa到本地
  • ->Export 选择是生成何种类型的ipa,有四个选项根据需要选择,如果需要多种选择可以直接重复Export,不用重新Archive
  • ->选择ipa类型,选择对应的Team,Next,Next,wait。。。选择存储位置,Export

Shell脚本

像这样一步一步配置,一步一步点击,还得wait,还得rebuild,again,again。。。像这种频繁手动修改配置是很不安全滴,作为一个开发者,时间很宝贵的好伐,这种重复的劳动完全可以省略嘛。

是时候说到正题了

首先

分析一下脚本需要做的工作有哪些:

  • 修改General配置
  • 修改自定义的一些配置
  • 修改BuildSetting配置
  • 修改Scheme-Archive-Build Configuration
  • 执行Archive
  • 选择Export类型 设置存储位置

然后

针对各种工作做出应对

  • 利用PlistBuddy
    General配置和一些自定义配置都可以放置在Plist文件里面进行,这样看起来清晰明了减少出错。在修改这些配置的时候我们可以利用Mac自带的PlistBuddy。
    针对不同的配置我们可以创建不同的配置文件,然后遍历这些文件,一个配置文件打次包就好了
  • xcodebuild
    xcodebuild命令是本脚本的主要部分,通过修改其参数可以对BuildSettings以及Scheme、Target等进行配置

干就完了

  • 熟悉了解PlistBuddy用法
    在终端中输入/usr/libexec/PlistBuddy --help查看,比较简单,细心可看懂。
  • 创建文件结构



    其中build.sh是执行脚本,module文件夹很显然里面放置的是不同的配置啦,各个配置下的config.plist是要修改的配置,里面包含各个要修改的属性;exportPlist.plist是必须要有的配置文件,可以为空,但必须有;xxxx.mobileprovision是各个配置对应的描述文件,如果使用xcode里面配置的可以没有。

  • 开始Coding
  1. 创建一些全局方便使用,比如PlistBuddy位置,xcodebuild位置等
plistBuddy="/usr/libexec/PlistBuddy"           #PlistBuddy位置
xcodebuild="/usr/bin/xcodebuild"               #xcodebuild位置
security="/usr/bin/security"                   #security 用来访问钥匙串
codesign="/usr/bin/codesign"                   #签名工具
shellPath=`pwd`                                #当前路径
projectPath="$shellPath/.."                    #工程路径
pbxprojFile=''                                 #xcodeproj文件路径
projTypeIsWorkSpace=true                       #工程文件类型 默认.xcworkspace
buildTime=$(date +%Y-%m-%d-%H-%M)              #时间
  1. 既然我们要对xcode项目进行打包,那么我们首先要得有.xcodeproj文件吧,工程文件都没有还打个毛线包啊!
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 应该带有.xcodeproj文件扩展,.${projectExtension}不是一个Xcode project扩展!"
    exit 1
else
    pbxprojFile="$xcodeProject/project.pbxproj"
    if [[ ! -f "$pbxprojFile" ]]; then
        echo "项目文件:\"$pbxprojFile\" 不存在"
        exit 1;
    fi
    echo "发现pbxproj:$pbxprojFile"
fi

  1. 由于现在许多工程都是通过workSpace来进行管理的,所以需要先检查判断是否是workspace工程
# 这里通过在.xcodeproj文件所在文件夹下是否有以.xcworkspace后缀的文件来判断
xcworkspace=`find "$xcodeProject/.." -maxdepth 1  -type d -name "*.xcworkspace"`
if [[ -d "$xcworkspace" ]]; then
    projTypeIsWorkSpace=true
    echo "发现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管理代码的所以执行svn update 可能需要输入svn密码,然后获取到svnVersion是用来标记代码版本。

  1. 是时候表演真正的技术了
    此处是脚本的主要部分,主要有一下几个部分:
    遍历module文件夹获取各个配置里面的config文件;
    根据配置文件利用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内容
    if [[ -f "$infoPlistPath" ]]; then
        if [[ "$appVersion" != '' ]]; then
            $plistBuddy -c "Set :CFBundleShortVersionString $appVersion" "$infoPlistPath"
        fi
    fi

上面是根据config.plist来修改Info.plist的例子

# ===========   keychain 授权 =====================#
    #允许访问证书
    $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
# =================================================#

上面是用来获取钥匙串的授权的,其中loginPwd是在config里面配置读取的。不进行授权有可能会影响证书的访问,导致打包失败。

#==============检查证书和描述文件====================#
    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
# =================================================#

对于自定义证书和描述文件的如果查找不到就会构建失败。

# ===============检查构建ipa存放路径=================#
    savePath=$projectPath/build/$buildTime
    if [[ ! -d "$projectPath/build" ]]; then
        mkdir $projectPath/build
    fi
    if [[ ! -d "$savePath" ]]; then
        mkdir $savePath
    fi
# =================================================#

马上就要出货了,出货之前一定要准备好放货的地方吧。我是根据时间生成一个文件夹,然后里面的ipa根据不同配置命名不同。

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参数,exportArchive。
如果是workspace工程只需要修改project参数为workspace即可,如下例

        xcodebuild clean -workspace "${xcworkspace}" -scheme "${schemeName}" -configuration "${buildConfiguration}" -sdk $sdk

关于更多xcodebuild的参数配置可以通过在终端中输入xcodebuild -help查看。

if [[ $ftp != '' ]];then
        echo "***开始上传ipa到ftp服务器***"
        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服务器***"
        fi

最后一步上传ftp了,由于我们使用ftp提供测试下载安装。其他上传蒲公英或者App Store的可以自己添加。

要结束了

脚本比较长,格式有点乱,主要是给大家提供个思想,大家可以参考下写出自己的更完美更漂亮的。
如果有了更好的请一定要@我去学啊。[笑脸]

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

推荐阅读更多精彩内容