diff --git a/README.md b/README.md index a9b441ac..dd1a4d33 100644 --- a/README.md +++ b/README.md @@ -65,11 +65,34 @@ Binary packages are available in the release section. - a Mac with Xcode - [SonarQube](http://docs.codehaus.org/display/SONAR/Setup+and+Upgrade) and [SonarQube Runner](http://docs.codehaus.org/display/SONAR/Installing+and+Configuring+SonarQube+Runner) installed ([HomeBrew](http://brew.sh) installed and ```brew install sonar-runner```) +- [xcpretty](https://github.com/supermarin/xcpretty) (```gem install xcpretty```) - [xctool](https://github.com/facebook/xctool) ([HomeBrew](http://brew.sh) installed and ```brew install xctool```). If you are using Xcode 6, make sure to update xctool (```brew upgrade xctool```) to a version > 0.2.2. -- [OCLint](http://docs.oclint.org/en/dev/intro/installation.html) installed. Version 0.8.1 recommended ([HomeBrew](http://brew.sh) installed and ```brew install https://gist.githubusercontent.com/TonyAnhTran/e1522b93853c5a456b74/raw/157549c7a77261e906fb88bc5606afd8bd727a73/oclint.rb```). -- [gcovr](http://gcovr.com) installed +- [OCLint](http://docs.oclint.org/en/dev/intro/installation.html) installed. Version 0.10.1 recommended. +- [gcovr](http://gcovr.com) installed for legacy (pre Xcode 7 coverage) +- [slather](https://github.com/venmo/slather) with profdata support (see instructions below) for Xcode 7 and above. - [Faux Pas](http://fauxpasapp.com/) command line tools installed (optional) +###Installation of slather with profdata support + +At the time, slather does not support profdata. A special version of slather needs t be installed. + +To install slather with profdata support, follow those steps : + + git clone https://github.com/mattdelves/slather.git + cd slather + git checkout feature-profdata + gem build slather.gemspec + gem install --both slather-1.8.1.gem + + +###Code coverage data format + +Since Xcode 7, Apple changed its coverage data format to a new format called 'profdata'. +By default this format will be used by the plugin, except if you explicitly force it to legacy mode (for Xcode 6 and below) in your *sonar-project.properties* with this line: + + sonar.objectivec.coverageType=legacy + + ###Installation (once for all your Objective-C projects) - Download the plugin binary into the $SONARQUBE_HOME/extensions/plugins directory - Copy [run-sonar.sh](https://rawgithub.com/Backelite/sonar-objective-c/master/src/main/shell/run-sonar.sh) somewhere in your PATH diff --git a/sample/sonar-project.properties b/sample/sonar-project.properties index 5cdfde10..b72ae5a0 100644 --- a/sample/sonar-project.properties +++ b/sample/sonar-project.properties @@ -15,6 +15,16 @@ sonar.sources=srcDir1,srcDir2 # Path to test directories (comment if no test) sonar.tests=testSrcDir +# Coverage type to expect from project +# can be 'legacy' (pre Xcode 7) or 'profdata' +# If not set : defaults to profdata +#sonar.objectivec.coverageType=profdata + +# Destination Simulator to run tests +# As string expected in destination argument of xcodebuild command +# Example = sonar.swift.simulator=platform=iOS Simulator,name=iPhone 6,OS=9.2 +sonar.objectivec.simulator=platform=iOS Simulator,name=iPhone 6,OS=9.2 + # Xcode project configuration (.xcodeproj or .xcworkspace) # -> If you have a project: configure only sonar.objectivec.project diff --git a/src/main/shell/run-sonar.sh b/src/main/shell/run-sonar.sh index a8d47ce6..e1212d6c 100755 --- a/src/main/shell/run-sonar.sh +++ b/src/main/shell/run-sonar.sh @@ -5,6 +5,11 @@ ## WARNING: edit your project parameters in sonar-project.properties rather than modifying this script # +# Global parameters +XCTOOL_CMD=xctool +SLATHER_CMD=slather +XCPRETTY_CMD=xcpretty + trap "echo 'Script interrupted by Ctrl+C'; stopProgress; exit 1" SIGHUP SIGINT SIGTERM function startProgress() { @@ -155,9 +160,9 @@ fi workspaceFile=''; readParameter workspaceFile 'sonar.objectivec.workspace' projectFile=''; readParameter projectFile 'sonar.objectivec.project' if [[ "$workspaceFile" != "" ]] ; then - xctoolCmdPrefix="xctool -workspace $workspaceFile -sdk iphonesimulator ARCHS=i386 VALID_ARCHS=i386 CURRENT_ARCH=i386 ONLY_ACTIVE_ARCH=NO" + xctoolCmdPrefix="$XCTOOL_CMD -workspace $workspaceFile -sdk iphonesimulator ARCHS=i386 VALID_ARCHS=i386 CURRENT_ARCH=i386 ONLY_ACTIVE_ARCH=NO" else - xctoolCmdPrefix="xctool -project $projectFile -sdk iphonesimulator ARCHS=i386 VALID_ARCHS=i386 CURRENT_ARCH=i386 ONLY_ACTIVE_ARCH=NO" + xctoolCmdPrefix="$XCTOOL_CMD -project $projectFile -sdk iphonesimulator ARCHS=i386 VALID_ARCHS=i386 CURRENT_ARCH=i386 ONLY_ACTIVE_ARCH=NO" fi # Count projects @@ -175,6 +180,11 @@ appScheme=''; readParameter appScheme 'sonar.objectivec.appScheme' testScheme=''; readParameter testScheme 'sonar.objectivec.testScheme' # The file patterns to exclude from coverage report excludedPathsFromCoverage=''; readParameter excludedPathsFromCoverage 'sonar.objectivec.excludedPathsFromCoverage' +# Read coverage type +coverageType=''; readParameter coverageType 'sonar.objectivec.coverageType' +# Read destination simulator +destinationSimulator=''; readParameter destinationSimulator 'sonar.objectivec.simulator' + # Check for mandatory parameters if [ -z "$projectFile" -o "$projectFile" = " " ]; then @@ -194,6 +204,10 @@ 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 +if [ -z "$destinationSimulator" -o "$destinationSimulator" = " " ]; then + echo >&2 "ERROR - sonar.objectivec.simulator parameter is missing in sonar-project.properties. You must specify which simulator to use." + exit 1 +fi if [ "$vflag" = "on" ]; then echo "Xcode workspace file is: $workspaceFile" @@ -233,35 +247,75 @@ if [ "$testScheme" = "" ]; then echo "" > sonar-reports/coverage.xml else - echo -n 'Running tests using xctool' - # Not using runCommand function because xctool may return 1, even if everything is fine (maybe a xctool bug ?) - #runCommand /dev/null $xctoolCmdPrefix -scheme "$testScheme" GCC_PRECOMPILE_PREFIX_HEADER=NO GCC_GENERATE_TEST_COVERAGE_FILES=YES GCC_INSTRUMENT_PROGRAM_FLOW_ARCS=YES -reporter junit:sonar-reports/TEST-report.xml -reporter plain clean test - $xctoolCmdPrefix -scheme "$testScheme" GCC_PRECOMPILE_PREFIX_HEADER=NO GCC_GENERATE_TEST_COVERAGE_FILES=YES GCC_INSTRUMENT_PROGRAM_FLOW_ARCS=YES -reporter junit:sonar-reports/TEST-report.xml -reporter plain clean test + echo -n 'Running tests' + runCommand /dev/stdout xcodebuild clean -workspace $workspaceFile -scheme $appScheme + if [ "$coverageType" = "profdata" -o "$coverageType" = "" ]; then + # profdata + buildCmd=(xcodebuild test -workspace $workspaceFile -scheme $appScheme -sdk iphonesimulator -configuration Debug -enableCodeCoverage YES) + else + # Legacy coverage + buildCmd=(xcodebuild test -workspace $workspaceFile -scheme $appScheme -sdk iphonesimulator -configuration Debug) + fi + + if [[ ! -z "$destinationSimulator" ]]; then + buildCmd+=(-destination "$destinationSimulator" -destination-timeout 60) + fi + runCommand sonar-reports/xcodebuild.log "${buildCmd[@]}" + cat sonar-reports/xcodebuild.log | $XCPRETTY_CMD -t --report junit + mv build/reports/junit.xml sonar-reports/TEST-report.xml echo -n 'Computing coverage report' - # Build the --exclude flags - excludedCommandLineFlags="" - if [ ! -z "$excludedPathsFromCoverage" -a "$excludedPathsFromCoverage" != " " ]; then - echo $excludedPathsFromCoverage | sed -n 1'p' | tr ',' '\n' > tmpFileRunSonarSh2 - while read word; do - excludedCommandLineFlags+=" --exclude $word" - done < tmpFileRunSonarSh2 - rm -rf tmpFileRunSonarSh2 - fi - if [ "$vflag" = "on" ]; then - echo "Command line exclusion flags for gcovr is:$excludedCommandLineFlags" - fi + if [ "$coverageType" = "profdata" -o "$coverageType" = "" ]; then - # Create symlink on the build directory to enable its access from the workspace - coverageFilesPath=$(grep 'command' compile_commands.json | sed 's#^.*-o \\/#\/#;s#",##' | grep "${projectName%%.*}.build" | awk 'NR<2' | sed 's/\\\//\//g' | sed 's/\\\\//g' | xargs -0 dirname) - splitIndex=$(awk -v a="$coverageFilesPath" -v b="/Intermediates" 'BEGIN{print index(a,b)}') - coverageFilesPath=$(echo ${coverageFilesPath:0:$splitIndex}Intermediates) - ln -s $coverageFilesPath sonar-reports/build + # profdata = use slather - # Run gcovr with the right options - runCommand "sonar-reports/coverage.xml" gcovr -r . $excludedCommandLineFlags --xml + echo 'Using profdata' + + # Build the --exclude flags + excludedCommandLineFlags="" + if [ ! -z "$excludedPathsFromCoverage" -a "$excludedPathsFromCoverage" != " " ]; then + echo $excludedPathsFromCoverage | sed -n 1'p' | tr ',' '\n' > tmpFileRunSonarSh2 + while read word; do + excludedCommandLineFlags+=" -i $word" + done < tmpFileRunSonarSh2 + rm -rf tmpFileRunSonarSh2 + fi + if [ "$vflag" = "on" ]; then + echo "Command line exclusion flags for slather is:$excludedCommandLineFlags" + fi + + runCommand /dev/stdout $SLATHER_CMD coverage --input-format profdata $excludedCommandLineFlags --cobertura-xml --output-directory sonar-reports --scheme $appScheme $projectFile + mv sonar-reports/cobertura.xml sonar-reports/coverage.xml + + else + + # Legacy mode = use gcovr + + # Build the --exclude flags + excludedCommandLineFlags="" + if [ ! -z "$excludedPathsFromCoverage" -a "$excludedPathsFromCoverage" != " " ]; then + echo $excludedPathsFromCoverage | sed -n 1'p' | tr ',' '\n' > tmpFileRunSonarSh2 + while read word; do + excludedCommandLineFlags+=" --exclude $word" + done < tmpFileRunSonarSh2 + rm -rf tmpFileRunSonarSh2 + fi + if [ "$vflag" = "on" ]; then + echo "Command line exclusion flags for gcovr is:$excludedCommandLineFlags" + fi + + # Create symlink on the build directory to enable its access from the workspace + coverageFilesPath=$(grep 'command' compile_commands.json | sed 's#^.*-o \\/#\/#;s#",##' | grep "${projectName%%.*}.build" | awk 'NR<2' | sed 's/\\\//\//g' | sed 's/\\\\//g' | xargs -0 dirname) + splitIndex=$(awk -v a="$coverageFilesPath" -v b="/Intermediates" 'BEGIN{print index(a,b)}') + coverageFilesPath=$(echo ${coverageFilesPath:0:$splitIndex}Intermediates) + ln -s $coverageFilesPath sonar-reports/build + + # Run gcovr with the right options + runCommand "sonar-reports/coverage.xml" gcovr -r . $excludedCommandLineFlags --xml + + fi fi