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
|
1 Answer
Reset to default 1A 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
BaseIntermediateOutputPath
andOutputPath
. However, everything depends on your project type, technology and platform; there are many different properties. – Sergey A Kryukov Commented Mar 3 at 23:41