OCLint 代碼靜態(tài)分析
為了提高代碼質(zhì)量和代碼走查的效率,軟件開發(fā)過程中一般會(huì)使用靜態(tài)代碼分析工具來對程序正確性和穩(wěn)定性進(jìn)行檢查。靜態(tài)代碼分析利用詞法分析、語法分析、抽象語法樹以及語義分析等手段檢查代碼中潛在的錯(cuò)誤過程。該過程與動(dòng)態(tài)分析相對應(yīng),不需要執(zhí)行應(yīng)用程序,直接通過對代碼掃描發(fā)現(xiàn)隱含的程序問題,并給出一定的修改建議。
OCLint 是基于 Clang 的靜態(tài)分析工具,支持對 C、C++ 和 Objective-C 代碼進(jìn)行靜態(tài)分析,它基于 Clang 輸出的抽象語法樹對代碼進(jìn)行靜態(tài)分析,支持與現(xiàn)有的 CI 集成,部署之后基本不需要維護(hù),簡單方便。
下面將從 OCLint 安裝、與 Xcode 集成和與 CI 集成這三個(gè)方面來展開介紹。
OCLint 安裝
OCLint 支持三種方式安裝:
- 下載二進(jìn)制包,將 bin 目錄添加到 PATH 下(.bashrc 或 .bash_profile)
OCLINT_HOME=/path/to/oclint-release
export PATH=$OCLINT_HOME/bin:$PATH
- 拷貝 OCLint 至系統(tǒng) PATH
直接將二進(jìn)制拷貝到 PATH 路徑下,比如拷貝到 /usr/local/bin,/usr/bin,/bin 目錄。這里以 /usr/local/bin 目錄為例:
1. `cp bin/oclint* /usr/local/bin/`
2. `cp -rp lib/* /usr/local/lib/`
同時(shí)需要將依賴的庫放到相應(yīng)的目錄中,oclint 執(zhí)行時(shí)會(huì)默認(rèn)搜索如下目錄 $(/path/to/bin/oclint)/../lib/clang, $(/path/to/bin/oclint)/../lib/oclint/rules 和 $(/path/to/bin/oclint)/../lib/oclint/reporters 來查找頭文件和動(dòng)態(tài)庫。
- Homebrew 安裝
安裝 OCLint:
$ brew tap oclint/formulae
$ brew install oclint
更新 OCLint:
$ brew update
$ brew upgrade oclint
安裝好后在終端中輸入 oclint 驗(yàn)證是否成功安裝,如出現(xiàn)如下提示說明已安裝成功:
$ oclint
oclint: Not enough positional command line arguments specified!
Must specify at least 1 positional arguments: See: oclint -help
Xcode 集成
OCLint 支持與 Xcode 集成,集成后只需在 Xcode 中跑一遍腳本即可完成對代碼的靜態(tài)分析,并且在 Xcode 中定位到對應(yīng)的行。
具體集成步驟如下:
- 添加 Target
在 Xcode 中新增 Aggregate Target:

- 添加
Run Script

- 填充腳本內(nèi)容

- 執(zhí)行分析
選擇新增的 Scheme,點(diǎn)擊編輯或者 Command+B

CI 集成
項(xiàng)目組目前使用 fastlane 進(jìn)行持續(xù)集成,使用一段時(shí)間后發(fā)現(xiàn)確實(shí)大大的減少重復(fù)工作,把程序員從重復(fù)的工作中解放出來。fastlane 的具體安裝使用篇幅較長,后面會(huì)另寫一篇文章進(jìn)行介紹,本章重點(diǎn)介紹如果將 fastlane 和 OCLint 集成,支持自動(dòng)靜態(tài)分析并上傳至 FTP 服務(wù)器。
fastlane 初始化成功后會(huì)創(chuàng)建一個(gè) fastlane 目錄,目錄中 Fastfile 文件包含當(dāng)前 fastlane 所支持的所有任務(wù)。這里我們添加一個(gè)名叫 lint 的任務(wù),該任務(wù)會(huì)分別調(diào)用靜態(tài)分析腳本(oclint_ci.sh)和上傳腳本(oclint_upload.sh)。

這里重點(diǎn)分析 oclint_ci.sh 腳本:
echo "xcodebuild clean"
xcodebuild clean -workspace tztMobileApp_HTSC.xcworkspace \
-scheme tztHuaTaiZLMobile
執(zhí)行靜態(tài)分析前,執(zhí)行 xcode clean 清除上一次編譯生成的文件,這是因?yàn)殪o態(tài)分析依賴編譯過程中的控制臺(tái)輸出,假如文件未做修改編譯器默認(rèn)會(huì)優(yōu)化編譯過程跳過該文件的編譯,則該文件的編譯過程中就不會(huì)產(chǎn)生輸出無法進(jìn)行靜態(tài)分析。
echo "xcodebuild analyze | tee xcodebuild.log | xcpretty --report json-compilation-database"
xcodebuild -workspace XXXApp.xcworkspace \
-scheme XXXApp analyze | tee xcodebuild.log | \
xcpretty --report json-compilation-database
執(zhí)行 xcodebuild analyze | tee xcodebuild.log 將 xcodebuild analyze 輸出的內(nèi)容保存到 xcodebuild.log 文件中,并使用 xcpretty 來格式化成 json 格式。
echo "xcodebuild analyze | tee xcodebuild.log | xcpretty --report json-compilation-database"
xcodebuild -workspace XXXApp.xcworkspace \
-scheme XXXApp analyze | tee xcodebuild.log | \
xcpretty --report json-compilation-database
需要注意的是,上一步生成的 json 文件在 build/reports 下,并且名字為compilation_db.json,和 oclint 默認(rèn)生成的文件命名和路徑均不同,因此需要移動(dòng)至根目錄并重命名為 compile_command.json。
echo "mv compilation_db.json compile_commands.json"
mv ./build/reports/compilation_db.json ./compile_commands.json
最后執(zhí)行 oclint-json-compilation-database 生成靜態(tài)分析報(bào)告,輸出成 html 文檔。
echo "oclint-json-compilation-database"
oclint-json-compilation-database \
-e Pods \
-- \
-stats \
-verbose \
-report-type=html -o=oclint.html \
-max-priority-1=99999 -max-priority-2=99999 -max-priority-3=99999 \
-rc LONG_LINE=200 \
-rc LONG_METHOD=100 \
-rc LONG_VARIABLE_NAME=40 \
-disable-rule=BrokenOddnessCheck \
-disable-rule=VerifyProhibitedCall \
-disable-rule=VerifyProtectedMethod \
-disable-rule=SubclassMustImplement \
-disable-rule=BaseClassDestructorShouldBeVirtualOrProtected \
-disable-rule=DestructorOfVirtualClass \
-disable-rule=ParameterReassignment \
-disable-rule=AvoidDefaultArgumentsOnVirtualMethods \
-disable-rule=AvoidPrivateStaticMembers \
-disable-rule=TooManyParameters
關(guān)于 oclint-json-compilation-database 命令相關(guān)參數(shù)說明可以參閱官方文檔。
Reference:
1.Using OCLint in Xcode
2.OC靜態(tài)代碼檢查及持續(xù)集成
3.OCLint 使用