写点什么

构建 iOS 持续集成平台(一)——自动化构建和依赖管理

  • 2013-09-10
  • 本文字数:4291 字

    阅读完需:约 14 分钟

2000 年 Matin Fowler 发表文章 Continuous Integration【1】;2007 年,Paul Duvall, Steve Matyas 和 Andrew Glover 合著的《Continuous Integration:Improving Software Quality and Reducing Risk》 【2】出版发行,该书获得了 2008 年的图灵大奖。持续集成理念经过 10 多年的发展,已经成为了业界的标准。在 Java, Ruby 的世界已经诞生了非常成熟的持续集成工具和实践,而对于 iOS 领域来说,因为技术本身相对比较年轻和苹果与生俱来的封闭思想,在持续集成方面的发展相对滞后一些,但是,随着越来越多的 iOS 开发者的涌入,以及各个互联网巨头加大对 iOS 开发的投入,诞生了一大批非常好用的持续集成工具和服务,本文的目的就是介绍一下如何有效的利用这些类库,服务快速构建一个 iOS 开发环境下的持续集成平台。

自动化构建

在 MartinFowler 的文章 [1] 中关于自动化的构建定义如下:

复制代码
Anyone should be able to bring in a virgin machine, check the sources
out of the repository, issue a single command, and have a running
system on their machine.

因此,自动化构建的的首要前提是有一个支持自动化构建的命令行工具,可以让开发人员可以通过一个简单的命令运行当前项目。

命令行工具

自动化构建的命令行工具比持续集成的概念要诞生得早很多,几十年前,Unix 世界就已经有了 Make,而 Java 世界有 Ant,Maven,以及当前最流行的 Gradle,.Net 世界则有 Nant 和 MSBuild。作为以 GUI 和命令行操作结合的完美性著称的苹果公司来说,当然也不会忘记为自己的封闭的 iOS 系统提供开发环境下命令行编译工具:xcodebuild【3】

xcodebuild

在介绍 xcodebuild 之前,需要先弄清楚一些在 XCode 环境下的一些概念【4】:

  • Workspace:简单来说,Workspace 就是一个容器,在该容器中可以存放多个你创建的 Xcode Project, 以及其他的项目中需要使用到的文件。使用 Workspace 的好处有,1), 扩展项目的可视域,即可以在多个项目之间跳转,重构,一个项目可以使用另一个项目的输出。Workspace 会负责各个 Project 之间提供各种相互依赖的关系 ;2), 多个项目之间共享 Build 目录。
  • Project:指一个项目,该项目会负责管理生成一个或者多个软件产品的全部文件和配置,一个 Project 可以包含多个 Target。
  • Target:一个 Target 是指在一个 Project 中构建的一个产品,它包含了构建该产品的所有文件,以及如何构建该产品的配置。
  • Scheme:一个定义好构建过程的 Target 成为一个 Scheme。可在 Scheme 中定义的 Target 的构建过程有:Build/Run/Test/Profile/Analyze/Archive
  • BuildSetting:配置产品的 Build 设置,比方说,使用哪个 Architectures?使用哪个版本的 SDK?。在 Xcode Project 中,有 Project 级别的 Build Setting,也有 Target 级别的 Build Setting。Build 一个产品时一定是针对某个 Target 的,因此,XCode 中总是优先选择 Target 的 Build Setting,如果 Target 没有配置,则会使用 Project 的 Build Setting。

弄清楚上面的这些概念之后,xcodebuild 就很好理解了,官网上对其作用的描述如下:

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

xcodebuild 就是用了构建产品的命令行工具,其用法可以归结为 3 个部分:

  • 可构建的对象
  • 构建行为
  • 一些其他的辅助命令

可以构建的对象有,默认情况下会运行 project 下的第一个 target:

  • workspace:必须和“-scheme”一起使用,构建该 workspace 下的一个 scheme。
  • project:当根目录下有多个 Project 的时候,必须使用“-project”指定 project,然后会运行
  • target:构建某个 Target
  • scheme:和“-workspace”一起使用,指定构建的 scheme。
  • ……

构建行为包括:

  • clean: 清除 build 目录下的
  • build: 构建
  • test: 测试某个 scheme,必须和"-scheme"一起使用
  • archive: 打包,必须和“-scheme”一起使用
  • ……

辅助命令包括:

  • -sdk:指定构建使用的 SDK
  • -list:列出当前项目下所有的 Target 和 scheme。
  • -version:版本信息
  • ……

关于 xcodebuild 更多详细的命令行请参见: https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man1/xcodebuild.1.html

下图是使用 XcodeBuild 运行一个 scheme 的 build 的结果:

了解了 xcodebuild 的用法之后,接下来分析一下 xcodebuild 的主要缺陷:

  • 从上图直接可以得到的感觉,其脚本输出的可读性极差,
  • 只能要么完整的运行一个 target 或者 scheme,要么全部不运行。不能指定运行 Target 中特定的测试。
  • 最令人发指的是,XCode 4 中的 xcodebuild 居然不支持 iOSUnitTest 的 Target【5】,当我尝试运行一个 iOS App 的测试 target 时,得到如下的错误:

对于上面提到的缺陷,Facebook 给出了他们的解决方案:xctool【6】

xctool

xctool 在 其主页直接表明了其目的:

<i>xctool is a replacement for Apple's xcodebuild that makes it easier to build and<br></br> test iOS and Mac products. It's especially helpful for continuous integration.</i>其作用是替代 xcodebuild,目的是让构建和测试更加容易,更好的支持持续集成。从个人感受来看,它的确成功取代了 xcodebuild。但是 xctool 说到底只是对 xcodebuild 的一个封装,只是提供了更加丰富的 build 指令,因此,使用 xctool 的前提是 xcodebuild 已经存在,且能正常工作。

安装

xctool 的安装非常简单,只需要 clone xctool 的 repository 到项目根目录就可以使用, 如果你的机器上安装有 Homebrew,可以通过“brew install xctool”命令直接安装。(注意:使用 xctool 前一定要首先确认 xcodebuild 已安装且能正确工作)。

用法

关于 xctool 的用法就更加人性化了,几乎可以重用所有的 xcodebuild 的指令,配置。只需要注意一下几点:

  • xctool 不支持 target 构建,只能使用 scheme 构建。
  • 支持“-only”指令运行指定的测试。
  • 支持多种格式的 build 报告。

例子:

复制代码
path/to/xctool.sh
-workspaceYourWorkspace.xcworkspace
-schemeYourScheme
test -only SomeTestTarget:SomeTestClass/testSomeMethod

下图是我使用 xctool 运行 test 的效果:

常见问题:

No architectures to compile for (ONLY_ACTIVE_ARCH=YES, active arch=x86_64, VALID_ARCHS=armv7 armv7s).

解决方法:到 Project Setting 中,把"Build Active Architecture Only"设置为 NO

Code Sign error: A valid provisioning profile matching the application’s Identifier ‘dk.muncken.MyApp’ could not be found

解决方法:通过“-sdkiphonesimulator”指定 SDK,从而能够使用符合 iOS 约定的 application Identifier。

依赖管理

选定了命令行工具之后, 接下来可以考虑下依赖管理的问题了。我到现在还记得几年前,刚从 Ant 转到使用 Maven 的那种爽快的感觉。后来,进入 Ruby 的世界,其与生俱来的 Gem 管理系统,也让其依赖管理变得极其简单。 对于 iOS 平台来说,在做项目时,经常需要使用到各种各样的第三方 Framework,这同样需要一个爽快的依赖管理系统,不然的话,各位可以想象一下重复的下载 Framework 文件,拖入各个 Target 的 Build Phase 的 Link Binary With Libraries 中的场景。这种重复的劳动对于“懒惰”的程序员来说,是很难接受的,于是,活跃的社区开发者们提供了这样的一个工具:Cocoapods【7】

Cocoapods 开始于 2011 年 8 月 12 日,经过 2 年多的发展,现在已经超过 2500 次提交,并且持续保持活跃更新,目前已成为 iOS 领域最流行的第三方依赖管理工具。从技术层面来说,其是一个 Ruby Gem,从功能层面来说,其是一个 iOS 平台下的依赖管理工具,为 iOS 项目开发提供了类似于在 Ruby 世界使用 Gem 的依赖管理体验。

安装

前面提到 cocoapods 本质上是一个 Ruby Gem,因此,其使用前提首先是 Ruby 开发环境。庆幸的是,Mac 下都自带 Ruby。这样,只需要简单的 2 条命令,就可以把 cocoapods 安装好:

复制代码
$ [sudo] gem install cocoapods
$ pod setup

用法

cocoapods 的使用方式和使用 Ruby Gem 非常相似,首先需要在项目根目录下创建文件 Podfile, 在 Podfile 中,开发人员只需要按照规则配置好如下内容就好:

  • 项目支持的平台,版本(iOS/OSX)
  • 每个 target 的第三方依赖

例子:

复制代码
platform :ios, '6.0'
inhibit_all_warnings!
xcodeproj `MyProject`
pod 'ObjectiveSugar', '~> 0.5'
target :test do
pod 'OCMock', '~> 2.0.1'
end
post_install do |installer|
installer.project.targets.each do |target|
puts "#{target.name}"
end
end

修改好配置文件之后,只需要简单的使用“pod install”即可安装好所有的依赖,执行该命令之后,在项目跟目录下会出现“.xcworkspace”和“Pods”两个目录:

接下来,开发者需要使用 xcworkspace 打开项目而不是使用 xcodeproject,打开项目之后,在项目目录下除了自己的 project 以外,还可以看到一个叫做 Pods 的项目,该项目会为每一个依赖创建一个 target:

在 Podfile 中,还可以指定依赖专属于某个 Target,

复制代码
target :CocoaPodsTest do
pod 'OCMock', '~> 2.0.1'
pod 'OCHamcrest'
end

如果你记不清楚某个依赖库的名称,可以使用“pod search ”模糊搜索依赖库中的相似库, 另外,如果你想使用的库在 cocoapods 的中央库中找不到,那么,你可以考虑为开源社区做做贡献,把你觉得好用的库添加到中央库中,Cocoapods 的官网上有具体的步骤【8】

原理

CocoaPods 的原理思想基本上来自于 Jonah Williams 的博客“Using Open Source Static Libraries in Xcode 4”【9】, 当使用“pod install”安装文件时,cocoapods 做了如下这些事:

  • 创建或者更新当前的 workspace
  • 创建一个新的项目来存放静态库
  • 把静态库会编译生成的 libpods.a 文件配置到 target 的 build phase 的 link with libraries 中
  • 在依赖项目中创建 *.xcconfig 文件, 指定在编译时的一些参数和依赖
  • 添加一个新的名为“Copy Pods Resource”的 Build Phase,该 build phase 会使用"${SRCROOT}/Pods/Pods-CocoaPodsTest-resources.sh"把 Pods 下的资源文件拷贝到 app bundle 下。

注意事项

当使用 xctool 作为命令行工具构建项目时,使用 cocoapods 管理依赖时,需要做一些额外的配置:

  • 编辑 Scheme,把 pods 静态库项目作为显式的依赖添加到项目的 build 中,
  • 把 pods 依赖项目拖动到本来的项目之上,表示先编译 pods 静态库项目,再编译自己的项目。


感谢张凯峰对本文的审校。

给InfoQ 中文站投稿或者参与内容翻译工作,请邮件至 editors@cn.infoq.com 。也欢迎大家通过新浪微博( @InfoQ )或者腾讯微博( @InfoQ )关注我们,并与我们的编辑和其他读者朋友交流。

2013-09-10 00:1319182

评论

发布
暂无评论
发现更多内容

阿里云AnalyticDB(ADB) + LLM:构建AIGC时代下企业专属ChatBot

科技热闻

旭阳数字郗维宝:数智化转型助力焦化企业打破行业困境

用友BIP

升级企业数智化底座 2023用友技术大会

深入浅出 OkHttp 源码解析及应用实践

vivo互联网技术

okhttp 拦截器 源代码

原型设计Axure RP 9中文授权码【Mac/win】

Rose

Axure RP 9汉化 Axure RP 9授权码 产品原型设计工具 axure rp9下载 axure rp9安装教程

「聊天机器人构建、智能文档问答」大模型应用开发实操课程来了

飞桨PaddlePaddle

AIGC Prompt

DevEco Studio 3.1 Release | 动态共享包开发,编译更快,包更小

HarmonyOS开发者

HarmonyOS

【5.12-5.19】写作社区优秀技术博文一览

InfoQ写作社区官方

热门活动 优质创作周报

Java性能分析工具JProfiler注册码下载

Rose

JProfiler激活码 JProfiler Mac永久激活版 Java 分析器 JProfiler中文版 JProfiler下载

【实践篇】教你玩转JWT认证---从一个优惠券聊起 | 京东云技术团队

京东科技开发者

分布式 JWT 企业号 5 月 PK 榜

全靠这份阿里大佬的“Java进阶面试手册”收获蚂蚁offer

Java你猿哥

Java kafka Spring Boot Netty java面试

常用的表格检测识别方法 - 表格区域检测方法(下)

合合技术团队

人工智能 文字识别 表格识别 表格检测

【GPT-4理论篇-1】GPT-4核心技术探秘 | 京东云技术团队

京东科技开发者

人工智能 openai GPT-4 企业号 5 月 PK 榜

完整版来了!阿里Dubbo技术负责人准备的源码教程,很有大厂风格

Java你猿哥

Java 架构 dubbo ssm

上海丨阿里云 Serverless 技术实战营邀你来玩!

Serverless Devs

阿里云 Serverless 中间件

龙蜥开发者说:构建软件包?不,是构建开源每一个角落!| 第 20 期

OpenAnolis小助手

开源 操作系统 龙蜥社区 开发者说 优秀贡献奖

500行代码手写docker开篇-goland远程编译环境配置

蓝胖子的编程梦

Docker 容器 云原生 k8s 命名空间

如何进行测试分析与设计-HTSM启发式测试策略模型 | 京东云技术团队

京东科技开发者

测试 测试策略 企业号 5 月 PK 榜 HTSM

为世界第一大癌症高效研发首创新药,AI大模型助力药物研发叩开未来之门

飞桨PaddlePaddle

百度飞桨

VM虚拟机 v13.0.2激活版 for Mac许可秘钥

Rose

VMware Fusion Pro 13 VM虚拟机破解版 Mac虚拟机 VMware Fusion激活秘钥

MobTech 秒验|助力预热618

MobTech袤博科技

用好kafka,你不得不知的那些工具

JAVA旭阳

Java kafka

RocketMQ你不得不了解的 Rebalance机制源码分析

Java你猿哥

Java 源码 RocketMQ ssm client

IDO&IEO盘点,包括PoseiSwap等即将面向市场的潜力打新活动

西柚子

上线半天下载量破100W!美团大佬的Java性能调优实战手册,超详细

Java你猿哥

Java JVM 多线程 ssm 性能调优

苹果系统更新:MacOS 11-13.x(PKG系统安装包及IPSW固件)

Rose

mac系统 macOS 13 Ventura 苹果最新系统 苹果系统下载

Photoshop 2023 如何切换语言?

Rose

Photoshop 2023下载 如何切换PS语言 PS 2023破解

什么是研发 Lead Time?我悟了!

LigaAI

DevOps 敏捷开发 研发速率 研发效能管理 企业号 5 月 PK 榜

LED显示屏技术升级方向介绍

Dylan

技术 升级 LED显示屏

为什么 GPU 更适用于时域算法,而 CPU 更适用于频域算法?

思茂信息

gpu cpu 计算机 电脑 电脑硬件

构建iOS持续集成平台(一)——自动化构建和依赖管理_DevOps & 平台工程_刘先宁_InfoQ精选文章