当您导入另一个msbuild文件时,评估的顺序是什么?

13

我有一个共享的属性文件 shared.properties.proj

<Project  xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <SharedAssemblySearch>$(MSBuildProjectDirectory)\..\Shared Assemblies</SharedAssemblySearch>
    <ParentDir>..</ParentDir>
    <SharedAssemblySearch Condition="!Exists('$(SharedAssemblySearch)')">$(ParentDir)\$(SharedAssemblySearch)</SharedAssemblySearch>
    <SharedAssemblySearch Condition="!Exists('$(SharedAssemblySearch)')">$(ParentDir)\$(SharedAssemblySearch)</SharedAssemblySearch>
    <SharedAssemblySearch Condition="!Exists('$(SharedAssemblySearch)')">$(ParentDir)\$(SharedAssemblySearch)</SharedAssemblySearch>
    <SharedAssemblySearch Condition="!Exists('$(SharedAssemblySearch)')">$(ParentDir)\$(SharedAssemblySearch)</SharedAssemblySearch>
    <SharedAssemblySearch Condition="!Exists('$(SharedAssemblySearch)')">$(ParentDir)\$(SharedAssemblySearch)</SharedAssemblySearch>
    <SharedAssemblySearch Condition="!Exists('$(SharedAssemblySearch)')">$(ParentDir)\$(SharedAssemblySearch)</SharedAssemblySearch>
    <SharedAssemblyPath Condition="Exists('$(SharedAssemblySearch)')">$(SharedAssemblySearch)</SharedAssemblyPath>
    <SharedAssemblySearch Condition="!Exists('$(SharedAssemblySearch)')">..\SharedAssemblies</SharedAssemblySearch>
    <SharedAssemblySearch Condition="!Exists('$(SharedAssemblySearch)')">$(ParentDir)\$(SharedAssemblySearch)</SharedAssemblySearch>
    <SharedAssemblySearch Condition="!Exists('$(SharedAssemblySearch)')">$(ParentDir)\$(SharedAssemblySearch)</SharedAssemblySearch>
    <SharedAssemblySearch Condition="!Exists('$(SharedAssemblySearch)')">$(ParentDir)\$(SharedAssemblySearch)</SharedAssemblySearch>
    <SharedAssemblySearch Condition="!Exists('$(SharedAssemblySearch)')">$(ParentDir)\$(SharedAssemblySearch)</SharedAssemblySearch>
    <SharedAssemblyPath Condition="Exists('$(SharedAssemblySearch)')">$(SharedAssemblySearch)</SharedAssemblyPath>
 </PropertyGroup>
</project>

我正在寻找包含名为Shared Assemblies的目录的任何级别的父目录。或者是SharedAssemblies

我想将此代码放在sln的中心位置,以便所有项目都可以导入它。sln中的项目不都位于同一层次结构。

示例.csproj

    <?xml version="1.0" encoding="utf-8"?>
    <Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
    <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), Shared.Properties.proj))\Shared.Properties.proj"
   Condition=" '$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), Shared.Properties.proj))' != '' "/>
    <ItemGroup>
    <Reference Include="EntityFramework">
      <HintPath>$(SharedAssemblyPath)\NuGet\EntityFramework.4.3.0\lib\net40\EntityFramework.dll</HintPath>
     </Reference>
    </ItemGroup>
  <Target Name="CheckReferencePaths" BeforeTargets="ResolveAssemblyReferences">
    <Message Importance="high" Text="Doing CheckReferencePaths" />
    <ItemGroup>
     <SharedAssemblyPathItem Include="$(SharedAssemblyPath)" />
    </ItemGroup>
    <Warning Condition="!Exists('@(SharedAssemblyPathItem)')" Text="SharedAssemblyPath not found at '@(SharedAssemblyPathItem)'" />
    <Warning Condition="!Exists('@(SharedAssemblyPathItem)')" Text="SharedAssemblyPath not found at '@(SharedAssemblyPathItem->'%(FullPath)')'" />
    <Message Condition="!Exists('%(Reference.HintPath)')" Text="FullPath=%(Reference.HintPath)" Importance="high" />

我已经在主项目中使其正常工作,但没有将属性组推出到我导入的卫星文件中,现在想要在其他可能具有共享引用的项目之间实现可重用性。

在新尝试中,BeforeTargets目标显示以下内容,但它无法正常工作:

  

CheckReferencePaths:   正在执行 CheckReferencePaths   D:\ projects \ Team \ Project \ Adapters \ DbAdapter \ dbadapter.csproj(103,5):   警告:未在''处找到 SharedAssemblyPath   D:\ projects \ Team \ Project \ Adapters \ DbAdapter \ dbadapter.csproj(104,5):   警告:未在''处找到 SharedAssemblyPath
  FullPath = \ NuGet \ EntityFramework.4.3.0 \ lib \ net40 \ EntityFramework.dll
  FullPath =

如何使导入共享的项目文件在评估项组的提示路径之前评估导入项目的属性? 或者评估顺序是否正确,但是我的构造中还有其他问题?

2个回答

19

阅读您的问题让我发现了这个有价值的MSDN信息,我在这里发布它以保持答案自包含


评估顺序

当 MSBuild 到达 Import 元素时,被导入的项目会被有效地插入到导入项目的位置处,即 Import 元素所在的位置。因此,Import 元素的位置可能会影响属性和项的值。重要的是要了解由导入的项目设置的属性和项,以及导入的项目使用的属性和项。

在构建项目时,所有属性首先进行评估,随后是项。例如,以下 XML 定义了导入项目文件 MyCommon.targets:

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
    <PropertyGroup>
        <Name>MyCommon</Name>
    </PropertyGroup>

    <Target Name="Go">
        <Message Text="Name='$(Name)'"/>
    </Target>
</Project>
以下的 XML 定义了 MyApp.proj,它引入了 MyCommon.targets:
<Project
    DefaultTargets="Go"
    xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
    <PropertyGroup>
        <Name>MyApp</Name>
    </PropertyGroup>
    <Import Project="MyCommon.targets"/>
</Project>

当项目构建时,会显示以下消息:

Name="MyCommon"

因为该项目在 MyApp.proj 定义 Name 属性之后被导入,所以 MyCommon.targets 中的 Name 定义将覆盖 MyApp.proj 中的定义。如果项目在定义 Name 属性之前被导入,则构建将显示以下消息:

Name="MyApp"

导入项目时,请使用以下方法

  1. 在项目文件中定义所有用作导入项目中属性和项的参数的属性和项。

  2. 导入项目。

  3. 在项目文件中定义必须覆盖导入项目中属性和项的默认定义的所有属性和项。

示例

以下代码示例显示了第二个代码示例导入的 MyCommon.targets 文件。.targets 文件评估从导入项目传递的属性以配置构建。

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
    <PropertyGroup>
        <Flavor Condition="'$(Flavor)'==''">DEBUG</Flavor>
        <Optimize Condition="'$(Flavor)'=='RETAIL'">yes</Optimize>
        <appname>$(MSBuildProjectName)</appname>
    <PropertyGroup>
    <Target Name="Build">
        <Csc Sources="hello.cs"
            Optimize="$(Optimize)"
            OutputAssembly="$(appname).exe"/>
    </Target>
</Project>
以下代码示例导入了 MyCommon.targets 文件。

以下代码示例导入了 MyCommon.targets 文件。

<Project DefaultTargets="Build"
    xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
    <PropertyGroup>
        <Flavor>RETAIL</Flavor>
    </PropertyGroup>
    <Import Project="MyCommon.targets"/>
</Project>

在最后一个例子中,你肯定是想让导入在propertygroup定义之前吧? - Adam
@Adam 不是的,因为 Flavor 有一个条件 <Flavor Condition="'$(Flavor)'==''">,这意味着它将采用第一个定义的值(在此情况下为 RETAIL)。 - KMoraz

-1

尝试使用内联任务而不是shared.properties.proj文件。请查看此问题上的我的答案。

这是关于在父目录中搜索某些文件的问题。您可以将其调整为搜索父目录。


1
相当确定内联任务对于 itemgroup hintpaths 不起作用,以便 Visual Studio 正确搜索设计时解决方案资源管理器。 - Maslow

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接