I have a project which is targeting both net472 and netstandard2.0 and this has conditional package references and conditional code.
If I compile this locally completes with no errors and also if I compile the solution via msbuild. However when I compile with msbuild task in azure build pipeline it throw errors like:
##[error]tests\Project.Tests\RiskUi\RiskUiProviderTests.cs(21,17): Error CS0246: The type or namespace name 'RiskUiProvider' could not be found (are you missing a using directive or an assembly reference?) My problem is like this link: https://github.com/dotnet/msbuild/issues/4435 The class RiskUiProvider is under a directive
#if NET472 public class RiskUiProvider {} #endif
it belongs to a project that is multitargeting<TargetFrameworks>net472;netstandard2.0</TargetFrameworks>
and the unit test which is net472 is throwing this error as if he doesn't read under the directive.
Has anyone else had/solved this same issue?
I added the reference of the multitargeting project like this:
<ProjectReference Include="..\Project.Standard\Project.Standard.csproj">
<AdditionalProperties>TargetFramework=net472</AdditionalProperties>
<Name>Project.Standard</Name>
</ProjectReference>
but it is like in azure pipeline he can"t read directives (#if NET472
) and the strange that in local it all works and it is running
yaml file
- task: MSBuild@1
displayName: 'Build solution All.sln'
inputs:
solution: All.sln
msbuildArchitecture: x64
platform: '$(BuildPlatform)'
configuration: '$(BuildConfiguration)'
msbuildArguments: '/p:OutDir=$(Build.ArtifactStagingDirectory) /p:AutoGenerateBindingRedirects=true /p:GeneratePackageOnBuild=True /p:GenerateProjectSpecificOutputFolder=True /p:PackageOutputPath=$(Build.ArtifactStagingDirectory)\NuGet /p:IncludeSymbols=true /p:SymbolPackageFormat=snupkg /target:Build '
clean: true
- task: VSTest@3
displayName: 'Test Assemblies'
inputs:
testAssemblyVer2: |
**\Project.UnitTests\Project.UnitTests.dll
searchFolder: '$(Build.ArtifactStagingDirectory)\TU'
testFiltercriteria: 'TestCategory=UnitTest & TestCategory!=Slow & TestCategory!=PerfNonRegTest'
runInParallel: false
codeCoverageEnabled: false
otherConsoleOptions: '/Platform:$(BuildPlatform) /Framework:.NETFramework,Version=v4.7.2'
platform: '$(BuildPlatform)'
configuration: '$(BuildConfiguration)'
condition: and(succeeded(), eq(variables['DisableUnitTests'], 'false'))
timeoutInMinutes: 30```
The csproj of test
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup>
<ProjectGuid>{48F901E6-F500-477A-B03C-4B6B2E8E362C}</ProjectGuid>
<TargetFramework>net472</TargetFramework>
<SccProjectName></SccProjectName>
<SccLocalPath></SccLocalPath>
<SccAuxPath></SccAuxPath>
<SccProvider></SccProvider>
<AssemblyTitle>LtCore.Tests</AssemblyTitle>
<Product>LtCore.Tests</Product>
<OutputPath>bin\$(Configuration)\</OutputPath>
<ResolveAssemblyWarnOrErrorOnTargetArchitectureMismatch>None</ResolveAssemblyWarnOrErrorOnTargetArchitectureMismatch>
<ErrorOnDuplicatePublishOutputFiles>false</ErrorOnDuplicatePublishOutputFiles>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<GenerateBindingRedirectsOutputType>true</GenerateBindingRedirectsOutputType> </PropertyGroup> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugType>full</DebugType> </PropertyGroup> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType> </PropertyGroup> <ItemGroup>
<PackageReference Include="log4net" Version="2.0.15" />
<PackageReference Include="Microsoft.AspNet.WebApi.Client" Version="5.2.8" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="NFluent" Version="2.8.0" />
<PackageReference Include="NSubstitute" Version="4.4.0" />
<PackageReference Include="NUnit" Version="3.13.3" />
<PackageReference Include="System.Text.Json" Version="8.0.5" /> </ItemGroup> <ItemGroup>
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Net.Http" /> </ItemGroup> <ItemGroup>
<ProjectReference Include="..\..\src\Project.Standard\Project.Standard.csproj">
<AdditionalProperties>TargetFramework=net472</AdditionalProperties>
</ProjectReference> </ItemGroup> <ItemGroup>
<Content Include="log4net.config">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content> </ItemGroup> </Project>
Testing from my side, the pipeline works as expected. Share the projects and yaml file for your reference.
MultiTargetingLibrary.csproj
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net472;netstandard2.0</TargetFrameworks>
</PropertyGroup>
<PropertyGroup Condition="'$(TargetFramework)' == 'net472'">
<DefineConstants>NET472</DefineConstants>
</PropertyGroup>
</Project>
RiskUiProvider.cs
in project MultiTargetingLibrary
#if NET472
public class RiskUiProvider
{
...
}
#endif
MultiTargetingLibrary.Tests.csproj
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net472</TargetFramework>
<IsPackable>false</IsPackable>
<IsTestProject>true</IsTestProject>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="coverlet.collector" Version="6.0.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
<PackageReference Include="xunit" Version="2.5.3" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.5.3" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\MultiTargetingLibrary\MultiTargetingLibrary.csproj" />
</ItemGroup>
<ItemGroup>
<Using Include="Xunit" />
</ItemGroup>
</Project>
pool:
vmImage: 'windows-latest'
variables:
buildConfiguration: 'Release'
solution: '**/*.sln'
buildPlatform: 'Any CPU'
steps:
- task: UseDotNet@2
inputs:
packageType: 'sdk'
version: '5.x' # Adjust based on your .NET SDK version
- task: NuGetToolInstaller@1
- task: NuGetCommand@2
inputs:
restoreSolution: '$(solution)'
- task: MSBuild@1
inputs:
solution: '$(solution)'
platform: '$(buildPlatform)'
configuration: '$(buildConfiguration)'
- task: VSTest@2
inputs:
platform: '$(buildPlatform)'
configuration: '$(buildConfiguration)'
Update:
Root cause:
When you use /p:OutDir=$(Build.ArtifactStagingDirectory)
in msbuildArguments
, the subfolder obj\Release\netstandard2.0
and obj\Release\net472
will not be created in the artifact directory, so that the dll for net472 is override by netstandard2.0.
Solution:
Add the following to test project.
<ProjectName>$(AssemblyName).$(TargetFramework)</ProjectName>
<PackageOutputPath>$(OutDir)</PackageOutputPath>