SonarQube Scanner for MSBuild 2.3.1.554 doesn't support multi-targeted projects

1,180 views
Skip to first unread message

rory.p...@gmail.com

unread,
Apr 14, 2017, 5:03:39 AM4/14/17
to SonarQube
I have updated the scanner on my VSTS build agent (on-prem) to use the 2.3.1 scanner for MsBuild. I have then run it against a build for a project using the new csproj format that also does multi-targeting. 

My csproj is:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFrameworks>netstandard1.5;net452</TargetFrameworks>
      <GeneratePackageOnBuild>True</GeneratePackageOnBuild>
        <TreatWarningsAsErrors>True</TreatWarningsAsErrors>
    <IncludeSymbols>true</IncludeSymbols>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Ensure.That" Version="5.0.0" />
    <PackageReference Include="gitversiontask" Version="4.0.0-beta0011">
      <PrivateAssets>all</PrivateAssets>
    </PackageReference>
    <PackageReference Include="nodatime" Version="2.0.0" />
  </ItemGroup>

</Project>

This fails on the Sonar step with the following log:

2017-04-14T06:09:13.7864515Z ##[section]Starting: Complete the SonarQube analysis
2017-04-14T06:09:13.7864515Z ==============================================================================
2017-04-14T06:09:13.7864515Z Task         : SonarQube  Scanner for MSBuild - End Analysis (new)
2017-04-14T06:09:13.7864515Z Description  : Complete the SonarQube analysis of your solution
2017-04-14T06:09:13.7864515Z Version      : 2.0.0
2017-04-14T06:09:13.7864515Z Author       : SonarSource
2017-04-14T06:09:13.7864515Z Help         : Version: 2.0.0. [More Information](http://redirect.sonarsource.com/doc/install-configure-scanner-tfs-ts.html)
2017-04-14T06:09:13.7864515Z ==============================================================================
2017-04-14T06:09:13.7874513Z Preparing task execution handler.
2017-04-14T06:09:14.1100204Z Executing the powershell script: C:\B\_tasks\SonarQubeScannerMsBuildEnd_6d01813a-9589-4b15-8491-8164aeb38055\2.0.0\SonarQubePostTest.ps1
2017-04-14T06:09:14.6192476Z SonarQube Scanner for MSBuild 2.3.1
2017-04-14T06:09:14.7197735Z Default properties file was found at C:\B\_tasks\SonarQubeScannerMsBuildBegin_15b84ca1-b62f-4a2a-a403-89b77a063157\2.0.0\SonarQubeScannerMsBuild\SonarQube.Analysis.xml
2017-04-14T06:09:14.7197735Z Loading analysis properties from C:\B\_tasks\SonarQubeScannerMsBuildBegin_15b84ca1-b62f-4a2a-a403-89b77a063157\2.0.0\SonarQubeScannerMsBuild\SonarQube.Analysis.xml
2017-04-14T06:09:14.7197735Z Post-processing started.
2017-04-14T06:09:14.7197735Z 16:09:14.578  Fetching code coverage report information from TFS...
2017-04-14T06:09:14.7197735Z 16:09:14.581  Attempting to locate a test results (.trx) file...
2017-04-14T06:09:14.7197735Z 16:09:14.59  Looking for TRX files in: C:\B\9\TestResults, C:\B\9\s\TestResults
2017-04-14T06:09:14.7197735Z 16:09:14.59  Located a test results file: C:\B\9\s\TestResults\MORPHEUS$_MORPHEUS 2017-04-14 16_09_01.trx
2017-04-14T06:09:14.8300281Z WARNING: Duplicate project GUID: "83c7f6ca-21bb-4efd-813a-d2ffdeeaac9e". Check that the project is only being built for a single platform/configuration and that that the project guid is unique. The project will not be analyzed by SonarQube. Project file: C:\B\9\s\Watchium.Models.UnitTests\Watchium.Models.UnitTests.csproj
2017-04-14T06:09:14.8305331Z WARNING: Duplicate project GUID: "83c7f6ca-21bb-4efd-813a-d2ffdeeaac9e". Check that the project is only being built for a single platform/configuration and that that the project guid is unique. The project will not be analyzed by SonarQube. Project file: C:\B\9\s\Watchium.Models.UnitTests\Watchium.Models.UnitTests.csproj
2017-04-14T06:09:14.8305331Z WARNING: Duplicate project GUID: "0bbc1305-0c57-49f7-a606-2dfc4b22d76a". Check that the project is only being built for a single platform/configuration and that that the project guid is unique. The project will not be analyzed by SonarQube. Project file: C:\B\9\s\Watchium.Models\Watchium.Models.csproj
2017-04-14T06:09:14.8305331Z WARNING: Duplicate project GUID: "0bbc1305-0c57-49f7-a606-2dfc4b22d76a". Check that the project is only being built for a single platform/configuration and that that the project guid is unique. The project will not be analyzed by SonarQube. Project file: C:\B\9\s\Watchium.Models\Watchium.Models.csproj
2017-04-14T06:09:14.8310285Z ##[error]No analysable projects were found but some duplicate project IDs were found. Possible cause: you are building multiple configurations (e.g. DEBUG|x86 and RELEASE|x64) at the same time, which is not supported by the SonarQube integration. Please build and analyse each configuration individually.
2017-04-14T06:09:14.8310285Z Generation of the sonar-properties file failed. Unable to complete SonarQube analysis.
2017-04-14T06:09:14.8310285Z 16:09:14.715  Creating a summary markdown file...
2017-04-14T06:09:14.8310285Z ##[error]16:09:14.718  Post-processing failed. Exit code: 1
2017-04-14T06:09:14.8371377Z ##[error]System.Exception: Unexpected exit code received from batch file: 1
2017-04-14T06:09:14.8371377Z    at Microsoft.TeamFoundation.DistributedTask.Task.Internal.InvokeBatchScriptCmdlet.ProcessRecord()
2017-04-14T06:09:14.8371377Z    at System.Management.Automation.CommandProcessor.ProcessRecord()
2017-04-14T06:09:15.1535489Z 
2017-04-14T06:09:15.1535489Z 
2017-04-14T06:09:15.1675489Z Waiting on the SonarQube server to finish processing in order to determine the quality gate status.
2017-04-14T06:09:15.1675489Z 
2017-04-14T06:09:15.1675489Z 
2017-04-14T06:09:15.1865496Z ##[error]System.Management.Automation.RuntimeException: Cannot determine if the analysis has finished. Possible cause: your SonarQube server version is lower than 5.3 - for more details see https://go.microsoft.com/fwlink/?LinkId=722407 ---> System.Management.Automation.RuntimeException: Cannot determine if the analysis has finished. Possible cause: your SonarQube server version is lower than 5.3 - for more details see https://go.microsoft.com/fwlink/?LinkId=722407
2017-04-14T06:09:15.1865496Z    --- End of inner exception stack trace ---
2017-04-14T06:09:15.1865496Z    at System.Management.Automation.Runspaces.PipelineBase.Invoke(IEnumerable input)
2017-04-14T06:09:15.1865496Z    at System.Management.Automation.PowerShell.Worker.ConstructPipelineAndDoWork(Runspace rs, Boolean performSyncInvoke)
2017-04-14T06:09:15.1875497Z    at System.Management.Automation.PowerShell.Worker.CreateRunspaceIfNeededAndDoWork(Runspace rsToUse, Boolean isSync)
2017-04-14T06:09:15.1875497Z    at System.Management.Automation.PowerShell.CoreInvokeHelper[TInput,TOutput](PSDataCollection`1 input, PSDataCollection`1 output, PSInvocationSettings settings)
2017-04-14T06:09:15.1875497Z    at System.Management.Automation.PowerShell.CoreInvoke[TInput,TOutput](PSDataCollection`1 input, PSDataCollection`1 output, PSInvocationSettings settings)
2017-04-14T06:09:15.1875497Z    at Microsoft.TeamFoundation.DistributedTask.Handlers.LegacyVSTSPowerShellHost.VSTSPowerShellHost.Main(String[] args)
2017-04-14T06:09:15.2065497Z ##[error]LegacyVSTSPowerShellHost.exe completed with return code: -1.
2017-04-14T06:09:15.2065497Z ##[section]Finishing: Complete the SonarQube analysis


This seems to fail because it thinks that multiple builds have occurred. This is technically true because multi-targeted builds in the new csproj format use a wrapper build internally around multiple compilations of the project for each target framework. So a build against a Release|Any CPU configuration (for the multi-target config above) would compile something like Release|Any CPU|netstandard1.5 and Release|Any CPU|net452. This must be done as part of a single execution of msbuild (wrapped by Sonar build steps) because the compilation of the wrapper project then does the package of the binary output into a nupkg file.

To test this out, you can create a csproj and copy in the above example with any class files you like in the directory.

Julien HENRY

unread,
Apr 14, 2017, 8:23:21 AM4/14/17
to SonarQube, rory.p...@gmail.com
Hi,

(Note that some courtesy is appreciated on this group)

Thanks for reporting the issue. We were not aware of this use case. Ticket created:

In the meantime and as a workaround, do you know if there is a way (using a command line switch) to select only one target?

Regards,

Julien

duncanp

unread,
Apr 19, 2017, 5:31:32 AM4/19/17
to SonarQube, rory.p...@gmail.com
Hi Julien,

It's possible to build only one framework by setting the TargetFrameworks property when invoking MSBuild e.g. /p:TargetFrameworks=net45

An alternative workaround is to build all versions but only analyse one.
This can be done by conditionally setting the SonarQubeExclude flag in the project file e.g.

  <PropertyGroup Condition="'$(TargetFramework)' != 'net45' ">
    <!-- Exclude the analysis of this framework type: workaround for https://jira.sonarsource.com/browse/SONARMSBRU-317 -->
    <SonarQubeExclude>true</SonarQubeExclude>
  </PropertyGroup>

Note that the first option sets TargetFrameworks and the second option sets TargetFramework (TargetFrameworks specifies all of the frameworks that should be built, and TargetFramework is set on each pass to indicate the framework that is currently being built).


The ability to target multiple frameworks in this way presents some interesting questions about what the preferred behaviour should be. Most of the code will be common across the various frameworks but it's likely there will be some framework-specific code.
Users will want to see issues for all platforms, but won't want to have issues in the common code reported multiple times.
One option would be to analyse each framework as a separate SonarQube project, but this would report the common issues in each SonarQube project.
A preferable option would be to combine the error reports for each framework and remove the duplicates, and upload the results to a single SonarQube project.

Regards,
Duncan

Julien HENRY

unread,
Apr 19, 2017, 8:07:32 AM4/19/17
to SonarQube, rory.p...@gmail.com
Hi Duncan,

A big thank you for all those details.

Regarding the open question about what to do with framework specific files, let say this is an accepted limitation. Users will have to choose the "main" framework that will be analyzed.

Regards,

Julien

rory.p...@gmail.com

unread,
Apr 21, 2017, 2:27:01 AM4/21/17
to SonarQube, rory.p...@gmail.com
Hi Julien,

I'm so sorry. I read my post and it is totally blunt. I'm loving SonarQube and I very much appreciate what you guy are producing :)

Cheers,

Rory

rory.p...@gmail.com

unread,
Apr 21, 2017, 2:57:47 AM4/21/17
to SonarQube, rory.p...@gmail.com
I can confirm that this works. I went for the second option so that the compilation process could still compile both targets and then produce the single nuget package for all the assets. This is an acceptable workaround.

The potential risk in this approach is that it is common to use compile directives so that code is only compiled into some target frameworks. This may mean that some code is not covered by SonarQube (my assumption here).

Cheers,

Rory

janos....@sonarsource.com

unread,
Jun 1, 2017, 4:35:43 AM6/1/17
to SonarQube, rory.p...@gmail.com
Hi,

I've done some tests to reproduce this. We normally build .NET projects with /t:rebuild, which includes a cleaning step that wipes out the analysis result of a previous build. For example if you have target platforms netstandard1.5 and net452, the building for net452 will wipe out the previous results for netstandard1.5. This way there will be no duplicate GUIDs, because only the last one survives.

Can you please confirm:

1. Are you able to reproduce the problem when building with /t:rebuild ?
2. Would it be an acceptable workaround to use /t:rebuild ? (Keeping in mind that /t:clean followed by /t:build is not the same as /t:rebuild)

Please let us know.

Thanks,
Janos
Reply all
Reply to author
Forward
0 new messages