iOS自动打包ipa

因为需要,最近在研究用脚本编译.ipa文件,在网上查找了不少资料,发现都是一些比较旧的操作了,在应用的时候难免会有一些问题。不过综合网上的各种说法和苹果最新的官方文档还是得到一个最终结果,记录下来,方便日后的使用。

1. 工具

  • xcodebuild简介
    xcodebuild 是苹果提供的打包项目或者工程的命令,可以使用 man xcodebuild或者xcodebuild -help来了解该命令的具体操作与用法。

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.

  • xcodebuild用法

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

比较常用的有:

  1. xcodebuild -list:可以查看Targets、Schemes、以及Configuration,这几个参数会在后续操作中用到。
  2. xcodebuild -showsdks:查看Xcode 所有可用的 SDKs信息。
  3. xcodebuild -showBuildSettings:查看project所有的配置信息,已有的配置参数可以在build时添加buildsetting=value进行覆盖重新设置。
  4. xcodebuild [-project name.xcodeproj] -scheme:build指定的project。
  5. xcodebuild -workspace name.xcworkspace -scheme:build 指定 workspace,与上一条功能相同,看到有人说用到CocoaPod时会生成.xcworkspace文件,故而需要采用该方法。但是我发现没有使用CocoaPod时,也可以找到xxx.xcodeproj/project.xcworkspace文件,也可以使用该方法,而且得到的结果和第3条并没有什么差异。对此,本人还没什么深入研究,知道详情的大牛可以解释下当然更好啦~~~
  6. xcodebuild -exportArchive -archivePath:打包生成.ipa文件,需要在上述3/4步操作后执行。

注:在第3/4条操作时,需要添加一个参数[action ...],该参数有如下几种选择:

Specify one or more actions to perform. Available actions are:

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

build-for-testing
Build the target and associated tests in the build root (SYMROOT). This will also produce an xctestrun file in the build root. This requires specifying a scheme.

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.

test-without-building

Test compiled bundles. If a scheme is provided with -scheme then the command finds bundles in the build root (SRCROOT). If an xctestrun file is provided with -xctestrun then the command finds bundles at paths specified in the xctestrun file.

install-src
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之后的内容涉及两种用法,ie:xcodebuild -project xxx.xcodeproj -scheme xxx clean build -showsdks 。当出现这种情况时,编译器只会执行后一种用法,也就是说示例中的操作在终端中执行后,不会build project,只会输出SDKs的信息。

2. 实现

  • 旧方法

首先说一下找到的第一种方法,试了一下,确实是可以编出ipa包的,安装之后似乎也没有什么问题,至少生成的ipa文件安装到手机上之后APP的功能都运行正常。

该方法的操作是:切换到项目xxx.xcodeproj所在文件夹下,并在终端执行以下两句

 $ xcodebuild -project 'xxx.xcodeproj' -target 'xxx' -configuration 'Release' -sdk 'iphoneos' build
 $ xcrun -sdk 'iphoneos' -v PackageApplication './build/Release-iphoneos/xxx.app' -o '~/Desktop/xxx.ipa'

注:其中,单引号标示的内容是需要按照自己的项目进行更换的。

但是该方法主要的问题是,成功之后会有一条警告信息:

 warning: PackageApplication is deprecated, use `xcodebuild -exportArchive` instead.

既然已经提示该方法被废弃,并由其他方法所替代,所以暂时就不考虑该方法了。

  • 当前最新方法

接下来就是按照提示去查找最新可用的方法了。现在测试,该操作是可以成功编译出.ipa文件,并且安装之后APP操作都运行正常,最重要的是编译的时候没有要命的警告_

该方法的操作是:切换到项目xxx.xcodeproj所在文件夹下,并在终端执行以下两句

 $ xcodebuild -project 'xxx.xcodeproj' -scheme 'xxx' -configuration 'Release' -arch 'arm64' archive -archivePath '$PWD/build/xxx.xcarchive'
 $ xcodebuild -exportArchive -archivePath '$PWD/build/xxx.xcarchive' -exportOptionsPlist 'export.plist'  -exportPath '$PWD/build'

注:其中,单引号标示的内容是需要按照自己的项目进行更换的。

在第一步操作结束后,会看到** BUILD SUCCEEDED **信息,表示编译成功。同时,向上拖动一段输出信息,可以看到以下两句信息:

 Signing Identity:     "iPhone Developer: UserName (User-Id)"
 Provisioning Profile: "iOS Team Provisioning Profile: Bundle-Id"
                  (b1xxxx-xxxx-xxxx-xxxx-xxxxxx)

该信息是文件的签名信息,可以在第一步中以buildsetting=value的方式进行设置,具体内容可以在Keychain Access -> Certificates -> 选中iPhone Developer:UserName(User-Id)证书右键弹出菜单 -> Get Info 中获取。

注:该操作中最重要的一点是对于export.plist文件的配置,查看官方文档,里边有一段说明:

Available keys for -exportOptionsPlist:

compileBitcode : Bool

For non-App Store exports, should Xcode re-compile the app from bitcode? Defaults to YES.

embedOnDemandResourcesAssetPacksInBundle : Bool

For non-App Store exports, if the app uses On Demand Resources and this is YES, asset packs are embedded in the app bundle so that the app can be tested without a server to host asset packs. Defaults to YES unless onDemandResourcesAssetPacksBaseURL is specified.

iCloudContainerEnvironment

For non-App Store exports, if the app is using CloudKit, this configures the "com.apple.developer.icloud-container-environment" entitlement. Available options: Development and Production. Defaults to Development.

manifest : Dictionary

For non-App Store exports, users can download your app over the web by opening your distribution manifest file in a web browser. To generate a distribution manifest, the value of this key should be a dictionary with three sub-keys: appURL, displayImageURL, fullSizeImageURL. The additional sub-key assetPackManifestURL is required when using on demand resources.

method : String

Describes how Xcode should export the archive. Available options: app-store, package, ad-hoc, enterprise, development, and developer-id. The list of options varies based on the type of archive. Defaults to development.

onDemandResourcesAssetPacksBaseURL : String

For non-App Store exports, if the app uses On Demand Resources and embedOnDemandResourcesAssetPacksInBundle isn't YES, this should be a base URL specifying where asset packs are going to be hosted. This configures the app to download asset packs from the specified URL.

teamID : String

The Developer Portal team to use for this export. Defaults to the team used to build the archive.

thinning : String

For non-App Store exports, should Xcode thin the package for one or more device variants? Available options: <none> (Xcode produces a non-thinned universal app), <thin-for-all-variants> (Xcode produces a universal app and all available thinned variants), or a model identifier for a specific device (e.g. "iPhone7,1"). Defaults to <none>.

uploadBitcode : Bool

For App Store exports, should the package include bitcode? Defaults to YES.

uploadSymbols : Bool

For App Store exports, should the package include symbols? Defaults to YES.

有很多参数是不必要的,现在查看teamID和method似乎是比较需要的,写了一个示例:

  <?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>method</key>
      <string>ad-hoc/enterprise/development</string>
      <key>teamID</key>
      <string>YOU_DISTRIBUTION_TEAM_ID</string>
      <key>compileBitcode</key>//暂不支持bitcode
      <string>NO</string>
  </dict>
  </plist>

因为我这边主要是企业账号开发,所以method是上述三项三选一。如果是个人账号,需要上传到App Store,需要设置method=app-store。
关于TeamID,可以去Keychain Access -> Certificates -> 选中前缀为iPhone Distribution:XXX的证书右键弹出菜单 -> Get Info 中获取组织ID即可。

3. 脚本文件

我是使用Makefile来编译ipa的,存放Makefile文件在xxx.xcodeproj所处文件夹下,然后直接执行make来编译,主要使用的就是这两句操作,所以在此就不给文件的示例了。

如果您需要shell脚本执行,可以自己写个.sh脚本哈,主要输入就是xxx.xcodeproj文件存放路径和ProjectName两项,其他需求可以针对不同情况随时调整。本人对脚本的研究还有点欠缺,就不在此献丑了。

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

推荐阅读更多精彩内容