MSBuild Evaluation Order - Stack Overflow

As the documentation stated:The Directory.Build.props file is imported by Microsoft.Common.props, so th

As the documentation stated:

The Directory.Build.props file is imported by Microsoft.Common.props, so the properties defined therein are available in the project file.

So is it implying that Directory.Build.props loads before proj file? However, another documentation showed an example how could a Directory.Build.props set OutDir before proj file. If proj file loads after, shouldn't it override the property? I couldn't find documentation about when were these well-known properties like OutDir evaluated, are they isolated from props and proj file? Maybe this is key I didn't understand.

<!-- Directory.Build.props -->
<Project>
   <PropertyGroup>
      <OutDir>C:\output\$(MSBuildProjectName)</OutDir>
   </PropertyGroup>
</Project>

As the documentation stated:

The Directory.Build.props file is imported by Microsoft.Common.props, so the properties defined therein are available in the project file.

So is it implying that Directory.Build.props loads before proj file? However, another documentation showed an example how could a Directory.Build.props set OutDir before proj file. If proj file loads after, shouldn't it override the property? I couldn't find documentation about when were these well-known properties like OutDir evaluated, are they isolated from props and proj file? Maybe this is key I didn't understand.

<!-- Directory.Build.props -->
<Project>
   <PropertyGroup>
      <OutDir>C:\output\$(MSBuildProjectName)</OutDir>
   </PropertyGroup>
</Project>
Share asked Mar 3 at 21:07 jamgoojamgoo 1071 silver badge4 bronze badges 1
  • Exactly, a *proj file property will overwrite a Directory.Build.props property. Where is your concern? These properties may be not what you want. You may need to overwrite two: BaseIntermediateOutputPath and OutputPath. However, everything depends on your project type, technology and platform; there are many different properties. – Sergey A Kryukov Commented Mar 3 at 23:41
Add a comment  | 

1 Answer 1

Reset to default 1

A project file generated by Visual Studio or the dotnet tool is not self-contained. It depends on standard files supplied by Microsoft.

With a legacy style project or a C++ project you will see the Import elements (and a lot of other content) directly in the project.

An Import is like a textual include. The content of the import file is added to the project.

With an SDK style project, the project file itself is intended to be as clean as possible. The specified type of SDK is used to determine the files to import. But you won't see the imports in the project. In essence there is a project created that imports SDK stuff, then your project, and then more SDK stuff.

Yes, the content of the Directory.Build.props file comes before the content of the project file. And the content of the Directory.Build.targets file comes after the content of the project file.

Directory.Build.props and Directory.Build.targets files are standard MSBuild files with no restrictions. The file name extensions are arbitrary. Properties and targets can be defined in either file.

If you want to override the OutDir property regardless of whether a project is overriding or not, add your OutDir property override in a Directory.Build.targets file. The documentation that you linked to says (with emphasis added):

The Directory.Build.targets file is read in after the project file. It typically contains targets, but here you can also define properties that you don't want individual projects to redefine.

The MSBuild documentation also says:

Directory.Build.props is imported early in Microsoft.Common.props, and properties defined later are unavailable to it. So, avoid referring to properties that aren't yet defined (and will evaluate to empty).

The well-known properties are, in general, defined after the Directory.Build.props and before the project file.

I suggest, as a rule of thumb, avoid using a Directory.Build.props file except for when you actually need to be before the "standard" imports. And it is actually very rare to need to be before the "standard" imports.

Addendum to address questions in the comments

Properties and Items

In MSBuild, data is represented as properties and items.

Properties are scalars, i.e. one value.

Items are collections, i.e. a set of values. Additionally, each member value of an Item collection has metadata.

A $ introduces a property reference, a @ introduces an item reference, and a % introduces a metadata reference.

Properties and items have separate namespaces. The property $(Foo) and the item @(Foo) are separate and unrelated. The names do not conflict.

Evaluation Phase

When MSBuild "runs" a project, there is an evaluation phase followed by an execution phase. The evalution phase looks at the immediate (or "top level") child elements of the Project element.

Top level PropertyGroup and ItemGroup elements will be evaluated in the evaluation phase. PropertyGroup and ItemGroup elements that are within Target elements will not be evaluated until the execution phase.

Within the evalaution phase, there is an order to when different elements are evaluated. Properties are evalauted before items.

The "Subtle effects of the evaluation order" section of the documentation has an example where an ItemGroup lexically appears first, but the PropertyGroup is evaluated first. The "late" expansion is because of an item transformation. The question of "how could a Directory.Build.props set OutDir?" doesn't involve an item transformation.

MSBuildProjectName

$(MSBuildProjectName) is a member of the set of "reserved properties". Reserved properties can't be overriden or changed. They are defined by the MSBuild engine itself and injected into the project before any properties are evaluated. You can't define a property before the reserved properties exist.

OutDir

$(OutDir) is a "Common Project Property". It is defined in a common Microsoft file. The Directory.Build.props file, if there is one, will be imported before $(OutDir) is defined.

However, as I mentioned in a comment, some property definitions check if the property already has a value and don't override. I checked the definition of $(OutDir) and confirmed that it behaves this way.

A Directory.Build.props file can define a value for $(OutDir) and the value will not be overriden by the standard project support.

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745072071a4609610.html

相关推荐

  • MSBuild Evaluation Order - Stack Overflow

    As the documentation stated:The Directory.Build.props file is imported by Microsoft.Common.props, so th

    2小时前
    20

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信