項目結構
- CocoaPods做業務劃分,每條業務線一個工程,每個工程依賴基礎框架,業務線之間解耦依賴基礎模塊
- 純Objective-C代碼,沒有引入Swift代碼
- 獨立服務器安裝Xcode通過Jenkins打包,發布到fir.im
- 2C端目前代碼量33W左右,2B端28W左右
打包時間
隨著項目的逐漸增大打包時間越來越久。代碼打包是放在獨立的服務器上,因為只是用來做項目打包使用,因此性能配置較低。為了保證每次打包的代碼的完整性,每次都會進行全量的更新(包含Pods私有庫和公共庫的更新)。代碼更新和Pos更新的時間加上編譯時間安裝包上傳時間,2C端項目完整的打包時間基本在800s左右,2B端項目在1200s左右。長久的等待實在讓人有些崩潰。
解決方案
ccache is a compiler cache. It speeds up recompilation by caching previous compilations and detecting when the same compilation is being done again. Supported languages are C, C++, Objective-C and Objective-C++.
ccache是一個可以把編譯中間產物緩存起來的工具,目前可以支持C、C++、Objective-C、Objective-C++,滿足目前需求
安裝ccache
如果已經安裝過homebrew(Mac OSX上的軟件包管理工具),可以通過以下命令直接安裝:
brew install ccache
如果沒有安裝homebrew,需要先安裝homebrew
ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
創建ccache編譯腳本
安裝完ccache之后我們需要讓它介入到整個編譯過程,如果發現ccache就用ccache編譯,如果沒有就走原有的clang
新建一個空白文本文件
touch ccache-clang
保存如下內容:
#!/bin/sh
if type -p ccache >/dev/null 2>&1; then
export CCACHE_MAXSIZE=10G
export CCACHE_CPP2=true
export CCACHE_HARDLINK=true
export CCACHE_SLOPPINESS=file_macro,time_macros,include_file_mtime,include_file_ctime,file_stat_matches
exec ccache /usr/bin/clang "$@"
else
exec clang "$@"
fi
腳本比較容易理解,先判斷ccache的執行路徑是否存在,如果存在設置ccache的參數,并啟動ccache編譯,如果不存在走原有clang編譯
修改touch ccache-clang的權限為可執行
chmod 755 ccache-clang
Xcode項目修改
定義CC常量
在項目構建設置(Build Settings)中,添加一個常量CC,Xcode編譯時會調用該路徑下的編譯器
如果ccache-clang跟工程文件平級,CC常量值可以設置為
$(SRCROOT)/ccache-clang
關閉Clang Modules
因為ccache不支持Clang Modules,所以需要把Enable Modules關閉
關閉Enable Modules后需要修改@import 為 #import,如果用到了系統框架還需要在Target 的 Build Phrase -> Link Binary With Libraries手動引入
CocoaPods處理
CocoaPods會把項目打包成靜態庫或者動態Framework,也需要把 Enable Modules選項關閉,這個操作需要在Podfile文件中完成
在Podfile文件中增加如下配置
require 'fileutils'
post_install do |installer_representation|
installer_representation.pods_project.targets.each do |target|
target.build_configurations.each do |config|
#關閉 Enable Modules
config.build_settings['CLANG_ENABLE_MODULES'] = 'NO'
# 在生成的 Pods 項目文件中加入 CC 參數
config.build_settings['CC'] = '$(SRCROOT)/ccache-clang'
end
end
# 拷貝主工程的ccache-clang文件到Pods下面
FileUtils.cp('ccache-clang', 'Pods/ccache-clang')
end
查看編譯結果
在第一次啟動ccache編譯時因為所有文件都沒有做過編譯緩存,因此是沒有任何提升效果的,反而由于ccache自己的緩存策略會降低編譯速度,從第二次開始編譯速度就會有所提升
ccache -s
cache directory /Users/ecotech/.ccache
primary config /Users/ecotech/.ccache/ccache.conf
secondary config (readonly) /usr/local/Cellar/ccache/3.2.3/etc/ccache.conf
cache hit (direct) 5484
cache hit (preprocessed) 0
cache miss 3436
called for link 10
called for preprocessing 30
can't use precompiled header 1896
no input file 10
files in cache 15504
cache size 2.8 GB
max cache size 10.0 GB
2C項目 優化前:615s 優化后:266s 提升:56.7%
2B項目 優化前:902s 優化后:403s 提升:55.3%