Home > Blockchain >  MSBuild Set Property to Influence Restore/Build of Project Dependencies
MSBuild Set Property to Influence Restore/Build of Project Dependencies

Time:11-08

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>

  • Related