摘要

集中构建顾名思义就是集中在一起进行构建,是实现持续集成、持续部署、持续交付等一系列开发实践的基础。

随着智能手机在人们生活中的占比越来越大,移动端应用也逐渐成为人们生活中使用最频繁的程序,而iOS平台作为移动端重要的组成部分之一,由于其本身产品系统的独特性以及移动应用迭代频繁的特点,在实现iOS平台集中构建过程中走了许多弯路。

为了适应项目投产需要与中心集中构建整体发展思路保持一致,在进行了大量项目实践的基础上,本文提出了两种适用于不同项目情况的集中构建方法,旨在帮助项目实现完全自动化的构建,生成可直接安装部署的应用目标码,有效管理项目证书和代码的同时,减少不必要的交互,提高投产效率并为后续的测试和自动化部署提供实施的先决条件。


关键词:持续集成、Objective-c、Javascript、TFS


一、研究背景




苹果操作系统主要包括OSX和iOS,其主要的开发语言为Objective-C、Swift以及Javascript,使用LLVM编译器框架系统,前端使用Clang编译器。目前投产运行的苹果应用主要使用Objective-C和Javascript语言开发,苹果公司为每一个应用都设置了证书以保证信息在互联网中安全传输,分为公司版证书程序和企业版证书程序,这两类证书对程序的发布途径起着至关重要的作用:

  • 公司版证书:属于“组织”类别,功能用途与个人版证书一致,允许多个开发者协作开发,只能用于将应用发布至苹果App Store。

  • 企业版证书:属于“组织”类别,允许多个开发者协作开发,只能用于将应用发布至企业内部使用。

由于iOS应用具有上述特点,证书的申请和管理对项目日常开发投产影响较大,并且与现有集中构建体系存在较大差异,面对移动端应用投产上线的实际情况,集中构建需求迫在眉睫。

二、技术术语




2.1 编译

一般来说编译过程主要分为以下四部分:

  • 预处理(Pre-process),把宏替换,删除注释信息,将头文件进行展开,产生.i文件。 

  • 编译(Compliling),把.i文件转换成汇编语言产生.s文件。

  • 汇编(Asembly),将.s文件转换成机器编码文件,产生.o文件。 

  • 链接(Link),对.o文件中的所提到的的库文件进行引用(包括多个.o文件进行link),生成最后的可执行文件。

2.2 开发语言

iOS开发语言主要包括:C语言基础、Objective-C、Swift以及Javascript编程语言。

  • Objective-C:是扩充C的面向对象编程语言,它是一个用C写成的很小的运行库,令应用程序尺寸增加很小,完全兼容C语言,可以在GCC和Clang运行的系统上进行编译,目前我们主要使用该语言进行开发。

  • Swift:于2014年WWDC发布的新开发语言,可与Objective-C共同运行于Mac OS和iOS平台,为了使Swift语言易用性和功能性更加出色,苹果公司也在不断地对编译器进行优化和改进。以Xcode7版本为例,使用LLVM7.1(Xcode7.3)编译器,该编译器是自Xcode5将GCC编译器取消后一直使用的,LLVM编译器的前端是Clang,支持C、C++、Objective-C和Objective-C++等编程语言。

  • Javascript:该脚本语言是苹果公司在iOS7之后推出的基于JavaScriptCore.framework框架的开发方式,实现Objective-C与Javascript相互调用并传参的方法,使用此框架可以在iOS应用中运行JavaScript脚本,也就是HybirdApp混合模式移动应用,即其中包含原生的结构有内嵌有web组件,这种App不仅性能和用户体验可以达到和原生所差无几的程度,更大的优势在于bug修复快,版本迭代无需重新编译发布,目前我们越来越多的项目开始采用此种开发模式。

2.3 iOS构建发布要素

iOS应用从构建到发布应用一般会经历三个阶段:在Xcode(苹果程序开发工具)上运行调试、在设备上运行调试和编译发布。苹果为了防止非法设备和非开发人员调试和发布应用,需要使用配置概要文件(Provisioning Profiles)控制应用在设备上运行调试和编译发布。配置概要文件由证书(certificates)、项目标识(Identifiers)以及设备(Devices)组成,具体的编译发布流程如下:

  • 证书(Certificates)苹果官方给你颁布的证书,分为开发证书和发布证书两种,苹果是发布者,然后安装,这个证书的Mac就是拥有者。苹果就会给电脑授予这个证书所对应的权利,简单来说,证书是iOS应用开发的基础,也是构建的必要组成部分。

  • 项目标识(Identifiers)Identifiers即“标识符”,约等于是项目的身份证,用于区别苹果应用,每个应用都有各自唯一的标识符,项目标识包括:App ID,其实就是一个App的身份证,一个App的位置标识。在Project中称为Bundle ID。在Member Center、Project、ITunes Connect都是需要此ID去标识APP的唯一性。Bundle ID在不同环境下的表现关系,如下图所示:

在创建App ID过程中可以配置该应用的权限,比如是否用到了PassBook,GameCenter,以及更常见的push服务,如果选中了push服务,就可以创建生成具有推送服务的App ID。所以,在所有和推送相关的配置中,首先要做的就是先开通支持推送服务的App ID。

  • 设备(Devices)Devices作用为创建测试设备,只有在此列表中的设备才能安装真机调试阶段的苹果应用,未在该列表中的设备则不能安装,一般情况下该列表中设备总数不能超过100个。

  • 配置概要文件(Provisioning Profiles)配置概要文件是很有苹果特点的设置,该文件将证书(Certificates) 、项目标识(Identifiers)、设备(Devices)结合起来,形成一个描述证书、标识符的描述文件。通过Xcode编译的过程将配置概要文件与程序关联起来从而形成待发布苹果App。


三、问题描述




不同于开放平台构建项目,iOS构建由于其操作系统、开发工具、证书授权机制等问题的制约,实施困难较大,经前期手动集中构建情况分析和经验总结,对项目症结有了大致的分类和判断,总体来说iOS集中构建主要问题集中在如下几点:

3.1 构建过程复杂

iOS项目一般将整个项目分为多个target进行编译,这与项目工程中的targets相互对应,每个target中的编译任务分为很多步骤,步骤中使用了多种命令对源码进行处理,虽然iOS项目代码是由Linux\Unix C语言进化而来,但经过多轮的演变,无论是开发语言还是编译器都发生了很大的变化,并且在各项目情况复杂多样的环境下,对集中构建的推广和实施产生了很大的影响。

3.2 构建环境特殊

iOS项目开发需在苹果操作系统macOS中进行,开发工具一般采用Xcode,根据项目情况的不同需适时升级macOS并安装多版本Xcode供编译使用,如果进行集中构建,编译环境以及Xcode版本升级问题将会成为制约集中构建的重要因素。

3.3 代码管理工具多样

iOS项目开发大多在苹果笔记本上进行,代码版本管理并没有统一的规定,配置库采用GIT、SVN等开源版本控制系统较多,各版本管理工具之间不能互联互通,没有统一的管理机制,在代码质量、版本稳定性以及版本追溯等方面对项目投产上线产生极大的影响。

3.4 证书管理繁琐

苹果公司对每一个发布的iOS应用都采用证书授权机制,通过编译将证书进行注入,起到认证和管理的目的,但由于证书的唯一性,在日常开发过程中是无法使用苹果授权证书进行打包并生成iOS应用的,尤其这对需要进行大规模测试的项目来说影响较大,项目上线则需要将代码拷贝至组织级构建管理员处进行编译后发布。为了更好地解决iOS项目集中构建问题,应从构建方式入手,梳理iOS构建特点的同时,总结出适用于各项目的构建方法,解决证书统一管理造成的开发测试受限等问题。


四、解决方案




4.1 构建日志分析

经过大量的手工编译并对编译日志进行分析总结得出目前iOS构建一共分为两种情况:

  • 一种是单证书单配置文件构建方式,这种项目只需要一套证书和配置概要文件即可实现构建,完成目标码的打包工作;
  • 第二种是单证书双配置概要文件的构建方式,主要帮助应用使用iOS推送拓展,实现离线推送等功能。

通过查看Build日志可以进一步了解苹果程序编译过程的工作原理提升开发及管理工作效率,在多数情况下Build编译日志隐藏了大量的信息,其中经常会有一些通用的编译命令,以这些命令为基础可以更好的对编译日志进行模块化的解读和研究。

  • CompileC...:主要用来编译.m和.c文件,在每一个target中被广泛使用,生成中间文件.o,一般出现在Compile步骤的行首位置。

  • Libtool...:主要是从目标文件中构建library,即生成.a文件,一般出现在创建.a文件的过程中。

  • CreateUniversalBinary...:将上阶段生成.a文件合并为一个通用的二进制文件。

  • Ld:与Libtool功能相似是一个linker的工具,被用来构建可执行文件,即生成最终的.ipa文件,该命令一般较长出现在构建目标码阶段。

根据上述命令分析我们就可以很清晰地了解苹果程序的编译过程,以项目中某一target为例,如下图所示,该target作用是生成可执行文件需要的.a文件,即libDZNEmptyDataSet.a,其中使用了CompileC、Libtool以及CreateUniversalBinary等命令对源码进行处理。

通过查看Build日志可以知道Xcode是通过一系列复杂的编译过程最终生成可执行文件(.ipa),但编译过程并不是不可控制的,Xcode提供了一套完整的编译过程控制方法,主要分为Buid Settings、Build Phases、Build Rules三方面。

  • Build Settings:主要是对编译各过程进行设定,在该选项下与很多配置信息,从编译打包到代码签名都可以进行设置。

  • Build Phases:主要用来控制从源码到可执行文件的整个过程,是面向源码的,包括编译哪些文件,在编译过程中执行哪些自定义脚本等。

  • Build Rules:顾名思义,该部分主要用来定义对各种类型的源码文件进行编译的方法,同时这里也会大量的运用一些xcode中的环境变量。

4.2 集中构建方法研究

通过对上述日志进行逐字逐句分析可以看出iOS项目虽然编译过程比较复杂,编译命令数量繁多,编译方法丰富多样,但总体来说都会遵循一定的规则进行,每一个target之间存在相互的主次关系,通过调用主target就可以实现整个项目构建并生成目标码(.IPA)文件。对于自动化构建来说,项目的配置和规则信息都储存于工程文件(.xcodeproj)当中,可以通过开发工具(Xcode)自带的自动化构建命令行实现自动化编译打包。核心问题是,在实际UI界面进行构建时,手工操作比较繁琐,需要对构建前及构建过程中使用的命令进行整理和分析才能最终形成集中构建命令行编译方法。通过对手工过程中所遇到情况进行总结,结合Xcode命令参数,目前形成了两种可以覆盖现有项目模式的集中构建方案。

1)单证书单配置概要文件集中构建模式

这类构建模式相对比较简单,只需要对构建过程中的操作命令进行排列组合并详细写出项目所对应的证书和配置概要文件即可实现自动化构建过程,经测试和实际使用经验总结,比较常用的命令如下所示:表1 编译参数解析

命令名称实际用途
-sdk使用指定的SDK编译项目,一般与Xcode版本保持相对一致
-configuration使用指定的方式进行构建操作,一般包括Release Debug等
-project构建项目工程文件(.xcodeproj)位置
-scheme项目主target的名称
clean用于清理项目工程下临时文件以及上次构建生成目标码
archive以生成目标码(.ipa)的方式进行构建
archivePath目标码(.ipa)储存路径
OTHER_CODE_SIGN_FLAGS添加额外的命令用于构建过程中证书的使用和授权
-keychain授权使用指定目录导入证书和配置概要文件
CODE_SIGN_IDENTITY使用证书的名称
PROVISIONING_PROFILE配置概要文件UUID名称

为了更好对iOS集中构建过程进行解析,将上述命令行带入项目运行可以看出实际效果如下:

usr/bin/xcodebuild
-sdk iphoneos12.2
-configuration Release
-project /Users/abc2/APP/ABC.xcodeproj
-scheme ABC
clean
archive
-archivePath /Users/abc2/APP
CODE_SIGN_IDENTITY=iPhone Distribution: AGRICULTURAL BANK OF CHINA
PROVISIONING_PROFILE=XXXX-XXXX-XXXX-XXXX

为了与集中构建工具进行集成也可新增证书及配置概要文件授权路径至集中构建目录。

usr/bin/xcodebuild
-sdk iphoneos12.2
-configuration Release
-project /Users/abc2/APP/ABC.xcodeproj
-scheme ABC
clean
archive
-archivePath /Users/abc2/APP
OTHER_CODE_SIGN_FLAGS=--keychain=/Users/abc2/_xcodetasktmp.keychain
CODE_SIGN_IDENTITY=iPhone Distribution: AGRICULTURAL BANK OF CHINA
PROVISIONING_PROFILE= XXXX-XXXX-XXXX-XXXX

2)单证书双配置概要文件集中构建模式
这类构建模式相对比较复杂,由于项目使用了两个配置概要文件,所以无法沿用单证书单配置概要文件的集中构建模式,并且现有命令行方式不支持设置多个配置概要文件,如果只设置单个在构建的过程中很容易产生匹配错误导致构建失败。为了解决上述问题,经过对编译参数的研究和实践,制定出一套比较合理可行的构建解决方案帮助项目组解决双配置概要文件的集中构建问题。对于单证书双配置概要文件项目的集中构建参数设置如下:表2 打包命令参数解析

命令名称实际用途
exportArchive指定归档应导出
exportPath指定从存档导出的项目的目标
exportOptionsPlist指定用于配置归档导出plist文件的路径

关于exportArchive命令,属于打包操作是结合exportPath和exportOptionsPlist命令一起使用的,实际使用格式如下:

Xcodebuild -exportArchive -archivePath <xcarchivepath> [-exportpath <destinationpath>] -exportOptionsPlist <plistpath>

使用了单证书双配置概要文件项目,需要对构建命令进行拆分,将原先的构建打包一体化命令,拆分成构建+打包两层命令行方式进行。

/usr/bin/xcodebuild
-sdk iphoneos12.2
-configuration Release
-project /Users/abc2/APP/ABC.xcodeproj
-scheme ABC
clean
archive

在进行了构建操作后,再通过ExportOptions.plist将两套配置文件与构建项目进行结合,进而生成最终的目标码程序,代码如下:

/usr/bin/xcodebuild
-exportArchive
-archivePath /Users/abc2/APP/ABC.xcarchive
-exportPath /Users/abc/iphoneos12.2/Release/_XcodeTaskExport_APP
-exportOptionsPlist /Users/abc/ios/APP/Resources/ExportOptions.plist

其中ExportOptions.plist文件是在手动构建项目成功后自动生成的,文件中记录了两个配置概要文件对应规则,在自动构建的过程中,程序直接调用该plist文件就可正确进行匹配,最终实现项目的构建打包自动化的过程。


五、总结




经过一年多的努力和实践,iOS集中构建实现了投产项目集中构建全覆盖,iOS应用实现了标准化构建模式,研究制定“编译命令+编译工具参数+工程路径+主target+证书+配置文件”以及“编译命令+编译工具参数+工程路径+主targe+Exportoptions.plist”的单证书单配置文件和单证书多配置文件的编译方法。在编译过程中将证书及配置文件进行注入,有效管理证书的同时解决了多个项目开发人员日常构建和投产的需要,由以往的“跑腿去投产”转变为“动动手指去投产”,提高了开发效率,提升了工作质量并建立标准化的构建发布流程。在后续工作开展当中我们将一如既往的披荆斩棘,不断深化扩展集中构建成果,积极探索后续开发实践过程。


【作者简介】系统支持部 霍晓楠

从事配置管理工作10余年,先后承担农行研发中心主机、开放、移动平台的配置管理和集中构建工作,对于各类语言的集中构建都有一定的实践并坚持在推广和知识传播的道路上越走越远,越走越精,奉行只有写不出来的脚本,没有做不了的集中构建,只要你给我脚本我就能圆一个投产上线的梦的工作准则。 


©著作权归作者所有:来自51CTO博客作者mob604756e58279的原创作品,如需转载,请注明出处,否则将追究法律责任

更多相关文章

  1. 微服务架构中如何快速构建一个数据报告服务?
  2. 编写Dockerfile最佳实践
  3. 编写 Dockerfile 最佳实践
  4. 构建用户评分体系
  5. 三分钟构建自动化运维平台-nightingale(夜莺)
  6. Nginx编译报错解决方法
  7. [灾备]通过 NAS 与文件服务器结合构建数据容灾系统
  8. Hadoop3.x进阶:源码编译全记录
  9. LAMP分离架构部署wordpress和LogAnalyzer

随机推荐

  1. Android studio 串口通信(动态获取串口)
  2. Android 使用CountDownTimer实现倒计时
  3. Android基于Handler实现倒计时
  4. android安装后控件拖不动问题解答
  5. Android 中可重写的一些样式
  6. android Intent的一些用法
  7. Android 引入AspectJ的记录
  8. 安卓笔记:安卓控件属性大全
  9. Android样式的开发:drawable汇总篇
  10. [Android系列—] 1. Android 开发环境搭