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


我有一个共享的属性文件 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 target在不起作用的新尝试上显示此信息:

CheckReferencePaths:   做CheckReferencePaths   d:\项目\团队\项目\适配器\将对DBAdapter \ dbadapter.csproj(103,5):   警告:''找不到SharedAssemblyPath   d:\项目\团队\项目\适配器\将对DBAdapter \ dbadapter.csproj(104,5):   警告:''找不到SharedAssemblyPath
  FULLPATH = \的NuGet \ EntityFramework.4.3.0 \ lib中\ net40 \ EntityFramework.dll
  FULLPATH =

如何在评估项目组的提示路径之前,获取导入共享的项目文件以评估导入项目的属性。或者评估顺序是否正确,但我的构造中的其他内容是不正确的?


2015
2018-03-02 16:35


起源



答案:


你的问题让我觉得这很有价值 信息 MSDN。我在这里张贴它以保持答案 自足


评估顺序

当MSBuild到达时 进口 元素,导入的项目有效地插入到导入项目的位置 进口 元件。因此,的位置 进口 element可以影响属性和项的值。了解导入项目设置的属性和项以及导入项目使用的属性和项非常重要。

项目构建时,首先评估所有属性,然后评估项目。例如,以下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文件。

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

17
2018-03-28 14:43



当然在最后一个例子中,你的意思是在属性组定义之前进行导入? - Adam
@Adam没有,因为 Flavor 是有条件的 <Flavor Condition="'$(Flavor)'==''"> 这意味着它将采用第一个定义的值(在这种情况下为RETAIL) - KMoraz


答案:


你的问题让我觉得这很有价值 信息 MSDN。我在这里张贴它以保持答案 自足


评估顺序

当MSBuild到达时 进口 元素,导入的项目有效地插入到导入项目的位置 进口 元件。因此,的位置 进口 element可以影响属性和项的值。了解导入项目设置的属性和项以及导入项目使用的属性和项非常重要。

项目构建时,首先评估所有属性,然后评估项目。例如,以下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文件。

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

17
2018-03-28 14:43



当然在最后一个例子中,你的意思是在属性组定义之前进行导入? - Adam
@Adam没有,因为 Flavor 是有条件的 <Flavor Condition="'$(Flavor)'==''"> 这意味着它将采用第一个定义的值(在这种情况下为RETAIL) - KMoraz


尝试使用内联任务而不是shared.properties.proj文件。检查我的答案 这个问题

它是关于搜索某些文件是父目录。您可以调整它以搜索父目录。


-1
2018-03-02 21:42



非常确定内联任务不适用于itemgroup提示路径,以便visual studio正确搜索设计时解决方案资源管理器。 - Maslow