Когда вы импортируете другой файл msbuild, каков порядок оценки? - PullRequest
11 голосов
/ 02 марта 2012

У меня есть файл общих свойств 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 ]

18 голосов
/ 28 марта 2012

Ваш вопрос заставил меня найти эту ценную информацию о 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>

Когда проектbuilds, отображается следующее сообщение:

Name = "MyCommon"

Поскольку проект импортируется после определения свойства Name в MyApp.proj, определение Name в MyCommon.targetsпереопределяет определение в 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>
0 голосов
/ 03 марта 2012

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

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

...