OCLint的編譯
基於版本 oclint version 0.15
OCLint
需要自定義規則的話需要自己編譯,如果是簡單的使用,參考 OCLint的使用
從Github
下拉代碼:
git clone https://github.com/oclint/oclint
README.md
oclint-core
oclint-driver
oclint-metrics
oclint-reporters
oclint-rules
oclint-scripts
編譯過程比較長,需要 富牆 纔會快一點
過程中提示錯誤,這裏需要提前安裝 cmake
以及 Ninja
- 安裝
cmake
-
官網下載CMake,傳送門:https://cmake.org/download/
-
命令行輸入
sudo "/Applications/CMake.app/Contents/bin/cmake-gui" --install
-
修改
~/.bash_profile
文件
export CMAKE_ROOT=/Applications/CMake.app/Contents/bin/
export PATH=$CMAKE_ROOT:$PATH
- 終端運行
source ~/.bash_profile
使修改生效
- 安裝
Ninjia
ninja
需要依賴於re2c
,否則編譯是會報錯,re2c
是一款語法分析器
- 安裝
re2c
http://re2c.org/index.html 下載 re2c
下載 re2c-1.3.tar
解壓,然後
cd re2c-1.3
./configure
make
make install
- 安裝ninjia
git clone git://github.com/ninja-build/ninja.git && cd ninja
./configure.py --bootstrap
//mac 10.14以上版本權限可能不夠
cp ninja /usr/bin/
或者拷貝至 /Applications/CMake.app/Contents/bin/
- 編譯OCLint
然後進入oclint-scripts
,執行./make
sheng@chengpengdeMacBook-Pro oclint-scripts % ./make
Cloning into 'oclint-json-compilation-database'...
remote: Enumerating objects: 88, done.
remote: Total 88 (delta 0), reused 0 (delta 0), pack-reused 88
Unpacking objects: 100% (88/88), done.
Cloning into 'oclint-xcodebuild'...
remote: Enumerating objects: 85, done.
remote: Total 85 (delta 0), reused 0 (delta 0), pack-reused 85
Unpacking objects: 100% (85/85), done.
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 657 100 657 0 0 503 0 0:00:01 0:00:01 --:--:-- 503
100 424M 100 424M 0 0 4238k 0 0:01:42 0:01:42 --:--:-- 4720k
...
...
-- The C compiler identification is Clang 10.0.0
-- The CXX compiler identification is Clang 10.0.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /Volumes/CaiCai/OCLint/oclint/build/llvm-install/bin/clang - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /Volumes/CaiCai/OCLint/oclint/build/llvm-install/bin/clang++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
LLVM_ROOT: /Volumes/CaiCai/OCLint/oclint/build/llvm-install
-- Found LLVM LLVM_PACKAGE_VERSION: 10.0.0 - LLVM_VERSION_RELEASE: 10.0.0
-- Using LLVMConfig.cmake in: /Volumes/CaiCai/OCLint/oclint/build/llvm-install/lib/cmake/llvm
-- Configuring done
-- Generating done
-- Build files have been written to: /Volumes/CaiCai/OCLint/oclint/build/oclint-driver
[14/14] Linking CXX executable bin/oclint-0.15
到這裏OCLint
算編譯成功了,但是還無法使用,參考官方文檔 installation 部分說明,我們採用直接添加進PATH
方式
修改 ~/.bash_profile
文件 ,加入以下內容
OCLINT_HOME=/Users/sheng/Documents/Caicai/OCLint/oclint/build/oclint-release
export PATH=$OCLINT_HOME/bin:$PATH
然後 source ~/.bash_profile
使得修改生效
命令行輸入 oclint
進行驗證
sheng@chengpengdeMacBook-Pro ~ % oclint
LLVM ERROR: CommonOptionsParser: failed to parse command-line arguments. [CommonOptionsParser]: oclint: Not enough positional command line arguments specified!
Must specify at least 1 positional argument: See: oclint --help
這樣就算成功了
自定義規則
rule 添加
OCLint
提供了一個腳本程序,位於 oclint-scripts/scaffoldRule
通過他傳入要生成的規則名,級別,類型,腳本就會在目錄oclint-rules/rules/custom/
自動幫我們生成一個模板代碼,並且加入編譯路徑中。舉個例子:
//生成一個名爲 CCRuleTest ,類型爲 ASTVisitor 的規則模板
oclint-scripts/scaffoldRule CCRuleTest -t ASTVisitor
你可以查看 scaffoldRule
文件瞭解更多可配置的參數
arg_parser = argparse.ArgumentParser()
arg_parser.add_argument("class_name", help="class name of the rule")
arg_parser.add_argument("-t", "--type", dest='rule_type', choices=['Generic', 'SourceCodeReader', 'ASTVisitor', 'ASTMatcher'], default="Generic")
arg_parser.add_argument("-c", "--category", dest='rule_category', default="custom")
arg_parser.add_argument("-n", "--name", dest='rule_name', default="")
arg_parser.add_argument("-p", "--priority", type=int, dest='rule_priority', choices=[1, 2, 3], default=3)
arg_parser.add_argument( "--test", dest='generate_tests', action='store_true', help="Generate a test for the new rule (default)")
arg_parser.add_argument( "--no-test", dest='generate_tests', action='store_false', help="Do not generate a test for the new rule")
arg_parser.set_defaults(generate_tests=True)
args = arg_parser.parse_args()
這樣就會在 oclint/oclint-rules/rules/custom
路勁下生成對應的文件
cpp
文件是邏輯實現,txt
文件是規則匹配
Xcode工程創建
我們通過生成xcode工程來直觀的管理各個規則,包括我們新建的rule
,OCLint
工程使用CMakeLists
的方式維護各個文件的依賴關係,我們可以使用CMake
自帶的功能將這些CMakeLists
生成一個xcodeproj
工程文件
OCLint
源碼目錄下建立一個文件夾,命名爲oclint-xcoderules
並創建一個腳本 ./create-xcode-rules.sh
,鍵入內容如下:
#! /bin/sh -e
cmake -G Xcode -D CMAKE_CXX_COMPILER=../build/llvm-install/bin/clang++ -D CMAKE_C_COMPILER=../build/llvm-install/bin/clang -D OCLINT_BUILD_DIR=../build/oclint-core -D OCLINT_SOURCE_DIR=../oclint-core -D OCLINT_METRICS_SOURCE_DIR=../oclint-metrics -D OCLINT_METRICS_BUILD_DIR=../build/oclint-metrics -D LLVM_ROOT=../build/llvm-install/ ../oclint-rules
然後 sh create-xcode-rules.sh
運行腳本,就生成了我們的xcode
工程 OCLINT_RULES
打開工程我們可以發現創建的rule
在裏面
如果使用brew安裝,這個路徑應該是 /usr/local/Cellar/oclint/0.15/lib/oclint/rules
編譯會生成對應的dylib庫
,那我們之後如何更新 OCLint
的規則呢
更新dylib
oclint/build/oclint-release
是最終編輯結果,當我們添加了自定義規則後,自然要將自定義規則添加到oclint-release
中,我們進入 oclint/build/oclint-release/lib/oclint/rules
,可以看到所有的規則dylib都放在這裏,我們將編譯後的dylib放進來,就可以了
這樣命令行調用 oclint
命令就會應用該rule
,但是問題來了,我們如何調試呢,能夠在Xcode
裏面進行調試最好,不然每次編譯,然後查看結果,要崩潰了。
Xcode調試
cd 進入 oclint-driver
目錄下,參考之前的方式,創建 Xcode工程
- 創建 create-xcode-driver.sh
- 腳本內容如下
#! /bin/sh -e
cmake -G Xcode \
-D CMAKE_CXX_COMPILER=../build/llvm-install/bin/clang++ \
-D CMAKE_C_COMPILER=../build/llvm-install/bin/clang \
-D OCLINT_BUILD_DIR=../build/oclint-core \
-D OCLINT_SOURCE_DIR=../oclint-core \
-D OCLINT_METRICS_SOURCE_DIR=../oclint-metrics \
-D OCLINT_METRICS_BUILD_DIR=../build/oclint-metrics \
-D LLVM_ROOT=../build/llvm-install/ ../oclint-driver
你可以每個文件夾生成Xcode工程,修改最後一個參數
這裏對 oclint-driver 生成Xcode工程
-
執行腳本
sh create-xcode-driver.sh
,生成Xcode工程
-
打開
Schemes
面板,配置 啓動參數
-R=/Users/sheng/Documents/Caicai/OCLint/oclint/oclint-xcoderules/rules.dl/Debug -report-type html -o /Users/sheng/Documents/Caicai/OCLint/oclint/output/reporter.html /Users/sheng/Documents/Caicai/OCLint/oclint/demo/test.m -- -x objective-c -isystem /Users/sheng/Documents/Caicai/OCLint/oclint/build/oclint-release/lib/clang/10.0.0/include -iframework /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/System/Library/Frameworks -isystem /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/usr/include
-R
表示設置rule的路徑,我們設置爲rule工程的編譯debug路徑
-report-type html -o
html
文件報告輸出路徑
test.m
我們寫一個本地變量未使用的rule檢測
int main(void) {
int i=9;
return 0;
}
見下圖:
- 拷貝
reporters
文件
設置運行後,終端打印錯誤
oclint: error: cannot find dynamic library for report type: html
Program ended with exit code: 2
搜索錯誤 cannot find dynamic library
斷點查看 reportDirPath
值爲
/Users/sheng/Documents/Caicai/OCLint/oclint/oclint-driver/bin/Debug/../lib/oclint/reporters
因爲我們改了bin
的路徑,它根據 bin路徑/../lib/oclint/reporters
來查找 reporters
,這裏直接將 oclint-release
下的 reporters
連父目錄一起拷貝,構成這個路徑
- 創建
reporter.html
再次運行提示錯誤
oclint: error: cannot open report output file /Users/sheng/Documents/Caicai/OCLint/oclint/output/reporter.html
Program ended with exit code: 4
這裏是創建的 output
文件夾路徑寫錯了,放置到上面所說的正確位置後運行正常
運行正常後,查看 reporter.html
然後進行斷點 UnusedLocalVariableRule.cpp
來進行調試
成功斷點,之後你就可以自行編寫 rule
,並進行調試了