Andrey Minakov
Andrey Minakov

Reputation: 576

how use properties from Directory.Build.props in Import from project file of Visual Studio

I have this situation:

I have a .proj file in project directory:

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <ItemGroup>
    <Compile Include="PQExtensionTest.pq">
      <SubType>Code</SubType>
    </Compile>
    <Content Include="PQExtensionTest.query.pq">
      <SubType>Code</SubType>
    </Content>
  </ItemGroup>
  <!-- <Import Project="..\Directory.Build.props" /> -->
  <Import Project="$(aProperty)add.targets" />
</Project>

In the solution directory (..\ from project directory) I have file Directory.Build.props:

<Project DefaultTargets="BuildExtension" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <aProperty>$(MSBuildProjectDirectory)/Subdir/</aProperty>
  </PropertyGroup>
</Project>

In the project directory I have subdirectory "Subdir", where there is file add.targets, which contains all the targets I need (do not show it's contains here because it is not relevant to the problem).

So all above has this folder structure:

Solution directory
  Directory.Build.props
  Project Directory
    Project.mproj
    Subdir
      add.targets

Preparing all the above, I expected that aProperty will be initiated before the import and the import of add.targets will happen without problem. But I get error that imported project is not found, and I see in error message that MSBuild tries to import from project directory, and not from subdirectory Subdir.

If I uncomment this row:

<Import Project="..\Directory.Build.props" />

all works fine.

The only reasonable explanation for me of such behavior is that aProperty is empty at the moment of importing, because explicit import happens before implicit one.

Is there any way to force MSBuild to inexplicitly import Directory.Build.props before any other imports, while work in Visual Studio?

Upvotes: 9

Views: 19050

Answers (2)

vikas pachisia
vikas pachisia

Reputation: 615

The way to import properties from 'Directory.Build.props' file from nested folder structure is given below:

Refer: https://learn.microsoft.com/en-us/visualstudio/msbuild/customize-your-build?view=vs-2019

Note that: 1. These property file definition works from MSBuild tools version 15.0 2. You need to be aware of where to place this import: At the beginning of the file or at the end of the file. Generally it is good to place at the end as nested properties will be visible to parent properties.

Upvotes: 0

LoLance
LoLance

Reputation: 28146

"While in Visual Studio"

For C# and VB language project, we don't need to import Directory.Build.props manually or force it before other imports.

When creating a new project(C# or VB) in VS, open its proj file we can find the format is like this:

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
  <PropertyGroup>
    ...
  </PropertyGroup>
  <ItemGroup>
    ...
  </ItemGroup>
  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project> 

Every time when creating new C# or VB project, the top line within the <Project>node is Import project="Microsoft.Common.props", and we can find the sentence from this document:

When MSBuild runs, Microsoft.Common.props searches your directory structure for the Directory.Build.props file (and Microsoft.Common.targets looks for Directory.Build.targets). If it finds one, it imports the property.

So in visual studio, we don't need to force it before other imports.Its always called after import Microsoft.Common.props, and since the import Microsoft.Common.props is always first line of project node by default, the Directory.Build.Targets is always implicitly imported right after the Microsoft.Common.props and before others.

Note: This feature only supports C# and VB, cause only these two kinds of projects will import the Microsoft.Common.Props in proj file.

And for other kinds of projects, just like your .mproj or .vcxproj(C++), this feature(Directory.Build.props) is not supported yet.

So the Directory.Build.Targets or .props is the same as any custom .props. It doesn't make difference between Directory.Build.Targets and anyName.props.

In this way,to read the value in it we have to use import project to call it manually. And that's why the build can't succeed until you uncomment the row:<Import Project="..\Directory.Build.props" />

Upvotes: 6

Related Questions