iOS打包ipa

iOS打包ipa


    iOS打包,无论是从平时的测试包,还是提交AppStore的正式包,或者企业包,每个开发都离不开打包。回想一下当初刚刚做开发时候还不知道如何将.app打包成ipa文件,感觉too young too simple。鉴于最近进化之地2的上线,让我又想起了该游戏的剧情,那么我现在也结合自己的经历,来说说自己的iOS打包史吧。

手动build时代

    刚刚工作的时候,也是没见过什么世面,在加上组内就我一个做iOS的,也没什么人可以交流,所以在打包这块,一直都是手动打包。我们知道iOS应用在普通build的时候产生的是.app,我们要提交测试的时候,需要选择好真机设备,通过Command+shift+I,进行一次Release build。之后在XCode的左侧项目导航栏的Products中右键XXX.app,选择show in Finder,然后再退到上一级目录,进入Release-iphoneos,中看到了XXX.app以及对应的符号表文件。

接下来就是把.app变成ipa的奇迹时刻了,当然这里有很多旁门左道。

  1. 新建一个文件夹名称叫"Payload",并且将.app拷贝到这个文件夹下面,压缩文件夹,修改后缀名为.ipa即可大功告成
  2. 将.app拖入itunes中,在itunes的应用中找到对应的app,再点击app拖出到桌面即可(目前itunes已经没有应用程序这一栏,该方法已不可用)
  3. XCode7及以前时代,可以通过Alcatraz给XCode安装AMAppExportToIPA插件,安装完在XCode的左侧项目导航栏Products中,右键XXX.app后,选择Export IPA即可。当然在这之前,需要修改scheme中的build configuration为Release。

这样大概就是之前打测试包的流程,全手工打造,无任何杂质。之后跟其他部门的同事交流了一下,发现可以通过命令行打包,于是就进入了下一个时代。

命令行打包时代

相信大家对于Makefile并不陌生,在学习Linux的时候就接触过,但是总是觉得设置make脚本很麻烦,况且当时都是基本上都是几个源文件的工程,而现在到了iOS打包,工程目录那么多,依赖库也不少,自己手写Makefile那不得累死。其实自己当时完全多虑了,XCode提供的命令行工具,几乎解决了所有能想到的问题,那么就开始打包吧。

  1. 首先执行Release Build
xcodebuild -project XXX.xcodeproj -sdk iphoneos -configuration Release;

这样就完事了,是不是so easy。

  1. 然后在工程根目录下找到./build/elease-iphoneos/目录,将XXX.app找到放到Payload目录下,通过zip命令生成ipa。
  2. 接着就是把ipa和符号表文件放到一个你想放到的目录下就好了。

打包就这么简单,不过这里面还有打包的命名,我们是通过应用名-版本号-日期-build号来命名的。

下面是打包的源码(XXX为工程名,我们代码管理是通过svn,所以REVISION获取的是svn版本号)。

BASE_NAME=XXX

MAIN_VERSION=4.1.0

DATE=$(shell date +%Y%m%d)

REVISION = $(shell svn info ./|grep "Last Changed Rev: "|cut -c 19-)

VERSION = $(MAIN_VERSION)-$(DATE)-$(REVISION)

PACKAGE = $(BASE_NAME)-$(VERSION)

PACKAGE_VERSION = $(BASE_NAME)-$(MAIN_VERSION)-$(REVISION)

DEST_DIR=$(shell pwd)

.PHONY: all build clean

all: build

build:

    sudo xcode-select -switch /Applications/Xcode.app/Contents/Developer;

    xcodebuild -project $(BASE_NAME).xcodeproj -sdk iphoneos -configuration Release;

    rm -rf ./build/ipa_dsym;

    mkdir -p ./build/ipa_dsym/Payload;

    cp -r ./build/Release-iphoneos/$(BASE_NAME).app ./build/ipa_dsym/Payload/$(BASE_NAME).app

    cd build/ipa_dsym;zip -rq $(PACKAGE).ipa ./Payload/;rm -rf ./Payload/;cd -;

    cd ./build/Release-iphoneos;zip -rq $(PACKAGE_VERSION).dSYM.zip ./$(BASE_NAME).app.dSYM/;mv -f ./$(PACKAGE_VERSION).dSYM.zip ../ipa_dsym/;cd -;

    cd ./build/Release-iphoneos;zip -rq iMessageExt-$(PACKAGE_VERSION).dSYM.zip iMessageExt.appex.dSYM/;mv -f ./iMessageExt-$(PACKAGE_VERSION).dSYM.zip ../ipa_dsym/;cd -;

c:clean

clean:

    rm -rf build;

    目前这样搞定了打包的问题,但是程序的build号还是需要手动设置,不要紧,上面makfile脚本都可以拿到svn的版本号,那么在build的时候,通过脚本设置svn的版本号为应用的版本号不就OK了么,具体操作如下:

    在XCode中点击工程,选择Build Phases,点击导航栏Editor->Add build phase->Add Run Script Build Phase,然后再里面添加两行代码,这样就不需要手动设置build号了。

扫描二维码关注公众号,回复: 1426015 查看本文章
svnv=`svnversion -c |sed 's/^.*://' |sed 's/[A-Z]*$//'`

#svn info ./|grep "Last Changed Rev: "|cut -c 19- makefile里面的获取svn版本号方式也可以

/usr/libexec/PlistBuddy -c "Set :CFBundleVersion ${svnv}" "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}"

    其实接下来还涉及到一个问题,就是在提测试计划的时候,需要将svn上的代码修改日志附上,既然都到了命令行时代,那么就通过一个脚本搞定吧。

#!/bin/bash

#使用说明:
#1.输入上一次发包的build号,脚本会自动将其+1作为起始build号,取最新svn版本为结束build号来获取log
#2.输入两个build号,脚本会取出这两个build号之间(包含这两个build号)的log


# Check parameters
from="$1"
if [ -z "$from" ]; then
    echo "Please specify the correct begin revision"
    exit
fi

from=`echo $((from+1))`

to="$2"
if [ -z "$to" ]; then
    echo "Executing 'svn update', please wait..."
    to=`svn up|awk '/At revision/{print $3}'|sed 's/\.//'`
    if [ $from -gt $to ]; then
        echo "Begin revision($from) should be less than end revision($to). Please specify the correct end revision"
        echo "Failed!!"
        exit
    fi
else
    from=`echo $((from-1))`
    echo $from
fi

# Generate log description
echo "Checking logs from build $from to $to..."

svn log -r $from:$to |awk '
BEGIN {
    i=1
    flag=0
    begin=0
    print "============================"
}
{
    if ($0 ~ /r[0-9]* \|/) {
        flag=1;
        next
    }

    if ($0 ~ /-----$/) {
        flag=0
        next
    }

    if (flag) {
        if (NF >= 1) { print i ". " $0; i++; }
    }
}
'

这样就可以通过命令得到全部的更新日志啦

    就这样从手动build时代,变成了Makefile一键打包,bash脚本一键获取更新日志了。感觉妈妈再也不用担心我打包需要十分钟了,运行俩脚本搞定,之后拿到ipa包提测就好了。日子就这样美滋滋的过着,直到项目组终于来人了,多个人都需要打包。那好,那就提供一个打包平台吧。于是乎,再次进入了一个新的时代。

Jenkins+fir.im时代

    Jenkins是一个开源软件项目,是基于Java开发的一种持续集成工具,用于监控持续重复的工作,旨在提供一个开放易用的软件平台,使软件的持续集成变成可能。

    在测试阶段,每天都需要打包提测。通过Jenkins部署上环境,每天早上定时打包,这样每天早上到了公司,就有现成的包,可以进行提测,这样不就是更美了么。

于是开始部署Jenkins(这里省略安装)

  1. 新建->选择构建一个自由风格的软件项目

之后进入配置页面

这里基本上不用管,如果你有强迫症,不想要在本地生成很多构建的话,可以选择丢弃旧的构建,来设置保持构建的天数以及保持构建的最大个数

  1. 源码管理,根据自己的实际情况来选择,配置好
  2. 设置构建触发器,也可以通过自己的实际情况来选择,我们是一天一次自动打包(当然也可以手动构建),配置个每天大概9点打包就可以了。 点这里了解触发器

  3. 构建环境跳过,直接看构建

还记得上面提到的Makefile脚本么?在这里再次排上用途了。添加构建步骤选择Execute shell,写个两句代码。

  1. 构建后选择Archive the artifacts

这里就是需要把ipa和符号表文件添加到构建结果中,这样可以在jenkins中备份并下载。还记得Makefile中把ipa放到哪里了,就填写该目录就好了

基本上正常的构建就是这样,构建完成之后,可以看到构建结果

接下来说下fir.im的事情,fir.im是一个分发平台,可以把测试包放上去,提供测试短链接在iPhone上直接安装即可。这个平台的优势就是不需要电脑即可安装ipa。(通过的是itms-services来安装的,搞过企业包的同学应该不会陌生,很简单,之前做过,需要一个plist、一个html即可,具体可以 戳这里)

Fir.im提供了Jenkins的插件,可以在打包之后,直接上传。具体方法可以看 fir.im的 官方文档。但每次都上传,显然并不需要。所以我们可以做一个jenkins可配置的构建。这里需要先安装fir.im的 命令行程序,并且在fir.im网站上获取app token。接下来就是配置过程:

  1. 配置参数化构建过程,选择Boolean Parameter,并且配置如下

  2. 修改构建脚本

等一下 make i是什么鬼?

要想知道make i,那先来看看fir上传这句代码,不难理解,publish是发布后面接着ipa的地址,所以make i要获取的就是ipa的名字,由于ipa的名字不是固定,所以需要Makefile提供一个方式来得到ipa的名字,具体如下(Makefile中):

i:info

info:

 @echo $(PACKAGE).ipa;

通过echo前加@是为了不把这行执行的代码也打印出来,这样就能打印出ipa的名字,得到名字后,上传即可。当然如果需要获取svn日志,也可以写一个相关的功能来获取svn的日志,并且放到fir命令的-c参数的后面。

目前我们的打包的进化就告一段落了,目前觉得这样打包还没有什么太大问题,每次进化都要比之前省事一些。

总结

打包其实是一个重复,但不复杂的过程,但如果手动打包,肯定是非常枯燥无味的。自动化打包是一件很幸福的事情,目前我们的自动化打包方案就介绍到这里。我相信打包肯定还可以继续优化,如果你有更优化的打包方案,不妨分享一下吧。

文中涉及文献

  1. http://blog.sina.com.cn/s/blog_71bc9d680102x0n1.html
  2. http://blog.csdn.net/qq_37586205/article/details/58597857
  3. http://blog.fir.im/jenkins/
  4. https://github.com/FIRHQ/fir-cli/blob/master/README.md

猜你喜欢

转载自blog.csdn.net/tugele/article/details/79501611