天天看點

iOS批量自動打包和部署(Ⅱ):自動打包

iOS批量自動打包和部署(Ⅱ):自動打包

網上有大把的文章講了自動打包,其實無非就是那幾條指令,但是我覺得有必要繼續了解一下一個app包(即應用)的組成和app可執行檔案的建構過程。這個裡面非常複雜,也參考了一些文章,僅将自己了解的大概梳理出來備忘。

應用的建構過程群組成

想象一下平時的打包過程,在Xcode中選擇對應的appid,bundleid,還要選擇正确的配置檔案(provisioning profile),然後點選

run

,我們看到Xcode上面有内容在不斷的更新,正如猜想的,更新的内容實際就是app包編譯的過程。

這個過程大概經過了:配置(編譯器确定目前系統環境)-> 确定标準庫和頭檔案的位置->确定依賴關系->頭檔案預編譯(precompilation)->預處理(preprocessing)->編譯(compilation)->連接配接(Linking)->打包,大緻步驟是這些,但其中還有一些過程是沒有講的。

對于iOS的包來講,在建構完成之後還會自動調用

codesign

指令進行簽名,這個時候我們之前選擇的bundleid啊,配置檔案啊等等就排上用場了。經過簽名後的應用是個相對來講安全的應用,通過簽名確定了包的來源合法,也能確定包的内容是否被修改過(理論知識上篇已講過)。最後的包的本質實際上是一個Mach-O格式的二進制可執行檔案(簽名的資料就在這個二進制檔案中)和一些資源檔案。

Mach-O可執行檔案

Mach是一種作業系統核心。它的大緻曆史是:Mach核心被NeXT公司的NeXTSTEP作業系統使用,NeXT是喬布斯蘋果被趕出蘋果後建立的公司。1996年,喬布斯将NeXTSTEP帶回蘋果,成為了OS X的核心基礎。在Mach上,一種可執行的檔案格是就是Mach-O(Mach Object file format)。iOS是從OS X演變而來,是以同樣支援Mach-O格式的可執行檔案。

搞iOS的肯定知道ipa包,它實際上就是一個zip壓縮包,可以用mac自帶的歸檔解壓工具進行解壓。解壓之後會有一個

Payload

檔案夾,其中有個

XXX.app

這樣的

.app

檔案,它實際上是檔案夾,它裡面除了有個各種資源、圖檔等,還有個和包名相同的檔案——這個就是二進制可執行檔案。可以用

file

指令檢視檔案類型,下圖是微信包的截圖:

iOS批量自動打包和部署(Ⅱ):自動打包

從上面看是支援arm7和arm64兩種處理器架構的通用程式包,裡面的格式是Mach-O。将微信的可執行檔案

WeChat

用Sublime打開,二進制開始部分如下:

iOS批量自動打包和部署(Ⅱ):自動打包

開頭的4個位元組是cafebabe,這被稱為“魔數”,反映檔案的類型。查了下相關文章,OS X上還有如下幾個辨別:

cafebabe
feedface
feadfacf
還有一個格式,就是以#!開頭的腳本

cafebabe就是跨處理器架構的通用格式,feedface和feedfacf則分别是某一處理器架構下的Mach-O格式,腳本的就很常見了,比如#!/bin/bash開頭的shell腳本。
           

Mach-O可執行檔案包含頭部資訊和加載指令。才疏學淺,這部分也沒有深入了解,本篇也無法繼續深入講這塊了。

其他資源檔案

解壓後的包中除了可執行檔案還有其他資源檔案,圖檔啊,plist啊等等。蘋果對安全确實重視,這些資源檔案其實大多數也是需要被設定簽名的,可以見到的是包中還有一個

_CodeSignature

檔案夾,這個檔案夾中的

CodeResources

檔案中存儲了被簽名的程式包中所有需要被簽名檔案的簽名。更詳細的介紹參見《代碼簽名探析》,從這些細節不難看出蘋果對于安全的重視。

自動打包

蘋果自帶的xcodebuild指令行工具就可以打包,但是這裡我更加推薦facebook出品的xctool,xctool的初衷就是要替代蘋果的xcodebuild,它們的指令參數都是一樣的,相比較xcodebuild,xctool有以下特點:

1.相比較xcodebuild輸出的log雜亂,xctool更有結構
2.xctool有人性化的顔色輸出
3.facebook聲稱xctool更快,據說能快2、3倍
4.完全用Ojbective-C實作
           

當然xctool隻支援Xcode6及以上,并且

Xcode Command Line Tools

安裝好。

xctool

xctool是可以使用homebrew安裝的,或者下源碼然後運作 

xctool.sh

腳本,homebrew安裝指令如下:

brew install xctool
           

實戰

接下來是實戰篇,按照我的設想,如果想要實作自動化,需要攻克幾個點:

1.自動打包
2.重新簽名
3.分發部署
           

其中,自動打包是基礎,打包完之後可以根據母包重新簽名生成相似的包,生成的包可以自動部署。隻要攻克這三個點就能實作全自動化,當然就需要寫腳本了,帶着這個性質我參考了一些文章并且在網上找到了一些腳本。最終,驗證了這些東西都是實際可行的。但,下面的實戰用到的腳本,一部分是網上找的,一部分是同僚寫的,當時雖然逐個研究了但是卻沒有精力在這個上,這部分的工作最後是同僚做的。

為了講的更清楚,建立了一個項目

PackageExample

(Demo已上傳到這裡),并且使用了CocoaPods(實驗起見僅引用了AFNetworking),項目的證書是dev狀态的。

PackageExample

項目在我機器上的路徑和目錄如下截圖:

iOS批量自動打包和部署(Ⅱ):自動打包

PackageExample

同目錄的還有

PackageShell

,裡面的

buildipa.sh

為編譯腳本,由于最後的目标是要做成可以随意配置的,是以還有一個

PackageConfig

檔案夾,裡面有配置檔案

packageExample.mobileprovision

packageExample.plist

,配置檔案主要用來簽名,plist檔案的内容為可配置的,例如裡面有app_Prefix、app_Name、app_ID等資訊。

Package

檔案夾為打的包的存放的地方。

完整的編譯腳本如下:

#!/bin/sh

#從plist檔案中讀取ipa包名和配置檔案名
profile_Name=`/usr/libexec/PlistBuddy -c "print profile_Name" ./PackageConfig/packageExample.plist`
ipa_Name=`/usr/libexec/PlistBuddy -c "print app_Name" ./PackageConfig/packageExample.plist`

#進入工程目錄
cd ../PackageExample
echo "go to packageExample workspace path"

#報名時根據時間戳命名的,是以這裡有用到
buildTime=$(date +%Y%m%d%H%M)

profile="${profile_Name}"

echo $profile $ipa_Name

#一下方法主要是建立打包的路徑和最後導出的ipa的路徑
if [ ! -d "../PackageShell/Package" ]; then
    mkdir ../PackageShell/Package
fi

if [ ! -d "../PackageShell/Package/ArchiveProduction" ]; then
    mkdir ../PackageShell/Package/ArchiveProduction
fi

if [ ! -d "../PackageShell/Package/ArchiveProduction/QA" ]; then
    mkdir ../PackageShell/Package/ArchiveProduction/QA
    echo "Create ArchiveProduction path"
fi

if [ ! -d "../PackageShell/Package/ipa" ]; then
    mkdir ../PackageShell/Package/ipa
fi

if [ ! -d "../PackageShell/Package/ipa/QA" ]; then
    mkdir ../PackageShell/Package/ipa/QA
    echo "Create ipa path"
fi

buildConfiguration="QA"

buildPath="../PackageShell/Package/ArchiveProduction/QA/${ipa_Name}_${buildTime}.xcarchive"
ipaName="../PackageShell/Package/ipa/QA/${ipa_Name}_${buildTime}.ipa"

#先進行clean操作
xctool -workspace PackageExample.xcworkspace -scheme PackageExample -configuration ${buildConfiguration} clean

#打包的指令
xctool -workspace PackageExample.xcworkspace -scheme PackageExample -configuration ${buildConfiguration} archive -archivePath ${buildPath}
#導出ipa包的指令,
xcodebuild -exportArchive -exportFormat IPA -archivePath ${buildPath} -exportPath ${ipaName} -exportProvisioningProfile "$profile"
           

做一些解釋,腳本的開頭有

PlistBuddy

指令,它是Mac下一個用來讀寫plist檔案的工具,在/usr/libexec/下。

xctool -workspace PackageExample.xcworkspace -scheme PackageExample -configuration ${buildConfiguration} clean

,由于項目是workspace,是以這裡必須要對應,如果是project則是project,clean的目的是進行清理緩存等。

xctool -workspace PackageExample.xcworkspace -scheme PackageExample -configuration ${buildConfiguration} archive -archivePath ${buildPath}

archive

指令主要用來打包,最後包的格式為

xcarchive

。可以進入這個包裡,目錄結構如圖:

iOS批量自動打包和部署(Ⅱ):自動打包

主要是産生了 

dsYM

和 

.app

檔案,并且可以看到的是它是已經經過簽名的。雖然從指令中沒有指定profile,但是我看到編譯的log輸出有以下這段:

iOS批量自動打包和部署(Ⅱ):自動打包

Sign PackageExample.app

,推測這步是進行簽名了,至于為什麼指令中沒有指定也可以編譯那是因為在Xcode中進行過手動設定(?:猜測是)。最後一步導入ipa主要用

xcodebuild

指令,至少在當時我找到的是這個指令而不是xctool。經過導出的ipa包,簡單點的,可以郵件群發給同僚進行測試。

小結

至此,差不多介紹完自動打包的一種方案。但其實還可以延伸,主要反映在兩點上:

1.雖然能夠成功打一個包,但是本系列文章第一篇開始部分中提到的,如何快速複制兩個很相似但又不同的包?
2.導出來的ipa包,用郵件群發是否仍然麻煩,能否繼續實作自動化?
           

上面的兩點實際上都能很好的解決,也就是前面說到的要攻克

2.重新簽名

 和 

3.分發部署

,下篇文章會介紹我的解決思路,裡面涉及重新簽名和一些上傳工具。

轉載于:https://my.oschina.net/hejunbinlan/blog/721184

繼續閱讀