But if you do the sa" /> But if you do the sa" /> But if you do the sa"/>

Clean Syntax to Force Property to Have Value

30 Views Asked by At

If you have a project reference with an empty path, it is an error, which is good:

<!-- ERROR -->
<ProjectReference Include="" />

But if you do the same thing with an empty property value, it is NOT an error.

<!-- No error or warning -->
<ProjectReference Include="$(ThisPropertyDoesNotExist)" />

Is there a way I can force the property to have a value?

I have tried using the MSBuild function ValueOrDefault. This kind of works but is a bit messy to use. It took a while to find something that would generate an error, but it seems like '.' and other numbers of dots works.

<!-- Build error when Property missing but messy -->
<ProjectReference Include="$([MSBuild]::ValueOrDefault('$(Property)', '...'))" />

This does cause an error if the property has no value, but it is a bit messy.

I would also like to avoid referring to the property more than once if possible, since that can lead to mistakes. For example, I think I could assert that the property has a value by using an Error task with a Condition but then I have to refer to the property twice and I have to get the name exactly right for it to actually assert the property value correctly.

Ideally I could say something like these:

<ProjectReference Include="$(Property)" Required="true" />
<ProjectReference Include="$(Property.OrThrow())" />

Another option could be if there is some kind of OptionStrict feature I could enable that causes an error on any undefined property usage.

1

There are 1 best solutions below

8
Jonathan Dodds On

MSBuild is (mostly) a declarative language. Unlike a procedural langauge, MSBuild doesn't have loops and it doesn't have unconditional branches.

Properties (and Items) are not the same as variables in a procedural language. There is no "declaration" of a property and MSBuild doesn't distinguish between a property that doesn't exist and a property with an empty value.

If you have a property that may not have a value, you can use a Condition attribute to test. In the following example, $(Property) will be included in @(ProjectReference) when it has a non-empty value.

  <ItemGroup>
    <ProjectReference Include="$(Property)" Condition="$(Property) != ''" />
  </ItemGroup>

The Error task can be used within a target to create an error when $(Property) has no value.

  <Target Name="CheckProperty" BeforeTargets="BeforeBuild">
    <Error Text="'Property' has no value." Condition="$(Property) == ''" />
  </Target>

(For a warning see the Warning task.)

MSBuild processes a project in two phases: evaluation and execution. In the evaluation phase the "top level" elements which are not targets are evaluated and the order of targets is determined. In the execution phase the targets are "run".

An error or warning can't be generated during evaluation but the BeforeTargets="BeforeBuild" attribute sets the CheckProperty target to run very early in the target order. You could have one or multiple "error check" targets to ensure that important properties and items have values after the evaluation phase.