美文网首页证书、上架相关
iOS批量打包(shell)

iOS批量打包(shell)

作者: JesnLu | 来源:发表于2017-09-06 14:21 被阅读47次

    写在前面

    相信很多做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的可以自己添加。

    要结束了

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

    相关文章

      网友评论

        本文标题:iOS批量打包(shell)

        本文链接:https://www.haomeiwen.com/subject/tbsmjxtx.html