一、安装工具
1、Java环境与MySQL安装
1.1 进入jdk1.8安装界面,下载macos版本
1.2 进入MySQL 下载界面,下载之后安装,安装完成后,进入系统偏好设置,可看到MySql选项,代表已安装成功
2、SonarQube安装
下载地址
下载完成解压之后直接把文件夹放到 /usr/local/ 路径下
3、其它必备插件的安装
安装OCLint
OCLint是Sonar扫描代码的主要工具,所以必须安装。若电脑中已安装Homebrew,可打开终端使用下面的命令安装
brew tap oclint/formulae
brew install oclint
安装xctool
xctool是用于编译构建和测试iOS、Mac项目的工具,打开终端使用下面的命令安装
brew install xctool
安装gcovr
gcovr是一个将单元测试中的代码覆盖率以多种方式(包括列表方式、XML文件方式、HTML网页方式等)展示出来的工具,打开终端使用下面的命令安装
brew install gcovr
xcpretty安装
用于对xcodebuild的输出进行格式化。并包含输出report功能。
github 链接
如果按照如下方法进行安装,一般会报错,
$ gem install xcpretty
You don’t have write permissions for the /Library/Ruby/Gems/2.0.0 directory.
因为这时你使用的是 Apple 家自带的 ruby,权限不够,使用以下命令即可安装完成,
$ sudo gem install xcpretty -n/usr/local/bin
这样就成功了!
安装Sonar-Scanner
Sonar-Scanner是Sonar中真正用于实现代码扫描的工具,进入 [Sonar-Scanner下载页面](https://docs.sonarqube.org/display/SCAN/Analyzing+with+SonarQube+Scanner),如下图所示
下载完成同样需要解压到/usr/local/文件夹下
二、环境变量与数据库的配置
配置环境变量
打开终端,创建.bash_profile配置文件(已有文件可跳过此步骤)
touch ~/.bash_profile
编辑.bash_profile配置文件
vim ~/.bash_profile
下列代码为我的配置,可直接复制到.bash_profile中使用,复制时注意修改安装路径与工具版本号为自己电脑上的情况
export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk1.8.0_181.jdk/Contents/Home
export PATH=$JAVA_HOME/bin:$PATH:.
export CLASSPATH=$JAVA_HOME/lib/tools.jar:$JAVA_HOME/lib/dt.jar:.
export OCLINT_HOME=/usr/local/oclint-0.13
export PATH=$OCLINT_HOME/bin:$PATH
编辑完成后保存,并执行下面的命令
source ~/.bash_profile
MySql数据库配置
- 创建sonar数据库和用户
打开终端,输入 mysql -u root -p ,再输入数据库密码,进入MySql,输入下面sql语句创建sonar所需的数据库。不知道数据库初始密码的可参考这篇文章
CREATE DATABASE sonar CHARACTER SET utf8 COLLATE utf8_general_ci;
CREATE USER 'sonar' IDENTIFIED BY 'sonar';
GRANT ALL ON sonar.* TO 'sonar'@'%' IDENTIFIED BY 'sonar';
GRANT ALL ON sonar.* TO 'sonar'@'localhost' IDENTIFIED BY 'sonar';
FLUSH PRIVILEGES;
三、配置SonarQube
配置SonarQube须在Java环境与MySql数据库都已创建配置好的情况下进行
配置sonar.properties
打开下面路径的文件(sonar版本不同,路径也会不同)
/usr/local/sonarqube-6.7.5/conf/sonar.properties
修改参数
sonar.jdbc.username=你的数据库账号(我的是root)
sonar.jdbc.password=你的数据库密码 (123)
sonar.jdbc.url=jdbc:mysql://localhost:3306/sonar?useUnicode=true&characterEncoding=utf8&rewriteBatchedStatements=true&useConfigs=maxPerformance&useSSL=false
sonar.jdbc.maxActive=60
sonar.jdbc.maxIdle=5
sonar.jdbc.minIdle=2
sonar.jdbc.maxWait=5000
sonar.jdbc.minEvictableIdleTimeMillis=600000
sonar.jdbc.timeBetweenEvictionRunsMillis=30000
修改完成保存后,在终端中启动sonar
sudo /usr/local//sonarqube-6.7.5/bin/macosx-universal-64/sonar.sh start
完成启动后,打开浏览器访问http://localhost:9000
若能看到下图页面则证明配置成功
安装中文插件
SonarQube中的应用市场中是有免费的中文插件的,在配置成功后可以去下载,下载方式如下图所示,图中是已经完成插件安装的情况安装sonar-objective-c-plugin
由于SonarQube官方插件中支持OC语言的插件非常昂贵,所以我这里使用的是来自GitHub上的一个开源插件,将jar包复制到下面的路径中,重启sonar即安装成功
/usr/local/sonarqube-6.7.5/extensions/plugins
四、本地项目中的配置
将文件 run-sonar.sh 与 sonar-project.properties 拷贝到待分析的项目目录下,如下图所示
配置sonar-project.properties文件
sonar.projectKey=你的项目名
sonar.projectName=你的项目名
sonar.projectVersion=显示在sonar中的项目版本号
sonar.sources=代码存放的文件夹
sonar.objectivec.project=项目名.xcodeproj
sonar.objectivec.workspace=项目名.xcworkspace
sonar.objectivec.appScheme=项目名
到这里本地项目中的配置就完成了。
五、开始使用
在终端中使用cd命令进入项目所在目录,再执行run-sonar.sh
cd /Users/chuqingqin/Desktop/项目文件夹
./run-sonar.sh
oc插件安装,下载地址自找
分析完成后,打开浏览器访问http://localhost:9000,可看到项目分析报告
六、踩过的坑
1、不要使用Mysql8.0版本,因为其中的配置发生改变,与SonarQube会有冲突,导致无法启动SonarQube。
2、如果要更新sonar,请同时看看sonar-objective-c-plugin是否需要更新,如果该插件作者未更新,则最好不要更新sonar,因为可能导致OC插件不兼容。 插件下载地址
https://github.com/culeo/sonar-objective-c
作者的开源代码中未提供jar包,需要下载下来后自行安装maven环境运行 build-and-deploy.sh 文件,生成jar包。
附件(run-sonar.sh)
#!/bin/bash
## INSTALLATION: script to copy in your Xcode project in the same directory as the .xcodeproj file
## USAGE: ./run-sonar.sh
## DEBUG: ./run-sonar.sh -v
## WARNING: edit your project parameters in sonar-project.properties rather than modifying this script
#
trap "echo 'Script interrupted by Ctrl+C'; stopProgress; exit 1" SIGHUP SIGINT SIGTERM
function testIsInstalled() {
hash $1 2>/dev/null
if [ $? -eq 1 ]; then
echo >&2 "ERROR - $1 is not installed or not in your PATH"; exit 1;
fi
}
function readParameter() {
variable=$1
shift
parameter=$1
shift
eval $variable="\"$(sed '/^\#/d' sonar-project.properties | grep $parameter | tail -n 1 | cut -d '=' -f2- | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')\""
}
# Run a set of commands with logging and error handling
function runCommand() {
# 1st arg: redirect stdout
# 2nd arg: command to run
# 3rd..nth arg: args
redirect=$1
shift
command=$1
shift
if [ "$nflag" = "on" ]; then
# don't execute command, just echo it
echo
if [ "$redirect" = "/dev/stdout" ]; then
if [ "$vflag" = "on" ]; then
echo "+" $command "$@"
else
echo "+" $command "$@" "> /dev/null"
fi
elif [ "$redirect" != "no" ]; then
echo "+" $command "$@" "> $redirect"
else
echo "+" $command "$@"
fi
elif [ "$vflag" = "on" ]; then
echo
if [ "$redirect" = "/dev/stdout" ]; then
set -x #echo on
$command "$@"
returnValue=$?
set +x #echo off
elif [ "$redirect" != "no" ]; then
set -x #echo on
$command "$@" > $redirect
returnValue=$?
set +x #echo off
else
set -x #echo on
$command "$@"
returnValue=$?
set +x #echo off
fi
if [[ $returnValue != 0 && $returnValue != 5 ]] ; then
stopProgress
echo "ERROR - Command '$command $@' failed with error code: $returnValue"
exit $returnValue
fi
else
echo "--------------------------------"
echo $command
echo "$@"
if [ "$redirect" = "/dev/stdout" ]; then
$command "$@" > /dev/null
elif [ "$redirect" != "no" ]; then
$command "$@" > $redirect
else
$command "$@"
fi
returnValue=$?
if [[ $returnValue != 0 && $returnValue != 5 ]] ; then
stopProgress
echo "ERROR - Command '$command $@' failed with error code: $returnValue"
exit $?
fi
echo
fi
}
## COMMAND LINE OPTIONS
vflag=""
nflag=""
oclint="on"
while [ $# -gt 0 ]
do
case "$1" in
-v) vflag=on;;
-n) nflag=on;;
-nooclint) oclint="";;
--) shift; break;;
-*)
echo >&2 "Usage: $0 [-v]"
exit 1;;
*) break;; # terminate while loop
esac
shift
done
# Usage OK
echo "Running run-sonar.sh..."
# 检查依赖是否已经安装 xcpretty and oclint
testIsInstalled xcpretty
testIsInstalled oclint
# 检查有没有 sonar-project.properties 文件
if [ ! -f sonar-project.properties ]; then
echo >&2 "ERROR - No sonar-project.properties in current directory"; exit 1;
fi
# 从 sonar-project.properties 读出参数
# .xcworkspace/.xcodeproj filename
workspaceFile=''; readParameter workspaceFile 'sonar.objectivec.workspace'
projectFile=''; readParameter projectFile 'sonar.objectivec.project'
# 源文件
srcDirs=''; readParameter srcDirs 'sonar.sources'
# Scheme
appScheme=''; readParameter appScheme 'sonar.objectivec.appScheme'
# test
testScheme=''; readParameter testScheme 'sonar.objectivec.testScheme'
if [ "$vflag" = "on" ]; then
echo "Xcode workspace file is: $workspaceFile"
echo "Xcode project file is: $projectFile"
echo "Xcode application scheme is: $appScheme"
echo "Xcode test scheme is: $testScheme"
fi
# 检查必须参数
if [ -z "$projectFile" -o "$projectFile" = " " ]; then
if [ ! -z "$workspaceFile" -a "$workspaceFile" != " " ]; then
echo >&2 "ERROR - sonar.objectivec.project parameter is missing in sonar-project.properties. You must specify which projects (comma-separated list) are application code within the workspace $workspaceFile."
else
echo >&2 "ERROR - sonar.objectivec.project parameter is missing in sonar-project.properties (name of your .xcodeproj)"
fi
exit 1
fi
if [ -z "$srcDirs" -o "$srcDirs" = " " ]; then
echo >&2 "ERROR - sonar.sources parameter is missing in sonar-project.properties. You must specify which directories contain your .h/.m source files (comma-separated list)."
exit 1
fi
if [ -z "$appScheme" -o "$appScheme" = " " ]; then
echo >&2 "ERROR - sonar.objectivec.appScheme parameter is missing in sonar-project.properties. You must specify which scheme is used to build your application."
exit 1
fi
## SCRIPT
# Create sonar-reports/ for reports output
if [[ ! (-d "sonar-reports") && ("$nflag" != "on") ]]; then
if [ "$vflag" = "on" ]; then
echo 'Creating directory sonar-reports/'
fi
mkdir sonar-reports
if [[ $? != 0 ]] ; then
stopProgress
exit $?
fi
fi
# Extracting project information needed later
echo 'Extracting Xcode project information'
xcodebuild clean
export LC_ALL="en_US.UTF-8"
if [[ "$workspaceFile" != "" ]] ; then
echo "xcodebuild clean"
xcodebuild clean -workspace "${workspaceFile}" -scheme "${appScheme}" -sdk iphonesimulator -configuration Release
echo "xcodebuild analyze"
xcodebuild -workspace "${workspaceFile}" -scheme "${appScheme}" -sdk iphonesimulator -destination 'platform=iOS Simulator,name=iPhone 6' ONLY_ACTIVE_ARCH=NO -configuration build | tee xcodebuild.log | xcpretty -r json-compilation-database --output compile_commands.json
else
echo "xcodebuild clean"
xcodebuild clean -project "${projectFile}" -scheme "${appScheme}" -configuration Release
echo "xcodebuild analyze"
xcodebuild -project "${projectFile}" -scheme "${appScheme}" -sdk iphonesimulator -destination 'platform=iOS Simulator,name=iPhone 6' ONLY_ACTIVE_ARCH=NO -configuration build | tee xcodebuild.log | xcpretty -r json-compilation-database --output compile_commands.json
fi
if [ "$oclint" = "on" ]; then
# OCLint
echo -n 'Running OCLint...'
# Build the --include flags
currentDirectory=${PWD##*/}
includedCommandLineFlags=""
echo "$srcDirs" | sed -n 1'p' | tr ',' '\n' > tmpFileRunSonarSh
while read word; do
includedCommandLineFlags+=" --include .*/${currentDirectory}/${word}"
done < tmpFileRunSonarSh
rm -rf tmpFileRunSonarSh
if [ "$vflag" = "on" ]; then
echo
echo -n "Path included in oclint analysis is:$includedCommandLineFlags"
fi
# Run OCLint with the right set of compiler options
maxPriority=10000
oclint-json-compilation-database -- -max-priority-1 $maxPriority -max-priority-2 $maxPriority -max-priority-3 $maxPriority -rc LONG_LINE=150 -report-type pmd -o sonar-reports/oclint.xml
else
echo 'Skipping OCLint (test purposes only!)'
fi
# SonarQube
echo 'Running SonarQube using SonarQube Scanner'
sonar-scanner
rm -rf sonar-reports
rm -rf build
rm -rf compile_commands.json
rm -rf xcodebuild.log
rm -rf .scannerwork
exit 0