[转载] OCLint - Objective-C 代码检查

原文地址 https://juejin.cn/post/7091063820973506573

已编译好Xcode14可正常运行的版本https://github.com/WangGuibin/OCLint-FixedXcode14

  1. Objective-C 项目代码检查方式

Xcode Analyze
OCLint
Xcode Analyze 本文不做介绍,默认快捷键shift+cmd+B 运行分析即可。以下介绍 OCLint 执行代码检查。

  1. OCLint 简介
    OCLint 官网地址:https://oclint.org/
    OCLint 仓库地址:https://github.com/oclint/oclint

A static source code analysis tool to improve quality and reduce defects for C, C++ and Objective-C

一个用于C、C++ 和 Objective-C 语言提升质量、减少缺陷的代码静态检查工具。

  1. OCLint 代码检查
    3.1. OCLint 安装
    OCLint 三种安装方式:Homebrew、安装包、源码编译。
    3.1.1. Homebrew 安装
    前置条件:Homebrew
    3.1.1.1. 更新 Homebrew 自身
    必须,确保通过 brew install oclint 安装的是最新版本,否则安装旧版本未适配 Xcode 13 导致最终无法正常生成报表。
    sql复制代码brew update

3.1.1.2. 安装 OCLint
brew tap oclint/formulae
brew install oclint

3.1.1.3. 验证
oclint --version

正常输出:
OCLint (https://oclint.org):

OCLint version 22.02.
Built Feb 19 2022 (21:13:26).

3.1.2. 安装包安装
3.1.2.1. 下载安装包
进入 oclint 仓库,选择 Releases,即可看到所有已发布版本。目前最新版本 22.02,选择 macOS 版本:oclint-22.02-llvm-13.0.1-x86_64-darwin-macos-12.2-xcode-13.2.tar.gz
xcode14系统库都会报错 得用修复分支去build https://github.com/Lianghuajian/oclint/tree/support_xcode14
暂未找到build好的版本 有时间自己build一个
3.1.2.2. 解压
下载完成后,解压到自己习惯的位置,以我放置的目录为例:

/Users/wangguibin/MyShell/oclint-22.02

# .zshrc里配置 OCLint 为环境变量
OCLINT=/Users/wangguibin/MyShell/oclint-22.02
export PATH=$OCLINT/bin:$PATH

更新环境变量PATH:

source ~/.zshrc

验证

oclint --version

正常输出:

OCLint (<https://oclint.org>):
 OCLint version 22.02.
 Built Feb 19 2022 (21:13:26).

3.1.3. 源码编译安装
前置条件:Homebrew
3.1.3.1. 更新 Homebrew 自身
3.1.3.2. 安装 CMakeNinja 编译工具

brew install cmake ninja

3.1.3.3. 下载 OCLint 源码
两种方式下载源码:
1). 进入 oclint 仓库,选择 Code-DownloadZIP,下载并解压;
2). git clone

git clone https://github.com/oclint/oclint.git

3.1.3.4. 编译 OCLint 源码
进入 oclint-scripts 目录,执行:
./make

1). 编译时间较长且必须FQ,过程中会下载 oclint-json-compilation-database、oclint-xcodebuild、llvm 源码以及 clang 源码;
2). 编译结束后,build 目录下即编译完成的 OCLint;
3.1.3.5. 更新环境变量 PATH,同 3.1.2.3
打开配置文件:

~/.zshrc
添加OCLint为环境变量 和上面brew安装一样

配置文件生效:
source ~/.zshrc

3.1.3.6. 验证
oclint --version

正常输出:
OCLint (https://oclint.org):
OCLint version 22.02.
Built Feb 19 2022 (21:13:26).

3.2 XCPretty 安装
前置条件:Ruby Gem
执行:
gem install xcpretty

3.3 OCLint 基本使用
前置条件:Command Line Tools,一般 Xcode 自带
3.3.1. 获取项目信息(可选)
进入项目目录,执行
xcodebuild -list

输出:Information about project "SViewIOS":
Targets:
SViewIOS
SViewTests
SViewUITests
ScreenCapture

Build Configurations:
Debug
Release

If no build configuration is specified and -scheme is not passed then "Release" is used.

Schemes:
ScreenCapture
SViewIOS

3.3.2. 编译项目
执行:
xcodebuild -scheme SViewIOS -workspace SViewIOS.xcworkspace clean && xcodebuild -scheme SViewIOS -workspace SViewIOS.xcworkspace -configuration Debug | xcpretty -r json-compilation-database -o compile_commands.json

以上实际执行了 3 步,clean、build、格式化,需要注意的是:

clean 操作需要每次都要执行,否则报错,暂未找到原因和方法;
工作空间项目(cocoapods 管理或手动创建 xcworkspace),必须添加 -workspace xxx.xcworkspace;
xcpretty 主要用来生成格式化的 json 文件;

3.3.3. 生成 HTML
执行:
oclint-json-compilation-database -e Pods -e SViewIOS/Library/ -e SViewIOS/SDK/ -e iOSSView2D -e iOSSViewBase -- -report-type html -rc LONG_LINE=200 -max-priority-1=100000 -max-priority-2=100000 -max-priority-3=100000 >> SViewOCLintReport.html

参数说明:

-e 排除项
LONE_LINE:每行代码最大字符数
-max-priority-x:各级别最大数量,设置大一些,否则可能会由于项目较大出现生成文件失败的情况
报错:

oclint: error: one compiler command contains multiple jobs

解决方法:

进入 Target-BuildSetting,搜索 compiler_index,将 Enable Index-While-Building Functionality 设置为 NO;
打开 podfile 文件,在target 'xxx' do 之前添加:

post_install do |installer|
installer.pods_project.targets.each do |target|
target.build_configurations.each do |config|
config.build_settings['COMPILER_INDEX_STORE_ENABLE'] = "NO"
end
end
end

报表生成时间较长,生成后打开对应 html 文件查看结果,根据 location 对应解决问题:

自动识别脚本

#!/bin/bash

COLOR_ERR="\033[1;31m"    #出错提示
COLOR_SUCC="\033[0;32m"  #成功提示
COLOR_QS="\033[1;37m"  #问题颜色
COLOR_AW="\033[0;37m"  #答案提示
COLOR_END="\033[1;34m"     #颜色结束符

# 寻找项目的 ProjectName
function searchProjectName () {
    find . -maxdepth 1 -name "*.xcodeproj"
}

function oclintForProject () {
    # 预先检测所需的安装包是否存在
    if which xcodebuild 2>/dev/null; then
        echo 'xcodebuild exist'
    else
        echo '🤔️  xcodebuild 都没有安装,玩鸡毛啊? 🤔️'
    fi

    if which oclint 2>/dev/null; then
        echo 'oclint exist'
    else
        echo '😠 完蛋了你,玩 oclint 却不安装吗,要闹哪样 😠'
        echo '😠 乖乖按照博文:https://github.com/FantasticLBP/knowledge-kit/blob/master/第一部分%20iOS/1.63.md 安装所需环境 😠'
    fi
    if which xcpretty 2>/dev/null; then
        echo 'xcpretty exist'
    else
        gem install xcpretty
    fi


    # 指定编码
    export LANG="zh_CN.UTF-8"
    export LC_COLLATE="zh_CN.UTF-8"
    export LC_CTYPE="zh_CN.UTF-8"
    export LC_MESSAGES="zh_CN.UTF-8"
    export LC_MONETARY="zh_CN.UTF-8"
    export LC_NUMERIC="zh_CN.UTF-8"
    export LC_TIME="zh_CN.UTF-8"
    export xcpretty=/usr/local/bin/xcpretty # xcpretty 的安装位置可以在终端用 which xcpretty找到

    searchFunctionName=`searchProjectName`
    path=${searchFunctionName}
    # 字符串替换函数。//表示全局替换 /表示匹配到的第一个结果替换。 
    path=${path//.\//}  # ./BridgeLabiPhone.xcodeproj -> BridgeLabiPhone.xcodeproj
    path=${path//.xcodeproj/} # BridgeLabiPhone.xcodeproj -> BridgeLabiPhone
    
    myworkspace=$path".xcworkspace" # workspace名字
    myscheme=$path  # scheme名字

    # 清除上次编译数据
    if [ -d ./derivedData ]; then
        echo -e $COLOR_SUCC'-----清除上次编译数据derivedData-----'$COLOR_SUCC
        rm -rf ./derivedData
    fi

    # xcodebuild clean
    xcodebuild -scheme $myscheme -workspace $myworkspace clean


    # # 生成编译数据
    xcodebuild -scheme $myscheme -workspace $myworkspace -configuration Debug | xcpretty -r json-compilation-database -o compile_commands.json

    if [ -f ./compile_commands.json ]; then
        echo -e $COLOR_SUCC'编译数据生成完毕😄😄😄'$COLOR_SUCC
    else
        echo -e $COLOR_ERR'编译数据生成失败😭😭😭'$COLOR_ERR
        return -1
    fi

    # 生成报表  -e  忽略目录  pod的话就要忽略Pods 
    oclint-json-compilation-database -e Pods -- -report-type html -o oclintReport.html \
    -rc LONG_LINE=200 \
    -disable-rule ShortVariableName \
    -disable-rule ObjCAssignIvarOutsideAccessors \
    -disable-rule AssignIvarOutsideAccessors \
    -max-priority-1=100000 \
    -max-priority-2=100000 \
    -max-priority-3=100000

    if [ -f ./oclintReport.html ]; then
        rm compile_commands.json
        echo -e $COLOR_SUCC'😄分析完毕😄'$COLOR_SUCC
    else 
        echo -e $COLOR_ERR'😢分析失败😢'$COLOR_ERR
        return -1
    fi
    
    echo -e $COLOR_AW'将为您自动打开 lint 的分析结果...'$COLOR_AW
    # 用 safari 浏览器打开 oclint 的结果
    open -a "/Applications/Safari.app" oclintReport.html
}

oclintForProject
posted @ 2023-06-19 22:52  CoderWGB  阅读(479)  评论(0)    收藏  举报