所需环境配置和软件安装
下面是在mac机器上安装的工具
- homebrew(mac命令管理软件工具)
- Java JDK
- xcode
- sonarqube(代码扫描平台)
- sonar-scanner(收集report.json、swiftlint.txt、lizard-report.xml上报到SonarQube)
- scanner-swift(扫描OC\swift的插件)
- xcpretty(处理xcodebuild.log,输出compile_commands.json)
- swiftlint(处理swift文件,输出swiftlint.txt)
- Tailor (Swift编程语言编写的源代码的静态分析和lint工具)
- lizard(处理ObjC文件,输出lizard-report.xml)
- oclint(一些代码规则问题)
- salther(生成测试覆盖率报告)
1.安装SonarQube
使用的是官方长期支持和维护的版本SonarQube 8.9.7,下载后,放到你想要的目录,我这里放到了/usr/local (注意点:因为sonarqube-object-c插件需要付费,需要使用免费的scanner-swift,而scanner-swift不支持新版本。)
- 修改sonar.properties文件配置
- 进入
sonarqube-8.9.7/conf目录下编辑sonar.properties,配置改为如下:
#----- 登录账号密码
sonar.login=admin
sonar.password=12345
#----- 数据库相关
sonar.jdbc.username=sonarqube
sonar.jdbc.password=sonarqube
sonar.jdbc.url=jdbc:postgresql://localhost/sonar
2.安装Java 11
下载Java 11, 前往官网下载Java SE Development Kit 11.0.16,下载java11是因为使用最新的版本或者java1.8都无法打开 http://localhost:9000
3.安装Sonar-scanner
- 使用
Homebrew安装
$ brew install sonar-scanner
- 查看是否安装成功还有版本
$ sonar-scanner --version
INFO: Scanner configuration file: /usr/local/Cellar/sonar-scanner/4.7.0.2747/libexec/conf/sonar-scanner.properties
INFO: Project root configuration file: NONE
INFO: SonarScanner 4.7.0.2747
INFO: Java 11.0.16.1 Homebrew (64-bit)
INFO: Mac OS X 11.5.2 x86_64
- 注意:如果homebrew因为多次安装报错建议使用如下命令进行重装
$ /bin/zsh -c "$(curl -fsSL https://gitee.com/cunkai/HomebrewCN/raw/master/Homebrew.sh)"
- Sonar-Scanner配置参数
在SonarScanner的安装目录中找到
/conf/sonar-scanner.properties,通过编辑更新全局设置:
#----- Default SonarQube server
#sonar.host.url=http://localhost:9000
#----- Default source code encoding
#sonar.sourceEncoding=UTF-8
#----- 登录账号密码
sonar.login=admin
sonar.password=xxxx
#----- 数据库
sonar.jdbc.username=sonarqube
sonar.jdbc.password=sonarqube
sonar.jdbc.url=jdbc:postgresql://localhost/sonar
4.安装PostgreSQL数据库
- 使用
Homebrew安装
$ brew install postgresql
- 安装完成后初始化数据库
$ initdb /usr/local/var/postgres
- 启动服务
$ pg_ctl -D /usr/local/var/postgres -l /usr/local/var/postgres/server.log start
- 创建账户
$ createuser username -P
username 是用户名,回车输入 2 次用户密码后即用户创建完成。更多用户创建信息可以 createuser --help 查看
- 创建数据库
$ createdb sonarqube -O username -E UTF8 -e
上面创建了一个名为 sonarqube 的数据库,并指定 username 为改数据库的拥有者
5.安装xcpretty
使用sudo gem install -n /usr/local/bin xcpretty ,这样会有安装风险。
使用sonar-swift官方推荐安装
git clone https://github.com/Backelite/xcpretty.git
cd xcpretty
git checkout fix/duration_of_failed_tests_workaround
gem build xcpretty.gemspec
sudo gem install --both xcpretty-0.3.0.gem
6.安装SwiftLint
安装:brew install swiftlint
7.安装Tailor
安装:brew install tailor
8.安装slather
直接执行命令gem install slather 会报错,需要升级brew到最新版本
ERROR: Error installing slather:
ERROR: Failed to build gem native extension.
...省略一大堆信息...
extconf failed, exit code 1
Gem files will remain installed in /Library/Ruby/Gems/2.6.0/gems/racc-1.5.2 for inspection.
Results logged to /Library/Ruby/Gems/2.6.0/extensions/universal-darwin-19/2.6.0/racc-1.5.2/gem_make.out
更新ruby版本:
brew install ruby
执行完成后按照提示添加环境变量,并立即生效;
export PATH="/usr/local/opt/ruby/bin:$PATH"
export LDFLAGS="-L/usr/local/opt/ruby/lib"
export CPPFLAGS="-I/usr/local/opt/ruby/include"
继续执行gem install slather 安装完成,但是依然会找不到命令,建议执行以下命令重新安装即可;
sudo gem install -n /usr/local/bin slather
9.安装lizard
直接官方命令sudo pip install lizard 会报错,改用sudo pip3 install lizard
注意!:安装过程中如果出现依赖包下载失败情况,可单独先安装好依赖包,然后再次执行安装
10.安装OCLint
- 使用
homebrew安装,但是有可能OCLint的版本不匹配你的Xcode版本导致检查出错
brew tap oclint/formulae
brew install oclint
- (建议直接下载)如果报错的话,前往 OCLint Releases 下载支持你当前
Xcode版本的OCLint版本,放到任意目录下。可以和SonarQube同级。
查看安装结果
% oclint --version
OCLint (https://oclint.org):
OCLint version 21.10.
Built Oct 25 2021 (21:41:25).
- 具体可以查看的OCLint使用手册
11.SonarQube-swift插件包安装
- 下载sonar-swift-0.4.6 , 从已下载的sonar-swift-0.4.6中,拷贝
backelite-sonar-swift-plugin-0.4.6.jar文件到sonarqube-8.9.7/extensions/plugins里。
建议下载完整master完整压缩包需要用到:sonar-project.properties文件和sonar-swift-plugin/src/main/shell/路径下的run-sonar-swift.sh文件
12.环境变量配置
- 统一配置下环境变量:(java、sonarqube、sonar-scanner等的环境变量配置)
打开配置文件
$ vim ~/.bash_profile
- 根据自身安装路径进行如下配置:
export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk-11.0.16.1.jdk/Contents/Home
export PATH=$JAVA_HOME/bin:$PATH:.
export CLASSPATH=$JAVA_HOME/lib/tools.jar:$JAVA_HOME/lib/dt.jar:.
OCLINT_HOME=/Users/xuejunting/bin/OCLint/oclint-21.10
export PATH=$OCLINT_HOME/bin:$PATH
export SONAR_RUNNER_HOME=/usr/local/sonarqube-8.9.7.52159
export PATH=$SONAR_RUNNER_HOME/bin:$PATH
export SONAR_SCANNER_HOME=/usr/local/sonar-scanner
export PATH=$SONAR_SCANNER_HOME/bin:$PATH
export PATH="/usr/local/opt/ruby/bin:$PATH"
export LDFLAGS="-L/usr/local/opt/ruby/lib"
export CPPFLAGS="-I/usr/local/opt/ruby/include"
export HOMEBREW_BOTTLE_DOMAIN=https://mirrors.ustc.edu.cn/homebrew-bottles #ckbrew
eval $(/usr/local/Homebrew/bin/brew shellenv) #ckbrew
- 退出并保存后运行
$ source ~/.bash_profile
13.扫描
- 启动sonarqube
终端cd到/usr/local/sonarqube-8.9.7.52159/bin/macosx-universal-64目录下运行
$ sh sonar.sh start
- 启动数据库
$ pg_ctl -D /usr/local/var/postgres -l /usr/local/var/postgres/server.log start
- 在终端通过
SonarQube推荐的指令集进行扫描
sonar-scanner \
-Dsonar.projectKey=TestPod \
-Dsonar.sources=. \
-Dsonar.host.url=http://localhost:9000 \
-Dsonar.login=生成的口令,你创建扫描工程的时候会自动生成此条命令
打开http://localhost:9000找到项目查看结果
这时你会发现使用sonar-scanner分析项目后刷新SonarQube后台,得到了一份完美的报告,一个问题都没有,这时需要我们结合前面下载的诸多工具如:OCLint进行分析;
- 需要在SnoarQube的设置
在项目设置完成如下更改:
在SonarQube后台,我们进入项目配置-设置,可以在左侧看到前面添加的插件
Swift (Backelite),点击后可以右侧看到一些路径配置,OCLint的报告的相对路径(Path to OCLint pmd formatted report)为sonar-reports/*oclint.xml,我们在可以将OCLint分析报告放置在此路径中,SonarQube即可显示出分析结果。
常见报错:#oclint: error: compilation contains multiple jobs:
在需要扫描的项目中需要做如下更改:
第一步:podfile文件中添加
post_install do |pi|
pi.pods_project.targets.each do |t|
t.build_configurations.each do |config|
config.build_settings['COMPILER_INDEX_STORE_ENABLE'] = "NO"
end
end
end
第二步:将project和target的COMPILER_INDEX_STORE_ENABLE,都设置为NO
-
新建测试项目和配置
sonar-project.properties文件 -
新建一个
sonar-project.properties在代码扫描的根目录(或者直接把下载好的添加到目录下),与.xcodeproj同级,然后编辑sonar-project.properties文件,按实际名称进行填写;
#
# Swift SonarQube Plugin - Enables analysis of Swift and Objective-C projects into SonarQube.
# Copyright © 2015 Backelite (${email})
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
sonar.projectKey=FatePlusIOS
sonar.projectName=FatePlusIOS
# Number version (can be found automatically in plist, just comment this line)
#sonar.projectVersion=1.0
# Comment if you have a project with mixed ObjC / Swift
sonar.language=ObjC
# Project description
sonar.projectDescription=prjDescription
# Path to source directories
sonar.sources=FatePlusIOS
# Path to test directories (comment if no test)
sonar.tests=FatePlusIOSTests
# Destination Simulator to run surefire
# As string expected in destination argument of xcodebuild command
# Example = sonar.swift.simulator=platform=iOS Simulator,name=iPhone 6,OS=9.2
#sonar.swift.simulator=platform=iOS Simulator,name=iPhone X,OS=latest
sonar.swift.simulator=platform=iOS Simulator,name=iPhone 13,OS=15.0
# Xcode project configuration (.xcodeproj)
# and use the later to specify which project(s) to include in the analysis (comma separated list)
# Specify either xcodeproj or xcodeproj + xcworkspace
sonar.swift.project=FatePlusIOS.xcodeproj
sonar.swift.workspace=FatePlusIOS.xcworkspace
# Scheme to build your application
sonar.swift.appScheme=FatePlusIOS
# Specify your appname when different from targeted scheme.
# Or when slather fails with 'No product binary found'
# You can also provide a list of framework names to analyse for coverage.
# This will be something like "myApp" or "myApp,myFramework"
# sonar.coverage.binaryNames=myApp,myFramework
# Configuration to use for your scheme. if you do not specify that the default will be Debug
#sonar.swift.appConfiguration=MyConfiguration
##########################
# Optional configuration #
##########################
# Encoding of the source code
sonar.sourceEncoding=UTF-8
# SCM
# sonar.scm.enabled=true
# sonar.scm.url=scm:git:http://xxx
# JUnit report generated by run-sonar.sh is stored in sonar-reports/TEST-report.xml
# Change it only if you generate the file on your own
# The XML files have to be prefixed by TEST- otherwise they are not processed
# sonar.junit.reportsPath=sonar-reports/
# Lizard report generated by run-sonar.sh is stored in sonar-reports/lizard-report.xml
# Change it only if you generate the file on your own
# sonar.swift.lizard.report=sonar-reports/lizard-report.xml
# Cobertura report generated by run-sonar.sh is stored in sonar-reports/coverage-swift.xml
# Change it only if you generate the file on your own
# sonar.swift.coverage.reportPattern=sonar-reports/coverage-swift*.xml
# OCLint report generated by run-sonar.sh is stored in sonar-reports/oclint.xml
# Change it only if you generate the file on your own
# sonar.swift.swiftlint.report=sonar-reports/*swiftlint.txt
# Change it only if you generate the file on your own
# sonar.swift.tailor.report=sonar-reports/*tailor.txt
# Paths to exclude from coverage report (surefire, 3rd party libraries etc.)
# sonar.swift.excludedPathsFromCoverage=pattern1,pattern2
sonar.swift.excludedPathsFromCoverage=.*Tests.*,.*Specs.*
# Ability to skip tests (such as UI Tests running long time)
# Example = sonar.swift.skipTests=UITests
##########################
# Tailor configuration #
##########################
# Tailor configuration
# -l,--max-line-length=<0-999> maximum Line length (in characters)
# --list-files display Swift source files to be analyzed
# --max-class-length=<0-999> maximum Class length (in lines)
# --max-closure-length=<0-999> maximum Closure length (in lines)
# --max-file-length=<0-999> maximum File length (in lines)
# --max-function-length=<0-999> maximum Function length (in lines)
# --max-name-length=<0-999> maximum Identifier name length (in characters)
# --max-severity=<error|warning (default)> maximum severity
# --max-struct-length=<0-999> maximum Struct length (in lines)
# --min-name-length=<1-999> minimum Identifier name length (in characters)
sonar.swift.tailor.config=--no-color --max-line-length=100 --max-file-length=500 --max-name-length=40 --max-name-length=40 --min-name-length=4
将下载好的run-sonar-swift.sh放到项目根目录下 然后在工程目录中执行以下命令:
sh run-sonar-swift.sh
执行完毕后,再次刷新sonarqube的后台就能看到完整的扫描信息,报错点击可查看具体问题内容了!
参考
IOS 代码扫描从放弃到入门
iOS 用sonar-swift实现SonarQube代码质量扫描
iOS 静态代码分析(SonarQube + Objective-C、Swift)
sonarqube进行iOS静态代码分析
Mac 配置 PostgreSQL 常用操作
sonar-swift