万物科技 学,以致用

8. 使用命令行构建Xcode项目

2017-04-08
Geng

测试环境已经搭建好了,那么下一步的工作,自然就该开始测试了。但是为了测试,我们需要先把应用跑起来。这个步骤每个iOS开发者可能都做过,就是点击Xcode的run,或者cmd+R,然后模拟器就启动了。那么这中间都发生了什么呢?

这次的内容,主要讨论从点击run到启动模拟器之前的部分,是为以后命令行运行iOS应用做准备,为以后Jenkins启动应用打下基础。关于Android,将会在以后讲述。

内容很基础,但是坑也不少。

欢迎入坑👻

iOS应用安装包的基础知识

详见iOS应用安装包的基础知识

上面参考文献总结出以下几点:

  1. 不管是从Apple Store或iTunes上下载的应用,还是在Xcode中针对真机设备编译生成的.ipa文件,都是面向于ARM处理器的iOS设备,只能在真机设备中进行安装;
  2. 而在Mac OSX系统中运行的iOS模拟器,运行环境是基于Intel处理器的;
  3. 因此,若是针对真机设备编译生成的.ipa文件,是无法在iOS模拟器中正常运行的,毕竟处理器架构都不一样;
  4. 要想在iOS模拟器中运行应用,则必须在Xcode中编译时选择模拟器类型;编译生成的文件后缀为.app

构建方式

详见关于持续集成打包平台的Jenkins配置和构建脚本实现细节

这里画一下上面文献的重点: 构建方式主要包括两种:

  • 源码 -> .archive文件 -> .ipa文件
  • 源码 -> .app文件 -> .ipa文件 这两种方式的主要差异是生成的中间产物不同,对应的,两种构建方式采用的命令也不同。

我们重点关注第二种方法,那么命令为:

源码 -> .app文件

# build .app file from source code
xcodebuild \    # xctool
  -workspace ${WORKSPACE_PATH} \
  -scheme ${SCHEME} \
  -configuration ${CONFIGURATION} \
  -sdk ${SDK}
  -derivedDataPath ${OUTPUT_FOLDER}

.app文件 -> .ipa文件

```bash
# convert .app file to ipa file
xcrun \
  -sdk iphoneos \
  PackageApplication \
  -v ${OUTPUT_FOLDER}/Release-iphoneos/xxx.app \
  -o ${OUTPUT_FOLDER}/Release-iphoneos/xxx.ipa

命令比较复杂,先放在这里,知道就行了,我们下面会仔细分析。

准备.app文件

有了这个文件,才能方便应用运行在模拟器,或者进一步转成.ipa文件运行在真机。

构建

点击Xcode的run,就是一个构建然后启动模拟器的过程。

首先我们需要了解构建到底发生了什么。那么,我们要理解至少下面三个东西:1

Targets(目标产物):构建完成后的单一产物。 Configuration(设置):构建过程中的一套定义。Xcode默认一个新的项目有RELEASEDEBUG两种configuration,你也可以建立更多的,比如STAGINGSchemes(方案):它将所有东西集合在一起。使用它,你可以指定构建的目标产物,设置,还可以定义不同的针对RunTestingAnalyzingArchiving的值。Xcode默认创建一个Schemes。它设置ArchiveRELEASE,其他都是DEBUG

下一步,开启Xcode,查看这三个分别都是什么。

开启Xcode后,我们可以看到,在run右侧,我标注了一个红框,点开它,我们可以看到,和Schemes相关。点击这个图标,下拉菜单中,点击Manage Schemes,可以看到,Schemes与项目名称相同,而且你还可以建立新的Schemes

上图标记的另外一个位置,就是Targets了。我们开发的时候,经常会在这里修改一些参数,但是可能一直没有留意,这些都是Targets内的参数。如果你在新建项目的时候,勾选了测试相关内容,这个位置也会出现测试想关的Targets


那么Configuration在哪里呢?如下图所示,点击项目名称,然后info,会看到Configuration选项。可以看到,有上文所说的RELEASEDEBUG两种。


如果我们想要使用命令来构建,就需要设置上面三个参数。那么,使用什么命令呢?

xcodebuild

可以使用xcodebuild来构建。xcodebuild 是苹果发布自动构建的工具,可以打包项目或者工程。

我们可以通过man xcodebuild命令,来查看其使用方法

坑:这个命令的文档最好自己通过man来查看,因为网上的教程,甚至你查到的苹果官方网站上官方文档都是老的,过时的。

XCODEBUILD(1)             BSD General Commands Manual            XCODEBUILD(1)

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

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

                ...

使用的时候,进入name.xcodeproj所在目录,运行这个命令即可。如果有多个project,那么需要使用-project来指定是哪一个。默认情况下,她会构建列表中第一个。

基本查询

有几个查询命令大家可以熟悉下:

首先是xcodebuild -list,可以看到Target,Schemes和Configurations:

$ xcodebuild -list
  Information about project "Hello":
    Targets:
        Homepwner
        HomepwnerTests
        HomepwnerUITests

    Build Configurations:
        Debug
        Release

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

    Schemes:
        Hello

然后就是xcodebuild -showsdks,可以看到sdk信息。最后还有一个xcodebuild -showBuildSettings,可以了解下。

简单使用

打开一个旧的Xcode项目(project)或者新建一个,安装上面讲的方法,在本目录下,运行:

xcodebuild -project projectName.xcodeproj -configuration Release

如果 build 成功,会看到 ** BUILD SUCCEEDED ** 字样.


如果失败,会有提示,比如如果账号等信息没有设置好,会有以下提示:

Check dependencies
Signing for "projectName" requires a development team. Select a development team in the project editor.
Code signing is required for product type 'Application' in SDK 'iOS 10.2'

**** BUILD FAILED ****


The following build commands failed:
	Check dependencies
(1 failure)

如果这个失败信息,那么你需要打开Xcode,设置Bundle IdentifierTeamTeam使用你的苹果账号登录即可,Bundle Identifier要求就是别和其他开发者冲突就可以。

成功后,会生成一个build文件夹,里面有Release文件夹,在其中可以看到.app文件。


尝试下面两个命令:

$ xcodebuild -project Projectname.xcodeproj -configuration Release -scheme Projectname
$ xcodebuild -project Projectname.xcodeproj -configuration Release -scheme Projectname -sdk iphonesimulator

查看最后输出的路径不一样,目录结构也不一样。

控制路径

那么我们怎么样指定输出路径呢,可以这样:

$ xcodebuild -project Projectname.xcodeproj -configuration Release -scheme Projectname -sdk iphonesimulator -derivedDataPath .

上面命令中的.表示当前目录。观察目录结构。可以找到.app文件 如果要编译成.ipa,进行上文xrun即可。

清除缓存文件

在每次build之后,工程目录下会遗留一些缓存文件,以便下次build时减少编译时间。然而,若因为工程配置错误等问题造成编译失败后,下次再编译时就可能会受到缓存的影响。

因此,比较好的做法是在每次build之前都清理一下上一次编译遗留的缓存文件。

$ xcodebuild clean

但是这个过程不是很清理的不是很干净,所以建议这样做:

$ xcodebuild -project Projectname.xcodeproj -configuration Release -scheme Projectname clean

如果还是觉得不够干净,那么可以这样:

$ xcodebuild -project Projectname.xcodeproj -configuration Release -scheme Projectname -sdk iphonesimulator -derivedDataPath . clean

这样下次就是全新的编译了。

workspace

上面的过程都是针对project,那么如果是workspace呢,我们把命令修改即可。

$ xcodebuild -project Workspacename.xcworkspace -configuration Release -scheme Projectname -sdk iphonesimulator -derivedDataPath . 

如果有Cocoapod依赖,记得要首先运行:

$ pod install

CocoaPods介绍

这部分是扫盲需要,熟悉CocoaPods可略过。

一般来说,一个完整的iOS应用,很可能会使用一些第三方的库,如果使用CocoaPods管理的项目,在项目根目录下会包含PodfilePodfile.lock文件,里面记录了当前项目依赖的第三方库以及对应的版本号。

如果使用了CocoaPods管理的库,那么首先需要有CocoaPods。如果没有的话,可以如下安装(注意需要安装ruby最新版,否则会有意想不到的奇妙事情,让你经历什么是从入门到放弃)

安装CocoaPods

$ sudo gem install cocoapods

然后,进入到iOS项目的目录,执行pod install命令即可安装当前项目的所有依赖。

$ cd Project_Folder
$ pod install

在依赖安装完成后,正常情况下,就可以在Xcode中编译项目了。

  1. http://ravelantunes.com/blog/xcode-build-process/ 


上一篇 9. 断点续传

Comments

你可以请我喝喝茶,聊聊天,鼓励我

Wechat Pay
wechat

Thanks!