ItemGroup Item scope, иначе "Почему MSBuild ненавидят меня?"

У меня есть решение, которое я пытаюсь построить на TFS. Я хочу обновить версии всех соответствующих файлов, и я застрял, пытаясь сделать это. Есть много ссылок о том, как это сделать, но никто из них не работает для меня из-за одной маленькой проблемы... Область.

<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="DesktopBuild" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">
    <Target Name="DesktopBuild">
        <CallTarget Targets="GetFiles"  />

        <Message Text="CSFiles: '@(CSFiles)'" />
    </Target>

    <Target Name="GetFiles">
        <ItemGroup>
            <CSFiles Include="**\AssemblyInfo.cs" />
        </ItemGroup>
        <Message Text="CSFiles: '@(CSFiles)'" />
    </Target>
</Project>

Мое дерево выглядит так:

  •  
  • test.proj 
  • application.sln 
  • приложение (папка) 
    •     
    • main.cs    
    • Свойства (папка)    
      •        
      • AssemblyInfo.cs    
       

Когда я запускаю "c:\Windows\Microsoft.NET\Framework\v3.5\MSBuild.exe test.proj" из папки решений... Я получаю следующий вывод:

Microsoft (R) Build Engine Version 3.5.30729.1
[Microsoft .NET Framework, Version 2.0.50727.3074]
Copyright (C) Microsoft Corporation 2007. All rights reserved.

Build started 7/6/2009 3:54:10 PM.
Project "D:\src\test.proj" on node 0 (default targets).
  CSFiles: 'application\Properties\AssemblyInfo.cs'
DesktopBuild:
  CSFiles: ''
Done Building Project "D:\src\test.proj" (default targets).


Build succeeded.
    0 Warning(s)
    0 Error(s)

Time Elapsed 00:00:00.04

Итак, как я могу сделать свою ItemGroup глобальной областью? Все файлы Targets, используемые компилятором и TeamBuild, делают то же самое, и все они кажутся глобальными... Я не понимаю, почему это не работает для меня.

Любая помощь?

Ответ 1

Вы пытались использовать DependsOnTarget, а не CallTarget? Возможно, CallTarget вызывает проблему с областью.

Ответ 2

Предыдущий комментатор был прав, вы должны изменить это, чтобы использовать DependsOnTargets вместо использования задачи CallTarget. То, что вы видите, - это bug, не отображающее информацию. способ избежать этой ошибки - использовать DependsOnTargets (это гораздо лучший подход в любом случае).

Сказал Ибрагим Хашими

Моя книга: Внутри Microsoft Build Engine: использование MSBuild и Team Foundation Build

Ответ 3

Как сказано, вы должны использовать DependsOnTargets. Я провел некоторое исследование в области MSBuild, вы можете найти мои результаты в моем блоге: http://blog.qetza.net/2009/10/23/scope-of-properties-and-item-in-an-msbuild-script/

Дело в том, что, похоже, глобальная область для проекта и локальная область для цели. При вводе цели глобальная область копируется и при выходе из целевого объекта локальная область объединяется. Таким образом, CallTarget не получит измененные значения локальной области, но DependsOnTargets будет с момента выхода первой цели до ввода второй цели.

Ответ 4

Мы делаем что-то подобное в нашей сборке. Мы передаем версию как параметр командной строки.

В нашем TFSBuild.proj мы устанавливаем версию на 0.0.0.0, если не была предоставлена ​​версия:

<!--Our assembly version. Pass it in from the command prompt like this: /property:Version=1.0.0.0-->
<PropertyGroup>
    <Version>0.0.0.0</Version>
</PropertyGroup>

<PropertyGroup>
    <!--Used to ensure there is a newline before our text to not break the .cs files if there is no newline at the end of the file.-->
    <newLine>%0D%0A</newLine>

Затем мы делаем следующее:

<Target Name="BeforeCompile">
    <!--Update our assembly version. Pass it in from the command prompt like this: /property:Version=1.0.0.0-->

    <!--attrib needs to be run first to remove the read only attribute since files from tfs are read only by default.-->
    <Exec Command='attrib -R $(SolutionRoot)\Source\Project\GlobalAssemblyInfo.cs'  />

    <WriteLinesToFile File="$(SolutionRoot)\Source\Project\GlobalAssemblyInfo.cs"
                      Lines='$(newLine)[assembly: AssemblyVersion("$(Version)")]'/>

</Target>