構建iOS持續集成平臺(一)——自動化構建和依賴管理

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在 其主頁直接表明了其目的:

xctool is a replacement for Apple's xcodebuild that makes it easier  to build and
test iOS and Mac products. It's especially helpful for continuous integration.

 

其作用是替代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 <name>”模糊搜索依賴庫中的相似庫,另外,如果你想使用的庫在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中文站投稿或者參與內容翻譯工作,請郵件至[email protected]。也歡迎大家通過新浪微博(@InfoQ)或者騰訊微博(@InfoQ)關注我們,並與我們的編輯和其他讀者朋友交流。

http://www.infoq.com/cn/articles/build-ios-continuous-integration-platform-part1?utm_source=infoq&utm_medium=related_content_link&utm_campaign=relatedContent_articles_clk

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章