I have a shared library that needs to be used by both .Net 5 and .Net Framework 4.8 projects. Due to other complexities in the build process, it is impossible to simply have multiple TargetFrameworks
defined in the shared library, so I want to use an MSBuild
property to dynamically set if the shared library should target .Net 5 or .Net Framework 4.8. This approach works when I pass the flag property via MSBuild (/p:Net48=True
) but does not when I define the MSBuild property directly in csproj file.
Below is a simple example of what I am trying to do:
Project A:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\C\C.csproj" />
</ItemGroup>
</Project>
Project B:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net48</TargetFramework>
</PropertyGroup>
<PropertyGroup>
<Net48>True</Net48>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\C\C.csproj" />
</ItemGroup>
</Project>
Project C (Shared Library):
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework Condition="'$(Net48)' == ''">net5.0</TargetFramework>
<TargetFramework Condition="'$(Net48)' != ''">net48</TargetFramework>
</PropertyGroup>
</Project>
Running dotnet build B.csproj /p:Net48=True
builds the project while dotnet build B.csproj
fails. Shouldn't the property definition <Net48>True</Net48>
have the same impact as setting the flag?
CodePudding user response:
Shouldn't the property definition True have the same impact as setting the flag?
No - properties set in Project A do not propagate to projects referenced by Project A, so when you execute dotnet build B.csproj
the property Net48
is undefined in Project C.
However, properties set on the command line apply globally to all projects (and take precedence over property values set statically in a project file) which is why setting it on the command line works.
You don't actually need any special conditional logic in this case, as SDK-style projects support building for multiple target frameworks.
Simply change your Project C to the following:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<!-- See https://docs.microsoft.com/en-us/dotnet/core/project-sdk/msbuild-props#targetframeworks -->
<TargetFrameworks>net48;net5.0</TargetFrameworks>
</PropertyGroup>
<Target Name="DisplayTargetInfo" BeforeTargets="Build">
<Message Importance="high" Text="$(MSBuildProjectName) TargetFramework = $(TargetFramework)" />
</Target>
</Project>