OCLint 初探

文章結(jié)構(gòu):

1. 什么是 OCLint

OCLint 是針對于 C,C++,Objective-C 代碼的靜態(tài)分析工具,目的是提高軟件質(zhì)量并且減少代碼中存在的潛在問題洼裤,OCLint 旨于分析以下潛在問題:

  • 可能出現(xiàn)的 bug:if/else/try/catch 等條件語句空的聲明
  • 未使用的代碼: 未使用的局部變量以及參數(shù)
  • 復雜的代碼邏輯:高循環(huán)復雜度邻辉、NP 復雜度(懵)、 高 NCSS(懵)
  • 冗余代碼:冗余的條件表達式以及無效的括號
  • 代碼嗅覺:方法代碼行過長或者參數(shù)過多
  • 不好的代碼習慣:顛倒的邏輯和參數(shù)的錯誤分配
  • ...

靜態(tài)代碼分析工具是偵測編譯器不可見的潛在缺陷的關(guān)鍵技術(shù)腮鞍。OCLint 具有以下先進的代碼檢驗特性:

  • 依靠源碼的抽象語法樹來提高分析的精確度以及效率值骇,誤報率低
  • 動態(tài)規(guī)則
  • 靈活可擴展的配置,確保用戶可以自定義分析行為
  • 命令行式的調(diào)用使持續(xù)集成成為可能

2. OCLint 安裝

下載 OCLint

2.1. Homebrew 安裝

確保你已經(jīng)安裝了 Homebrew

$ brew install oclint

近些天使用 Homebrew 安裝 OCLint 經(jīng)常失敗移国,遂放棄了這種安裝方式吱瘩。

2.2. 下載并設(shè)置下載目錄為環(huán)境變量

添加以下代碼到命令行啟動文件中,默認啟動文件是 .bashrc.bash_profile 迹缀,安裝 oh-my-zsh 后是 .zshrc 文件使碾。

$ OCLINT_HOME=path-to-oclint-release
$ export PATH=$OCLINT_HOME/bin:$PATH

解釋path-to-oclint-release是 OCLint 安裝包的路徑

使用以下命令判斷是否添加環(huán)境變量成功

echo $PATH

2.3. 下載并拷貝至系統(tǒng)環(huán)境變量中

也可以直接將 OCLint 的可執(zhí)行文件拷貝至系統(tǒng)文件夾 /usr/local/bin∽6可以注意到 /usr/local/bin 也在 PATH 中票摇。

cd oclint
cp bin/oclint* /usr/local/bin/
cp -rp lib/* /usr/local/lib/

3. OCLint 工具的組成

OCLint 工具集由一下三部分組成

  • oclint
  • oclint-json-compilation-database
  • oclint-xcodebuild

具體的使用手冊還是建議大家去閱讀他們的官方文檔,其功能可以簡單概括為:

  • oclint 是 OCLint 工具集最主要的指令砚蓬,主要作用是規(guī)則加載矢门、編譯分析選項以及生成分析報告
  • oclint-json-compilation-database 的作用是在 JSON Compilation Database format 類型的編譯文件 compile_commands.json 中提取必要的信息。
  • oclint-xcodebuild 用于將 xcodebuild 生成的 log 文件 xcodebuild.log 轉(zhuǎn)換為 JSON Compilation Database format 類型

可以使用時序圖來概括我們使用這幾個指令的場景:


oclint-sequence

4. OCLint 的使用

4.1. OCLint 結(jié)合 xcodebuild 的使用

xcodebuild 命令用來編譯 Xcode 工程,xcodebuild 可以編譯 Xcode 工程里面的一個或多個 target祟剔,也可以用來編譯 Xcode workspace 或者 Xcode project 中的任意一個 scheme隔躲。

OCLint 結(jié)合 xcodebuild 的使用主要分為一下幾個步驟

  1. 使用 xcodebuild clean 清理工程(可選)
  2. 使用 xcodebuild build 編譯工程 并且使用 xcpretty 輸出編譯文件
  3. 使用 oclint-json-compilation-database 輸出分析結(jié)果

4.1.1. 清理工程(可選)

假設(shè)一個源文件已經(jīng)使用 xcodebuild 編譯過了,并且沒有被修改物延,那么下次編譯的時候改源文件不參與編譯宣旱,也就是說生成的 compile_commands.json 文件里面是不含有該源文件的內(nèi)容的。如果你希望該源文件每次都編譯,可以使用 xcodebuild clean 指令來清理編譯緩存党饮。

然而 clean 過后,編譯過程會變得相當漫長,這種現(xiàn)象在大項目中表現(xiàn)最為明顯奋刽。所以說如果你的項目文件沒改動,工程的編譯選項也未修改肠缔。使用上次的 xcodebuildcompile_commands.json 進行分析也是可取的鸯两。這里是否可以得出增量編譯的條件下,項目中未變動代碼的部分是不會出現(xiàn)在新的編譯報告中的蓉冈。

4.1.2. 編譯工程城舞,輸出編譯報告

使用 xcodebuild 命令編譯工程,例如使用一下命令編譯 OCLintDemo.xcworkspace 下的 OCLintDemo scheme寞酿。

xcodebuild -workspace       OCLintDemo.xcworkspace \
           -scheme          OCLintDemo \
           -configuration   Debug \
           -sdks            iphonesimulator10.3 \
           build

此時就有兩種方式生成 compile_commands.json家夺。

方式一:使用 tee 指令獲取輸出結(jié)果為 xcodebuild.log ,使用 oclint-xcodebuild 將 xcodebuild.log 輸出為 compile_commands.json 文件

xcodebuild -workspace       OCLintDemo.xcworkspace \
           -scheme          OCLintDemo \
           -configuration   Debug \
           -sdks            iphonesimulator10.3 \
           build | tee xcodebuild.log

oclint-xcodebuild

方式二:使用 xcpretty 直接將編譯結(jié)果輸出為 compile_commands.json

xcodebuild -workspace       OCLintDemo.xcworkspace \
           -scheme          OCLintDemo \
           -configuration   Debug \
           -sdks            iphonesimulator10.3 \
           build | xcpretty -r json-compilation-database -o compile_commands.json

推薦使用 xcpretty 的方式生成 json-compilation-database 類型的編譯報告伐弹。

4.1.3. 輸出分析結(jié)果

使用 oclint-json-compilation-database 指令來解析 json-compilation-database 類型的編譯報告拉馋。

$ oclint-json-compilation-database --help
usage: oclint-json-compilation-database [-h] [-v] [-debug] [-i INCLUDES]
                                        [-e EXCLUDES]
                                        [oclint_args [oclint_args ...]]

OCLint for JSON Compilation Database (compile_commands.json)

positional arguments:
  oclint_args           arguments that are passed to OCLint invocation

optional arguments:
  -h, --help            show this help message and exit
  -v                    show invocation command with arguments
  -debug, --debug       invoke OCLint in debug mode
  -i INCLUDES, -include INCLUDES, --include INCLUDES
                        extract files matching pattern
  -e EXCLUDES, -exclude EXCLUDES, --exclude EXCLUDES
                        remove files matching pattern

從引導上來看,oclint-json-compilation-database 可以通過 -e 選項來忽略對制定路徑文件的分析惨好,對于使用 Cocoapods 來管理依賴的工程煌茴,我們往往會忽略 Pods 文件夾。

oclint-json-compilation-database -e Pods -- xxxx

通常使用 -- 來分割 oclint-json-compilation-database 的參數(shù)與 oclint_args日川。oclint_args 就是 oclint 命令的參數(shù)蔓腐,接下來我們來看看 oclint 指令支持的參數(shù)。

$ oclint --help
USAGE: oclint [options] <source0> [... <sourceN>]

OPTIONS:

OCLint options:

  -R=<directory>                - Add directory to rule loading path
  -allow-duplicated-violations  - Allow duplicated violations in the OCLint report
  -disable-rule=<rule name>     - Disable rules
  -enable-clang-static-analyzer - Enable Clang Static Analyzer, and integrate results into OCLint report
  -enable-global-analysis       - Compile every source, and analyze across global contexts (depends on number of source files, could results in high memory load)
  -extra-arg=<string>           - Additional argument to append to the compiler command line
  -extra-arg-before=<string>    - Additional argument to prepend to the compiler command line
  -list-enabled-rules           - List enabled rules
  -max-priority-1=<threshold>   - The max allowed number of priority 1 violations
  -max-priority-2=<threshold>   - The max allowed number of priority 2 violations
  -max-priority-3=<threshold>   - The max allowed number of priority 3 violations
  -no-analytics                 - Disable the anonymous analytics
  -o=<path>                     - Write output to <path>
  -p=<string>                   - Build path
  -rc=<parameter>=<value>       - Override the default behavior of rules
  -report-type=<name>           - Change output report type
  -rule=<rule name>             - Explicitly pick rules

Generic Options:

  -help                         - Display available options (-help-hidden for more)
  -help-list                    - Display list of available options (-help-list-hidden for more)
  -version                      - Display the version of this program

-p <build-path> is used to read a compile command database.

    For example, it can be a CMake build directory in which a file named
    compile_commands.json exists (use -DCMAKE_EXPORT_COMPILE_COMMANDS=ON
    CMake option to get this output). When no build path is specified,
    a search for compile_commands.json will be attempted through all
    parent paths of the first input file . See:
    http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html for an
    example of setting up Clang Tooling on a source tree.

<source0> ... specify the paths of source files. These paths are
    looked up in the compile command database. If the path of a file is
    absolute, it needs to point into CMake's source tree. If the path is
    relative, the current working directory needs to be in the CMake
    source tree and the file must be in a subdirectory of the current
    working directory. "./" prefixes in the relative files will be
    automatically removed, but the rest of a relative path must be a
    suffix of a path in the compile command database.

For more information, please visit http://oclint.org

如果想最終輸出一個 HTML 類型的分析報告龄句,一個完整的 oclint-json-compile-database 指令應(yīng)該這么寫

$ oclint-json-compilation-database -e Pods -- -o=report.html

4.2. 使用 OCLint 分析 Xcode 工程

Using OCLint with Xcode

5. OCLint 與持續(xù)集成

6. 遇到的問題

6.1. PCH 錯誤

Compiler Errors: (please be aware that these errors will prevent OCLint from analyzing this source code) :0:0: input is not a PCH file: '/xxx/PrefixHeader.pch.pch' :0:0: file '/xxx/PrefixHeader.pch.pch' is not a valid precompiled PCH file :0:0: input is not a PCH file: '/xxx/PrefixHeader.pch.pch' :0:0: file '/xxx/PrefixHeader.pch.pch' is not a valid precompiled PCH file OCLint Report Summary: TotalFiles=0 FilesWithViolations=0 P1=0 P2=0 P3=0 [OCLint (http://oclint.org) v0.12]

沒找到問題原因回论,目前只知道將編譯選項 Precompile prefix header 設(shè)置為 NO 可以解決問題。

6.2. oclint: error: violations exceed threshold

運行 oclint-json-compilation-databse 以下錯誤

$ oclint-json-compilation-database -e Pods -- -o=report.html
oclint: error: violations exceed threshold
P1=0[0] P2=1637[10] P3=53904[20]

出現(xiàn)這個的原因是項目中的 issue 超過了限制分歇,使用以下 option 來約定最大的 issue 閾值傀蓉。

-max-priority-1=9999 -max-priority-2=9999 -max-priority-3=9999

7. 引用文檔

OCLint Documentation

Using OCLint with xcodebuild

Using OCLint with Xcode

oclint-json-compilation-database

json-compilation-database

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市卿樱,隨后出現(xiàn)的幾起案子僚害,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,311評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件萨蚕,死亡現(xiàn)場離奇詭異靶草,居然都是意外死亡,警方通過查閱死者的電腦和手機岳遥,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評論 2 382
  • 文/潘曉璐 我一進店門奕翔,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人浩蓉,你說我怎么就攤上這事派继。” “怎么了捻艳?”我有些...
    開封第一講書人閱讀 152,671評論 0 342
  • 文/不壞的土叔 我叫張陵驾窟,是天一觀的道長。 經(jīng)常有香客問我认轨,道長绅络,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,252評論 1 279
  • 正文 為了忘掉前任嘁字,我火速辦了婚禮恩急,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘纪蜒。我一直安慰自己衷恭,他們只是感情好,可當我...
    茶點故事閱讀 64,253評論 5 371
  • 文/花漫 我一把揭開白布纯续。 她就那樣靜靜地躺著随珠,像睡著了一般。 火紅的嫁衣襯著肌膚如雪杆烁。 梳的紋絲不亂的頭發(fā)上牙丽,一...
    開封第一講書人閱讀 49,031評論 1 285
  • 那天,我揣著相機與錄音兔魂,去河邊找鬼烤芦。 笑死,一個胖子當著我的面吹牛析校,可吹牛的內(nèi)容都是我干的构罗。 我是一名探鬼主播,決...
    沈念sama閱讀 38,340評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼智玻,長吁一口氣:“原來是場噩夢啊……” “哼遂唧!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起吊奢,我...
    開封第一講書人閱讀 36,973評論 0 259
  • 序言:老撾萬榮一對情侶失蹤盖彭,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體召边,經(jīng)...
    沈念sama閱讀 43,466評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡铺呵,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,937評論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了隧熙。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片片挂。...
    茶點故事閱讀 38,039評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖贞盯,靈堂內(nèi)的尸體忽然破棺而出音念,到底是詐尸還是另有隱情,我是刑警寧澤躏敢,帶...
    沈念sama閱讀 33,701評論 4 323
  • 正文 年R本政府宣布闷愤,位于F島的核電站,受9級特大地震影響父丰,放射性物質(zhì)發(fā)生泄漏肝谭。R本人自食惡果不足惜掘宪,卻給世界環(huán)境...
    茶點故事閱讀 39,254評論 3 307
  • 文/蒙蒙 一蛾扇、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧魏滚,春花似錦镀首、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,259評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至腥寇,卻和暖如春成翩,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背赦役。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工麻敌, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人掂摔。 一個月前我還...
    沈念sama閱讀 45,497評論 2 354
  • 正文 我出身青樓术羔,卻偏偏與公主長得像,于是被迫代替她去往敵國和親乙漓。 傳聞我的和親對象是個殘疾皇子级历,可洞房花燭夜當晚...
    茶點故事閱讀 42,786評論 2 345

推薦閱讀更多精彩內(nèi)容

  • 寫在前面 剛?cè)肼毜臅r候,博哥交代給我一個任務(wù)叭披,讓我調(diào)研一款叫SonarQube的靜態(tài)代碼分析工具寥殖,我當時跪在了Ce...
    雨潤聽潮閱讀 2,252評論 0 5
  • OCLint是一個強大的靜態(tài)代碼分析工具,可以用來提高代碼質(zhì)量,查找潛在的bug嚼贡,主要針對c,c++和Object...
    劉應(yīng)閱讀 1,280評論 0 1
  • OCLint工具介紹 OCLint是一個靜態(tài)代碼掃描分析工具锋边,可用于提高代碼質(zhì)量和減少潛在的缺陷,目前支持C编曼,C+...
    Lojii閱讀 5,955評論 5 5
  • 失去的那個人 是 一次曾誓死相知卻遭到背棄 最后成為記憶中 永遠 卻無法再一次親密的 那一個人 失去的那個人 和 ...
    因為愛所以執(zhí)著閱讀 463評論 0 1
  • 直接先把方法貼出來(參考了Stack Overflow) 下面解釋下方法中用到的一些類型(參考MDN) Array...
    KimYYX閱讀 16,435評論 4 6