您的位置:首页 > 移动开发 > IOS开发

iOS自动打包[转载]

2016-04-19 08:57 489 查看

敲一下enter键,完成iOS的打包工作[转载]

http://ios.jobbole.com/84677/

作为开发人员,免不了要为测试人员打包,让其测试。而打包这个行为是非常无聊的,特别是在每个新版本上线前一两天,总会出现一些莫名其妙的
bug
,然后这两天打包活动也是特别频繁。一天要重复好几次同样的动作,作为一个程序员,去做这样的事情,是完全无法容忍的。
自动化打包
,好在有你。所以今天就来谈一谈
iOS应用自动化打包
,但是本篇文章主要谈的是打单一的测试包,并不是在讲
持续集成




xcodebuild & xcrun

Xcode
提供了一套构建打包的命令,就是
xcodebuild
xcrun
xcodebuild
将对应的项目打包成
.app
文件,
xcrun
将对应的
.app
文件转换为对应的
.ipa
文件。了解这两套命令可以查看对应的 xcodebuild官方文档xcrun官方文档 ,或者在终端输入
man xcodebuild
man xcrun
命令,查看对应的
man page
。下面挑出来这两个命令的一部分为例大致介绍一下他们的使用方法。

xcodebuild

xcodebuild的所有命令

Objective-C

12
3
4
5
6
7
8
9
10
1112
13
14
15
16
17
18
19
20
2122
23
24
25
26
27
28
29
30
3132
33
34

NAME
xcodebuild -- build Xcode projects and workspaces

SYNOPSIS
xcodebuild [-project name.xcodeproj] [[-target targetname] ... | -alltargets]
[-configuration configurationname] [-sdk [sdkfullpath | sdkname]]
[action ...] [buildsetting=value ...] [-userdefault=value ...]

xcodebuild [-project name.xcodeproj] -scheme schemename
[[-destination destinationspecifier] ...] [-destination-timeout value]
[-configuration configurationname] [-sdk [sdkfullpath | sdkname]]
[action ...] [buildsetting=value ...] [-userdefault=value ...]

xcodebuild -workspace name.xcworkspace -scheme schemename
[[-destination destinationspecifier] ...] [-destination-timeout value]
[-configuration configurationname] [-sdk [sdkfullpath | sdkname]]
[action ...] [buildsetting=value ...] [-userdefault=value ...]

xcodebuild -version [-sdk [sdkfullpath | sdkname]] [infoitem]

xcodebuild -showsdks

xcodebuild -showBuildSettings
[-project name.xcodeproj | [-workspace name.xcworkspace -scheme schemename]]

xcodebuild -list [-project name.xcodeproj | -workspace name.xcworkspace]

xcodebuild -exportArchive -archivePath xcarchivepath -exportPath destinationpath
-exportOptionsPlist path

xcodebuild -exportLocalizations -project name.xcodeproj -localizationPath path
[[-exportLanguage language] ...]
xcodebuild -importLocalizations -project name.xcodeproj -localizationPath path

以上命令中最常用的应该就是
SYNOPSIS
中的前三行,其中分别对应
.project
.xcworkspace
类型的工程。除了这三个,我先讲一下第七行的
xcodebuild -list
这个命令。

xcodebuild -list命令介绍
以我们自己的工程为例在终端切入到工程文件夹,然后使用
xcodebuild -list
这个命令输出信息为:

Objective-C

12
3
4
5
6
7
8
9
10
1112
13
14
15
16
17

Information about project "yeemiao":
Targets:
yeemiao
yeemiao-inhouse
yeemiaoTests
yeemiaoInhouseTests

Build Configurations:
Debug
Release

If no build configuration is specified and -scheme is not passed then "Release" is used.

Schemes:
yeemiao
yeemiao-inhouse

Targets:
我们的工程有四个
Targets
yeemiao
是发布
App Store
的,
yeemiao-inhouse
是对应的测试版本,下面两个则是对应的性能测试。

Build Configurations:
由于我们在Targets中区分了测试版和正式版,这里面就没有在添加一个
Build Configurations
,而是系统默认的两个
Debug
Release
版本。

Schemes:
上面显示的两个
Schemes
默认是
.xcodeproj
的,如果你使用
xcodebuild -list -workspace yeemiao.xcworkspace
去查看就能看到第三方库对应的
Schemes
.

xcodebuild前三行命令介绍
了解了以上三个知识,在来看
SYNOPSIS
中的前三行命令就很容易理解了

-project -workspace
:这两个对应的就是项目的名字也就是说哪一个工程要打包。如果有多个工程,这里又没有指定,则默认为第一个工程。

-target
:打包对应的targets,如果没有指定这默认第一个。

-configuration
:如果没有修改这个配置,默认就是Debug和Release这两个版本,没有指定默认为Release版本。

buildsetting=value ...
:使用此命令去修改工程的配置。但是在实际应用中,我选择了读取文件去修改一个配置,而没有应用此种方法。

-scheme
:指定打包的scheme。

一个Demo的简单使用

在进入实际的使用之前,先用一个简单的
Demo
演示一下。 首先创建一个工程命名为
Toyun
,然后确保此工程可以真机调试。打开终端进入
Toyun
这个工程下,然后运行以下命令:


xcodebuild -project Toyun.xcodeproj -target Toyun -configuration Release



此行命令的意思是将
Toyun
这个工程
targets
对应的也是
Toyun
,打包成
Release
版本。当终端出现
** BUILD SUCCEEDED **
字样时,表示成功。这时候在去
Toyun
这个工程的文件夹下,你会发现多了一个名为
build
的文件夹,此下面两个子文件夹,
Release-iphoneos
Toyun.build
Release-iphoneos
文件夹下有
Toyun.app
这个文件。这就是
xcodebuild
命令的作用,最终生成
.app
文件。但是我们需要的是
.ipa
文件,这时在终端下面执行此行命令


xcrun -sdk iphoneos -v PackageApplication ./build/Release-iphoneos/Toyun.app -o ~/Desktop/Toyun.ipa



此行命令的意思为,将
Release-iphoneos
文件夹下的
Toyun.app
文件转换为
Toyun.ipa
文件并且放在桌面上。
iphoneos
是使用的
sdk
PackageApplication
为使用的开发者工具。此时你回到桌面可以看到
Toyun.ipa
文件,则为成功。

实际使用自动化打包

通过上面简单
Demo
的练习,我们已经可以使用短短的两行命令来打出我们需要的
.ipa文件
了。但是这据我们实际使用还有一段距离,在实际应用中情况复杂多变。这里以我们自己的打测试包的过程为例来说明实际中的一些情况。我写此自动化打包程序选的是
Shell脚本
,当然你也可以选择其他的语言去写。

打包流程

首先说一下我们打包的流程。先从
svn
上拉取最新的代码,然后修改对应的测试版本号,选择对应的证书和描述文件然后开始
archive打包
,打包完成后,需要
export
出对应的
ipa文件
,而且我们下载安装包使用了
itms-services协议
,这个时候就要去修改导出来的测试包包名和协议相关的
.plist文件
。然后上传到服务器,这时测试根据协议生成的链接去下载对应的测试包开始测试。这个整套流程走下来,大概需要10分钟

将打包流程准换为脚本语言

Objective-C

12
3
4
5
6
7
8
9
10
1112
13
14
15
16
17
18
19
20
2122
23
24
25
26
27
28
29
30
3132
33
34
35
36
37
38
39
40
4142
43
44
45
46
47
48
49
50
5152
53
54
55
56
57
58
59
60
6162
63
64
65
66
67
68
69
70
7172
73
74
75
76
77
78
79
80
8182
83
84
85
86
87
88
89
90
9192
93
94
95
96
97
98
99
100
101102
103
104

#! /bin/bash

# 传入这次的版本号
version_string=$1
# build号 我们是使用前时间作为build号的 2016041517 即为16年4月15号17点
build_number=$(date +%Y%m%d%H)

# 清空上一次的文件夹
rm -rf ~/Desktop/project

# 创建要工作的文件夹
mkdir ~/Desktop/project

# 进入要工作的文件夹
cd ~/Desktop/project

# 去svn上拉取最新的代码 如果你们使用的git或其他版本控制则修改对应的拉取代码命令即可
svn export svn://

# 下面是一些用到的变量给抽取出来了
# 工程环境路径
workspace_path=~/Desktop/project/yeemiao2016/yeemiao

# 打包项目名字
scheme_name=yeemiao-inhouse

# 打包使用的证书
CODE_SIGN_IDENTITY="替换为你们的证书名字"

# 打包使用的描述文件 这描述文件的名字不是自己命名的那个名字,而是对应的8b11ac11-xxxx-xxxx-xxxx-b022665db452这个名字
PROVISIONING_PROFILE="替换为你们的描述文件的名字"

# 指定yeemiao.app的输出位置 也就是Demo中build文件夹的位置
build_path=~/Desktop/project/build

# 指定yeemiao.ipa的输出位置
ipa_path=~/Desktop/project

# info.plist文件的位置
info_plist=~/Desktop/project/yeemiao2016/yeemiao/yeemiaoInhouse-Info.plist

# 下面是读取.plist文件的位置然后修改版本号和build号,这点没有使用xcodebuild提供的命令,在上面也有叙述
# 修改版本号
/usr/libexec/PlistBuddy -c "Set :CFBundleShortVersionString $version_string" ${info_plist}

# 修改build号
/usr/libexec/PlistBuddy -c "Set :CFBundleVersion $build_number" ${info_plist}

# 生成yeemiao.app, 在build_path路径下面
xcodebuild -workspace ${workspace_path}.xcworkspace -scheme ${scheme_name} -configuration Release clean -sdk iphoneos build CODE_SIGN_IDENTITY="${CODE_SIGN_IDENTITY}" PROVISIONING_PROFILE="${PROVISIONING_PROFILE}" SYMROOT="${build_path}"

# 生成yeemiao.ipa, 在ipa_path路径下面
xcrun -sdk iphoneos -v PackageApplication ${build_path}/Release-iphoneos/yeemiao.app -o ${ipa_path}/yeemiao_ios_${version_string}.ipa

# itms-services协议需要使用的.plist文件的位置
plist_path=~/Desktop/project/yeemiao_ios_${version_string}.plist

# 生成plist文件 在替换对应的路径中替换为你们的路径
cat << EOF > $plist_path
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>items</key>
<array>
<dict>
<key>assets</key>
<array>
<dict>
<key>kind</key>
<string>software-package</string>
<key>url</key>
<string>替换对应的路径</string>
</dict>
</array>
<key>metadata</key>
<dict>
<key>bundle-identifier</key>
<string>com.threegene.yeemiao.inhouse</string>
<key>bundle-version</key>
<string>1.0.0</string>
<key>kind</key>
<string>software</string>
<key>title</key>
<string>小豆苗</string>
</dict>
</dict>
</array>
</dict>
</plist>
EOF

# .ipa文件的位置
ipa_file_path=~/Desktop/project/yeemiao_ios_${version_string}.ipa

# .plist文件的位置
plist_file_path=~/Desktop/project/yeemiao_ios_${version_string}.plist

# 这里就要把.ipa和.plist文件上传到对应的服务器上,当然这一步也是可以使用命令来完成的。
# 这里要看你们要把测试包上传到哪儿,Fir、蒲公英、七牛等一般都提供了命令上传文件的方式。
# 如果需要修改数据库中测试包的指向,也可以开一个网络请求接口然后使用curl命令共同集成到测试包中。
# 同样可以增加一些判断(判断需要上次的文件存在不存在)和一些Log输出来让此脚本更为清晰安全和准确。

脚本最终完善之后,就可以敲一下
enter键
,整个打包过程就完成了。比我我给这段程序命名为
autoArchive.sh
。然后我在打包的时候只需要在终端输入命令:


~ ./autoArchive.sh 3.0.0000


其他

在写此脚本的时候也遇到了一些问题,其中一个就是当时我们的
xcshareddata数据
是没有提交到
svn
上的,然后在指向打包命令那一行,脚本就会卡死不动。后来提交了
xcshareddata
,此问题也就好了。

网络上也有对自动化打包进行的各种封装,其中比较出名的就是facebook出的xctool。这个工具规范了输出的
log日志
,而且一些错误信息也更为清晰一些。还是可以安装体验一下的

参考

iOS自动打包并发布脚本

iOS自动打包并发布脚本

Nov 25, 2015 in 编程语言

本文最终实现的是使用脚本打 Ad-hoc 包,并发布测试,当然稍微修改一下脚本参数就可以打其他类型的 ipa 包了。另外该脚本还实现了将生成的 ipa 包上传至蒲公英进行测试分发。

xcodebuild 简介

使用xcodebuild和xcrun打包签名

将打包过程脚本化

xcodebuild 简介

xcodebuild
是苹果提供的打包项目或者工程的命令,了解该命令最好的方式就是使用
man xcodebuild
查看其 man page. 尽管是英文,一定要老老实实的读一遍就好了。


DESCRIPTION

xcodebuild builds one or more targets contained in an Xcode project, or builds a scheme contained in an Xcode workspace or Xcode project.

Usage

To build an Xcode project, run xcodebuild from the directory containing your project (i.e. the directory containing the name.xcodeproj package). If you have multiple projects in the this directory you will need to use -project to indicate which project should be built. By default, xcodebuild builds the first target listed in the project, with the default build configuration. The order of the targets is a property of the project and is the same for all users of the project.

To build an Xcode workspace, you must pass both the -workspace and -scheme options to define the build. The parameters of the scheme will control which targets are built and how they are built, although you may pass other options to xcodebuild to override some parameters of the scheme.

There are also several options that display info about the installed version of Xcode or about projects or workspaces in the local directory, but which do not initiate an action. These include -list, -showBuildSettings, -showsdks, -usage, and -version.


总结一下:

需要在包含 name.xcodeproj 的目录下执行
xcodebuild
命令,且如果该目录下有多个 projects,那么需要使用
-project
指定需要 build 的项目。

在不指定 build 的 target 的时候,默认情况下会 build project 下的第一个 target

当 build workspace 时,需要同时指定
-workspace
-scheme
参数,scheme 参数控制了哪些 targets 会被 build 以及以怎样的方式 build。

有一些诸如
-list
,
-showBuildSettings
,
-showsdks
的参数可以查看项目或者工程的信息,不会对 build action 造成任何影响,放心使用。

那么,
xcodebuild
究竟如何使用呢? 继续看文档:


NAME

xcodebuild – build Xcode projects and workspaces

SYNOPSIS

xcodebuild [-project name.xcodeproj] [[-target targetname] … | -alltargets] [-configuration configurationname] [-sdk [sdkfullpath | sdkname]] [action …] [buildsetting=value …] [-userdefault=value …]

xcodebuild [-project name.xcodeproj] -scheme schemename [[-destination destinationspecifier] …] [-destination-timeout value] [-configuration configurationname] [-sdk [sdkfullpath | sdkname]] [action …] [buildsetting=value …] [-userdefault=value …]

xcodebuild -workspace name.xcworkspace -scheme schemename [[-destination destinationspecifier] …] [-destination-timeout value] [-configuration configurationname] [-sdk [sdkfullpath | sdkname]] [action …] [buildsetting=value …] [-userdefault=value …]

xcodebuild -version [-sdk [sdkfullpath | sdkname]] [infoitem]

xcodebuild -showsdks

xcodebuild -showBuildSettings [-project name.xcodeproj | [-workspace name.xcworkspace -scheme schemename]]

xcodebuild -list [-project name.xcodeproj | -workspace name.xcworkspace]

xcodebuild -exportArchive -archivePath xcarchivepath -exportPath destinationpath -exportOptionsPlist path

xcodebuild -exportLocalizations -project name.xcodeproj -localizationPath path [[-exportLanguage language] …]

xcodebuild -importLocalizations -project name.xcodeproj -localizationPath path


挑几个我常用的形式介绍一下,较长的使用方式以序列号代替:

xcodebuild -showsdks
: 列出 Xcode 所有可用的 SDKs

xcodebuild -showBuildSettings
: 上述序号6的使用方式,查看当前工程 build setting 的配置参数,Xcode 详细的 build setting 参数参考官方文档 Xcode Build Setting Reference, 已有的配置参数可以在终端中以
buildsetting=value
的形式进行覆盖重新设置.

xcodebuild -list
: 上述序号7的使用方式,查看 project 中的 targets 和 configurations,或者 workspace 中 schemes, 输出如下:

1

Information about project "NavTabBar":
Targets:
NavTabBar
NavTabBarTests
NavTabBarUITests

Build Configurations:
Debug
Release
Ad-hoc

If no build configuration is specified and -scheme is not passed then "Release" is used.

Schemes:
NavTabBar

xcodebuild [-project name.xcodeproj] [[-target targetname] ... | -alltargets] build
: 上述序号1的使用方式,会 build 指定 project,其中
-target
-configuration
参数可以使用
xcodebuild -list
获得,
-sdk
参数可由
xcodebuild -showsdks
获得,
[buildsetting=value ...]
用来覆盖工程中已有的配置。可覆盖的参数参考官方文档 Xcode Build Setting Reference,
action...
的可用选项如下, 打包的话当然用 build,这也是默认选项。

build
Build the target in the build root (SYMROOT). This is the default action, and is used if no action is given.

analyze
Build and analyze a target or scheme from the build root (SYMROOT). This requires specifying a scheme.

archive
Archive a scheme from the build root (SYMROOT). This requires specifying a scheme.

test
Test a scheme from the build root (SYMROOT). This requires specifying a scheme and optionally a destination.

installsrc
Copy the source of the project to the source root (SRCROOT).

install
Build the target and install it into the target’s installation directory in the distribution root (DSTROOT).

clean
Remove build products and intermediate files from the build root (SYMROOT).

xcodebuild -workspace name.xcworkspace -scheme schemename build
: 上述序号3的使用方式,build 指定 workspace,当我们使用 CocoaPods 来管理第三方库时,会生成 xcworkspace 文件,这样就会用到这种打包方式.

使用xcodebuild和xcrun打包签名

开始之前,可以新建一个测试工程 TestImg 来练习打包,在使用终端命令打包之前,请确认该工程也可以直接使用 Xcode 真机调试成功。

然后,打开终端,进入包含 TestImg.xcodeproj 的目录下,运行以下命令:

xcodebuild -project TestImg.xcodeproj -target TestImg -configuration Release


如果 build 成功,会看到
** BUILD SUCCEEDED **
字样,且在终端会打印出这次 build 的签名信息,如下:


Signing Identity: “iPhone Developer: xxx(59xxxxxx)”
Provisioning Profile: “iOS Team Provisioning Profile: *"


且在该目录下会多出一个
build
目录,该目录下有
Release-iphoneos
TestImg.build
文件,根据我们 build
-configuration
配置的参数不同,
Release-iphoneos
的文件名会不同。

Release-iphoneos
文件夹下,有我们需要的
TestImg.app
文件,但是要安装到真机上,我们需要将该文件导出为ipa文件,这里使用 xcrun 命令。

xcrun -sdk iphoneos -v PackageApplication ./build/Release-iphoneos/TestImg.app -o ~/Desktop/TestImg.ipa


这里又冒出一个
PackageApplication
, 我刚开始也不知道这是个什么玩意儿,万能的google告诉我,这是 Xcode 包里自带的工具,使用
xcrun -sdk iphoneos -v PackageApplication -help
查看帮助信息.


Usage:
PackageApplication [-s signature] application [-o output_directory] [-verbose] [-plugin plugin] || -man || -help

Options:

[-s signature]
: certificate name to resign application before packaging
[-o output_directory]
: specify output filename
[-plugin plugin]
: specify an optional plugin
-help
: brief help message
-man
: full documentation
-v[erbose]
: provide details during operation


如果执行成功,则会在你的桌面生成 TestImg.ipa 文件,这样就可以发布测试了。如果你遇到以下警告信息:


Warning: –resource-rules has been deprecated in Mac OS X >= 10.10! ResourceRules.plist: cannot read resources


请参考 stackoverflow 这个回答

将打包过程脚本化

工作中,特别是所做项目进入测试阶段,肯定会经常打 Ad-hoc 包给测试人员进行测试,但是我们肯定不想每次进行打包的时候都要进行一些工程的设置修改,以及一系列的 next 按钮点击操作,现在就让这些操作都交给脚本化吧。

脚本化中使用如下的命令打包:

xcodebuild -project name.xcodeproj -target targetname -configuration Release -sdk iphoneos build CODE_SIGN_IDENTITY="$(CODE_SIGN_IDENTITY)" PROVISIONING_PROFILE="$(PROVISIONING_PROFILE)"


或者

xcodebuild -workspace name.xcworkspace -scheme schemename -configuration Release -sdk iphoneos build CODE_SIGN_IDENTITY="$(CODE_SIGN_IDENTITY)" PROVISIONING_PROFILE="$(PROVISIONING_PROFILE)"


然后使用 xcrun 生成 ipa 文件:

`xcrun -sdk iphoneos -v PackageApplication ./build/Release-iphoneos/$(target|scheme).app"

清除 build 过程中产生的中间文件

结合蒲公英分发平台,将 ipa 文件上传至蒲公英分发平台,同时在终端会打印上传结果以及上传应用后该应用的 URL。蒲公英分发平台能够方便地将 ipa 文件尽快分发到测试人员,该平台有开放 API,可避免人工上传。

该脚本的使用可使用
python autobuild.py -h
查看,与
xcodebuild
的使用相似:


Usage: autobuild.py [options]

Options:
-h, --help
: show this help message and exit
-w name.xcworkspace, --workspace=name.xcworkspace
: Build the workspace name.xcworkspace.
-p name.xcodeproj, --project=name.xcodeproj
: Build the project name.xcodeproj.
-s schemename, --scheme=schemename
: Build the scheme specified by schemename. Required if building a workspace.
-t targetname, --target=targetname
: Build the target specified by targetname. Required if building a project.
-o output_filename, --output=output_filename
: specify output filename


在脚本顶部,有几个全局变量,根据自己的项目情况修改。

12
3
4
5
6
7

CODE_SIGN_IDENTITY = "iPhone Distribution: companyname (9xxxxxxx9A)"
PROVISIONING_PROFILE = "xxxxx-xxxx-xxx-xxxx-xxxxxxxxx"
CONFIGURATION = "Release"
SDK = "iphoneos"

USER_KEY = "15d6xxxxxxxxxxxxxxxxxx"
API_KEY = "efxxxxxxxxxxxxxxxxxxxx"

其中,
CODE_SIGN_IDENTITY
为开发者证书标识,可以在 Keychain Access -> Certificates -> 选中证书右键弹出菜单 -> Get Info -> Common Name 获取,类似
iPhone Distribution: Company name Co. Ltd (xxxxxxxx9A)
, 包括括号内的内容。

PROVISIONING_PROFILE
: 这个是 mobileprovision 文件的 identifier,获取方式:

Xcode -> Preferences -> 选中申请开发者证书的 Apple ID -> 选中开发者证书 -> View Details… -> 根据 Provisioning Profiles 的名字选中打包所需的 mobileprovision 文件 -> 右键菜单 -> Show in Finder -> 找到该文件后,除了该文件后缀名的字符串就是
PROVISIONING_PROFILE
字段的内容。

当然也可以使用脚本获取, 此处参考 命令行获取mobileprovision文件的UUID:

12
3
4
5
6
7
8
9
10

#!/bin/bash
if [ $# -ne 1 ]
then
echo "Usage: getmobileuuid the-mobileprovision-file-path"
exit 1fi

mobileprovision_uuid=`/usr/libexec/PlistBuddy -c "Print UUID" /dev/stdin <<< $(/usr/bin/security cms -D -i $1)`
echo "UUID is:"
echo ${mobileprovision_uuid}

USER_KEY
,
API_KEY
: 是蒲公英开放 API 的密钥。

该脚本可在 github 查看,如有任何问题,请留言回复。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: