¿Cómo puedo obtener TFS 2010 para construir cada proyecto en un directorio separado?
msbuild tfs2010 (9)
En nuestro proyecto, nos gustaría que nuestra compilación TFS coloque cada proyecto en su propia carpeta debajo de la carpeta desplegable, en lugar de colocar todos los archivos en una estructura plana. Para ilustrar, nos gustaría ver algo como esto:
DropFolder/
Foo/
foo.exe
Bar/
bar.dll
Baz
baz.dll
Esta es básicamente la misma pregunta que se hizo here , pero ahora que estamos usando versiones basadas en flujo de trabajo, esas soluciones no parecen funcionar. La solución que utiliza la propiedad CustomizableOutDir parece que funcionaría mejor para nosotros, pero no puedo hacer que esa propiedad sea reconocida. Personalicé nuestro flujo de trabajo para pasarlo a MSBuild como un argumento de línea de comandos (/ p: CustomizableOutDir = true), pero parece que MSBuild simplemente lo ignora y coloca la salida en el OutDir dado por el flujo de trabajo.
Miré los registros de compilación, y puedo ver que las propiedades CustomizableOutDir y OutDir se están configurando en los argumentos de la línea de comandos para MSBuild. Todavía necesito que OutDir se transfiera para poder copiar mis archivos a TeamBuildOutDir al final.
¿Alguna idea de por qué mi parámetro CustomizableOutDir no se reconoce, o si hay una mejor manera de lograrlo?
Aquí hay otra solución muy simple que no requiere modificación de los archivos de origen o de proyecto. Al configurar el Proceso de la definición de compilación -> Proyectos para compilar, en lugar de especificar su archivo .sln en los proyectos para compilar, agregue cada proyecto (.csproj o .vbproj). Ahora dentro del paso "Ejecutar MSBuild para Proyecto" de su flujo de trabajo, cambie la propiedad OutDir a lo siguiente:
OutputDirectory + "/" + System.IO.Path.GetFileNameWithoutExtension(serverBuildProjectItem)
Aquí hay una solución muy simple que no requiere ninguna modificación a los archivos de origen o de proyecto. Al configurar el Proceso de la definición de compilación -> Proyectos para compilar, en lugar de especificar su archivo .sln en los proyectos para compilar, agregue cada proyecto (.csproj o .vbproj). Ahora dentro del paso "Ejecutar MSBuild para Proyecto" de su flujo de trabajo, cambie la propiedad OutDir a lo siguiente:
outputDirectory + "/" + serverBuildProjectItem.Substring(serverBuildProjectItem.LastIndexOf("/"), serverBuildProjectItem.Length - serverBuildProjectItem.LastIndexOf("/")).Replace(".csproj", String.Empty)
Esto colocará la salida de compilación de cada proyecto en un subdirectorio que lleva el nombre del proyecto.
Descubrí una buena manera de hacerlo. Resulta que, dado que puede establecer el OutDir a lo que quiera dentro del flujo de trabajo, si lo establece en la cadena vacía, MSBuild usará el OutputPath específico del proyecto. Eso nos permite ser mucho más flexibles. Aquí está mi solución completa (basada en el flujo de trabajo de compilación predeterminado):
En la tarea Ejecutar MSBuild, establezca OutDir en la cadena vacía. En esa misma tarea, configure sus CommandLineArguments en algo como lo siguiente. Esto le permitirá tener una referencia al OutDir predeterminado de TFS de su proyecto:
String.Format("/p:CommonOutputPath=""{0}//""", outputDirectory)
En cada proyecto que desee copiar en la carpeta desplegable, establezca el OutputPath como:
<PropertyGroup Condition=" ''$(Configuration)|$(Platform)'' == ''Release|AnyCPU'' ">
<OutputPath Condition=" ''$(CommonOutputPath)''=='''' ">bin/Release/</OutputPath>
<OutputPath Condition=" ''$(CommonOutputPath)''!='''' ">$(CommonOutputPath)YourProjectName/bin/Release/</OutputPath>
</PropertyGroup>
Verifique todo y debe tener una compilación que funcione y que implemente cada uno de sus proyectos en su propia carpeta debajo de la carpeta desplegable.
Instalé el paquete PublishedApplications de Nuget para cada ejecutable en My Solution y creé subcarpetas en la carpeta _PublishedApplications para cada proyecto durante la compilación.
Los pasos aquí no requieren una modificación del archivo de proyecto - http://lajak.wordpress.com/2011/05/07/customize-binaries-folder-in-tfs-team-build/
No estoy seguro de si todavía puede hacer que Team Build 2010 use la última versión de msbuild, pero hay una nueva propiedad / p: GenerateProjectSpecificOutputFolder = true cuando se especifique, los bits caerán en $ (OutDir) / $ (ProjectName) / para cada proyecto.
No he jugado con obtener TFS / MSBuild para colocar los archivos de salida en carpetas separadas, así que no puedo dar una respuesta directa. Sin embargo, aquí hay un par de sugerencias que no vi en su enlace:
Podría agregar pasos posteriores a la compilación a los proyectos que copian los archivos requeridos a una estructura de "implementación". (Esto, por supuesto, también se ejecutaría en las máquinas de desarrollo, lo que podría ser un dolor). Utilizamos este enfoque para nuestras bibliotecas, que se crean y luego se copian en una carpeta de archivos compartidos (binarios) para que otros proyectos puedan consultarlas.
Puede agregar un destino de MSBuild para copiar los archivos requeridos donde los desee. Hemos anulado los objetivos predeterminados de "copiar a soltar carpeta" para copiar los archivos a otra carpeta, ofuscarlos, firmarlos digitalmente, crearlos en un instalador, firmar digitalmente el instalador y luego copiarlo (y otras cosas útiles como el archivos de mapa de ofuscación) y una lista de los cambios realizados desde la última compilación a la carpeta desplegable. En última instancia, agregar su propio objetivo posterior a la construcción le brinda el máximo control sobre qué se pone exactamente dónde. (En el lado negativo, es posible que tenga que agregar manualmente cualquier dlls o exes nuevos al objetivo de copia posterior a la compilación, lo que podría ser una irritación)
También resolví este problema y creo que es más limpio que las soluciones existentes en este hilo.
- Antes de
Run MSBuild for Project
la actividadRun MSBuild for Project
, agregué una actividadAssign
: nombre deprojectName = Regex.Replace(New FileInfo(localProject).Name, "/.sln$", "")
. - A continuación, agregué una actividad
Create Directory
:outputDirectory + "/" + projectName
- Finalmente en la actividad de MSBuild cambié
OutDir
aoutputDirectory + "/" + projectName
.
La plantilla ya llena localProject
con el nombre completo de la ruta del archivo .sln
que se está construyendo en el Agente, por ejemplo, c:/build/path/to/MySolution.sln
. La actividad de asignación corta la ruta y la extensión, colocando la salida en MySolution
. Deberá crear la variable projectName
e importar System.Text.RegularExpressions
y System.IO
.
La ventaja sobre la solución de OP es que no tiene que editar cada .csproj
, esa información se deduce del nombre del archivo de la solución.
Tuvimos que hacer esto para evitar el problema donde tenemos una biblioteca de Silverlight y .Net con el mismo nombre para la serialización CSLA. La biblioteca se sobrescribiría y nuestras pruebas fallarían.
Utilicé la respuesta de Jonathan y la publicación de Jim Lamb , pero descubrí que también necesitas configurar OutDir para que esté vacío.
Por lo tanto, debe realizar estos parámetros para las actividades de MSBuild (si usa la siguiente Macro, también debe configurar los parámetros de actividad para Limpiar; de lo contrario, recibirá advertencias de que OutputPath no está configurado):
- Establezca CommandLineArguments en
String.Format("/p:SkipInvalidConfigurations=true;TeamBuildOutDir=""{0}"" {1}", BinariesDirectory, MSBuildArguments)
- Establecer OutDir en vacío (era BinariesDirectory)
También he creado una macro que se puede ejecutar en Visual Studio que elimina el OutputPath de las configuraciones, y agrega un PropertyGroup que contiene el OutputPath para todas las configuraciones así:
<PropertyGroup Label="OutputPathLabel">
<OutputPath Condition="''$(TeamBuildOutDir)''=='''' ">bin/$(Configuration)/</OutputPath>
<OutputPath Condition="''$(TeamBuildOutDir)''!='''' ">$(TeamBuildOutDir)/$(SolutionName)/$(MSBuildProjectName)/$(Configuration)/</OutputPath>
</PropertyGroup>
Aquí está la macro:
Public Sub SetTeamBuildOutDir()
Dim projectObjects = DTE.Solution.Projects
For Each project In projectObjects
If project.ProjectItems IsNot Nothing Then
SetTeamBuildOutDirRecursive(project)
End If
Next
End Sub
Sub SetTeamBuildOutDirRecursive(ByVal proj As Project)
If proj.ConfigurationManager Is Nothing Then
For Each subProj As ProjectItem In proj.ProjectItems
If subProj.SubProject IsNot Nothing Then
SetTeamBuildOutDirRecursive(subProj.SubProject)
End If
Next
Else
SetTeamBuildOutDir(proj)
End If
End Sub
Sub SetTeamBuildOutDir(ByVal project As Project)
''Do not handle .vdproj
If project.FullName.ToLower().EndsWith(".vdproj") Then
Exit Sub
End If
Dim needToSave = False
Dim msproject = ProjectRootElement.Open(project.FullName)
Dim outputPathGroupExists = False
Dim outputPropertyGroup As ProjectPropertyGroupElement = Nothing
Dim lastConfigPropertyGroup As ProjectPropertyGroupElement = Nothing
For Each propertyGroup In msproject.PropertyGroups
If propertyGroup.Label = "OutputPathLabel" Then
outputPathGroupExists = True
outputPropertyGroup = propertyGroup
End If
If Not String.IsNullOrEmpty(propertyGroup.Condition) AndAlso _
propertyGroup.Condition.TrimStart().StartsWith("''$(Configuration)") Then
lastConfigPropertyGroup = propertyGroup
End If
''Remove the OutputPath from the configurations
Dim outputPathElement As ProjectPropertyElement = Nothing
For Each element As ProjectPropertyElement In propertyGroup.Children
If element.Name = "OutputPath" Then
outputPathElement = element
End If
Next
If outputPathElement IsNot Nothing Then
propertyGroup.RemoveChild(outputPathElement)
needToSave = True
End If
Next
''If we want to always remove the group and add it back (in case of modifications to the group)
''If outputPathGroupExists Then
'' msproject.RemoveChild(outputPropertyGroup)
'' outputPathGroupExists = False
''End If
If Not outputPathGroupExists Then
Dim propertyGroup = msproject.CreatePropertyGroupElement()
propertyGroup.Label = "OutputPathLabel"
''Need to insert the PropertyGroup before the CSharp targets are included
msproject.InsertAfterChild(propertyGroup, lastConfigPropertyGroup)
Dim isDbProject = project.FullName.ToLower().EndsWith(".dbproj")
Dim outputEmpty = propertyGroup.AddProperty("OutputPath", IIf(Not isDbProject, "bin/$(Configuration)/", "sql/$(Configuration)/"))
outputEmpty.Condition = "''$(TeamBuildOutDir)''=='''' "
Dim outputTeamBuild = propertyGroup.AddProperty("OutputPath", "$(TeamBuildOutDir)/$(SolutionName)/$(MSBuildProjectName)/$(Configuration)/")
outputTeamBuild.Condition = "''$(TeamBuildOutDir)''!='''' "
needToSave = True
End If
If needToSave Then
''checkout the project file with tfs
Shell("C:/Program Files/Microsoft Visual Studio 10.0/Common7/IDE/tf.exe checkout " & project.FullName, , True)
''Save the project file
msproject.Save()
End If
End Sub
¡¡¡Espero que esto ayude!!!