2009-07-06 22 views
10

Tengo una solución que estoy tratando de construir en TFS. Quiero actualizar las versiones de todos los archivos apropiados, y he estado atascado tratando de hacer esto. Hay muchos enlaces sobre cómo hacerlo, pero ninguno de ellos funciona para mí, debido a un pequeño problema ... Alcance.ItemGroup Ámbito del artículo, como alternativa "¿Por qué MSBuild me odia?"

<?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> 

Mi árbol se parece a esto:

  • test.proj
  • application.sln
  • aplicación (carpeta)
    • main.cs
    • Propiedades (carpeta)
      • AssemblyInfo.cs

Cuando corro "c: \ Windows \ Microsoft.NET \ Framework \ v3.5 \ MSBuild.exe test.proj" de la carpeta de la solución ... me sale la siguiente salida:

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 

Entonces, ¿cómo puedo hacer que mi ItemGroup tenga alcance global? Todos los archivos de Targets utilizados por el compilador y TeamBuild hacen lo mismo, y todos parecen ser globales ... No entiendo por qué esto no funciona para mí.

¿Algún ayuda?

+0

¿Estás tratando de construir el archivo test.proj? No estoy seguro de entender por qué está especificando AssemblyInfo.cs en lugar de crear el archivo del proyecto. –

+0

Creé el archivo test.proj como un ejemplo mínimo que muestra mi problema. En realidad, estoy tratando de construir mi archivo de solución múltiple en TFS. Esto es solo para ilustrar el comportamiento de scoping que veo en ItemGroups and Targets. –

+0

Desearía poder recomendar a todas las personas que intentan ayudar, pero aparentemente soy demasiado "nuevo". Solo quería dejar una nota que agradezco el tiempo que todos pasaron mirando y pensando en esto. –

Respuesta

9

¿Ha intentado utilizar DependsOnTarget en lugar de CallTarget? Podría ser que CallTarget está causando el problema de alcance.

+0

OK, esto parece darme más información. Puedo cambiar el alcance del ItemGroup usando DependsOn, pero no parece consistente. Parece que los hermanos de los objetivos invocados con dependenson tienen acceso al grupo de elementos, pero el padre nunca lo hace. Tan raro. ¿Hay algún documento que muestre las reglas de alcance? No pude encontrarlos, y creo que ahora tengo que volver a escribir mis archivos usando dependencias complejas en lugar de llamadas. Esto es tan loco. –

+0

No he visto ninguno. ¿Has intentado simplemente mover el ItemGroup fuera de los Objetivos por completo? ¿Hay alguna razón por la que no quieras hacer eso? – technophile

+0

o inicializar fuera para vaciar (piratear con Incluir = "*. WontExist") –

0

Hacemos algo similar en nuestra compilación. Pasamos la versión como un parámetro de línea de comando.

En nuestra TFSBuild.proj hemos indicado que la versión 0.0.0.0 si hay versión fue suministrada:

<!--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> 

Luego de hacer esto:

<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> 
+2

Para su información, no existe no hace lo que el código parece esperar que haga. Existen controles para ver si el archivo nombrado existe, no si existe la variable nombrada. Probablemente quieras Condition = "'$ (Version)' == ''" en su lugar. Ver http://msdn.microsoft.com/en-us/library/7szfhaft.aspx – technophile

+0

Este chico tecnófilo es inteligente. :-) Lo que dijo. La forma estándar de doc es rodear con comillas simples y poner mucho espacio en blanco alrededor ... Además, este método no es asombroso para mí . Prefiero los métodos de tareas de la comunidad MSBuild para attrib y regex actualizar los archivos. Mi problema es crear la lista de archivos para actualizar, ya que tengo ubicaciones dinámicas. Gracias sin embargo. :-) –

+0

Gracias Chris. :) Estamos en el medio de hacer un montón de trabajo en nuestro entorno de CI, así que todo esto es muy fresco en mi mente. ;) – technophile

5

El comentarista anterior era correcto, debe cambie esto para usar DependsOnTargets en lugar de usar la tarea CallTarget. Lo que está viendo es un bug que no es un scoping inssue. El error way to avoid es usar DependsOnTargets (que es un enfoque mucho mejor de todos modos).

Sayed Ibrahim Hashimi

Mi libro: Inside the Microsoft Build Engine : Using MSBuild and Team Foundation Build

+0

¿Es realmente un error? La explicación ofrecida [aquí] (http://blogs.msdn.com/b/aaronhallberg/archive/2007/07/16/msbuild-property-evaluation.aspx) es igualmente convincente, y es corroborada por el hecho de que se trata todavía cómo funciona esto, varios años después. –

+0

Es un error, consulte http://blogs.msdn.com/b/msbuild/archive/2006/01/03/508629.aspx –

1

Como se ha dicho, se debe utilizar DependsOnTargets. He hecho algunas investigaciones sobre el alcance de MSBuild, puede encontrar mis resultados en mi blog: http://blog.qetza.net/2009/10/23/scope-of-properties-and-item-in-an-msbuild-script/

Parece que hay un alcance global para el proyecto y un alcance local para el objetivo. Al ingresar el objetivo, se copia el alcance global y al salir del objetivo, el alcance local se fusiona nuevamente. Entonces, una CallTarget no obtendrá los valores de alcance locales modificados, pero DependsOnTargets lo hará desde que se sale del primer objetivo antes de ingresar el segundo.

Cuestiones relacionadas