Когда вы импортируете другой файл 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 показывает это при новой попытке, которая не работает:

CheckReferencePaths: Выполнение CheckReferencePaths D:\Projects\Team\Project\Переходники\DbAdapter\dbadapter.csproj(103,5): предупреждение: SharedAssemblyPath не найден в '' D:\Projects\Team\Project\Переходники\DbAdapter\dbadapter.csproj(104,5): предупреждение: SharedAssemblyPath не найден в ''
FullPath =\NuGet\EntityFramework.4.3.0\Lib\net40\EntityFramework.dll
FullPath =

Как я могу получить файл проекта, который импортирует shared, чтобы оценить импортированные свойства проекта, прежде чем он оценит hintpaths групп элементов. Или собственно порядок оценки, но что-то еще в моей конструкции неверно?

Ответ 1

Ваш вопрос заставил меня найти эту ценную информацию о MSDN. Я размещаю его здесь для сохранения ответа автономного.


Порядок оценки

Когда MSBuild достигает элемента Импорт, импортированный проект эффективно вставляется в проект импорта в месте расположения элемента Импорт. Поэтому расположение элемента Импорт может влиять на значения свойств и элементов. Важно понимать свойства и элементы, заданные импортированным проектом, а также свойства и элементы, которые использует импортированный проект.

Когда проект строится, сначала сначала оцениваются все свойства, а затем элементы. Например, следующий 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"

Поскольку проект импортируется после определения свойства Name в MyApp.proj, определение Name в MyCommon.targets переопределяет определение в MyApp.proj. Если проект импортируется до определения имени свойства, в сборке будет отображаться следующее сообщение:

Name= "MyApp"

При импорте проектов

используйте следующий подход:
  • Определите в файле проекта все свойства и элементы, которые используются как параметры свойств и элементов в импортированном проекте.

  • Импортируйте проект.

  • Определите в файле проекта все свойства и элементы, которые должны переопределять определения свойств и элементов по умолчанию в импортированных проект.

Пример

В следующем примере кода показан файл 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>

Ответ 2

Попробуйте использовать встроенную задачу вместо файла shared.properties.proj. Проверьте мой ответ на этот вопрос.

Речь идет о поиске какого-либо файла в родительских каталогах. Вы можете адаптировать его для поиска родительского каталога.