visual-studiomsbuildconditional-statementspackagereference

MSBuild Conditions Not Evaluating


I have an app which can come in one of 3 "flavors", the flavor depends only on the NuGet packages that are referenced in the project. In order to simplify the build, I want to use a custom property to define the flavor and then use conditions on the package references. It should be possible to build the app using Visual Studio or using MSBuild CommandLine. I added this to the PropertyGroup:

<Flavor Condition= "'$(Flavor)'==''">Flavor1</Flavor>

I can see the custom property is being set correctly, simply the conditions are being ignored This is what I tried:

  1. Setting the condition on the PackageReference itself as described here: https://learn.microsoft.com/en-us/nuget/consume-packages/package-references-in-project-files#adding-a-packagereference-condition
  2. Placing the conditioned packages in separate ItemGroup and setting the condition there
  3. Same as #2 but with Choose+When

Only #3 works and only in Visual Studio I need a solution that will work in both Visual Studio and MSBuild command line

#1 looks like this:

<PackageReference Include="Falvor1Package" Condition="'$(Flavor)'=='Flavor1'">
    <Version>1.1.1.1</Version>
</PackageReference>
<PackageReference Include="Falvor2Package" Condition="'$(Flavor)'=='Flavor2'">
    <Version>1.1.1.1</Version>
</PackageReference>

#2 looks like this:

<ItemGroup Condition="'$(Flavor)'=='Flavor1'">
    <PackageReference Include="Falvor1Package">
        <Version>1.1.1.1</Version>
    </PackageReference>
</ItemGroup>
<ItemGroup Condition="'$(Flavor)'=='Flavor2'">
    <PackageReference Include="Falvor2Package">
        <Version>1.1.1.1</Version>
    </PackageReference>
</ItemGroup>

#3 looks like this:

<Choose>
    <When Condition="'$(Flavor)'=='Flavor1'">
        <ItemGroup>
            <PackageReference Include="Falvor1Package">
                <Version>1.1.1.1</Version>
            </PackageReference>
        </ItemGroup>
    </When>
</Choose>
<Choose>
    <When Condition="'$(Flavor)'=='Flavor2'">
        <ItemGroup>
            <PackageReference Include="Falvor2Package">
                <Version>1.1.1.1</Version>
            </PackageReference>
        </ItemGroup>
    </When>
</Choose>

I am using VS2019 and MSBuild 16 What am I missing?


Solution

  • AFAIK, that doesn't work. You cannot use arbitrary conditions (properties) on PackageReference. Also see this:

    You can use a condition to control whether a package is included, where conditions can use any MSBuild variable or a variable defined in the targets or props file. However, at presently, only the TargetFramework variable is supported.

    In other words, you could do something like this, but not use your custom property:

    <ItemGroup>
        <PackageReference Include="..." Version="..." Condition="'$(TargetFramework)' == '...'" />
    </ItemGroup>
    

    Where the value of TargetFramework must be a valid TFM.

    The same applies when adding the condition to the/a enclosing ItemGroup element.

    Guesswork: I guess that the reason is, that when supporting arbitrary conditions here that wouldn't play well with Visual Studio. Because in the end, it has know which nuget packages (assemblies in the end), are referenced. The TargetFramework value is changed by changing the respective setting inside Visual Studio, so it can cope with that (manually), adjusting the referenced packages accordingly. It would be hard to do that for arbitrary stuff. But that all is just a guess and might be totally wrong.