Как мне получить TFS 2010 для сборки каждого проекта в отдельный каталог?
В нашем проекте мы хотели бы, чтобы наша сборка TFS помещала каждый проект в отдельную папку в папке drop, вместо того, чтобы помещать все файлы в одну плоскую структуру. Чтобы проиллюстрировать это, мы хотели бы увидеть что-то вроде этого:
DropFolder/
Foo/
foo.exe
Bar/
bar.dll
Baz
baz.dll
По сути, это тот же вопрос, который был задан здесь, но теперь, когда мы используем сборки на основе рабочих процессов, кажется, что эти решения не работают. Решение, использующее свойство CustomizableOutDir, выглядело так, как будто оно будет работать лучше для нас, но я не могу распознать это свойство. Я настроил наш рабочий процесс для передачи его в MSBuild в качестве аргумента командной строки (/p:CustomizableOutDir=true), но кажется, что MSBuild просто игнорирует его и помещает выходные данные в OutDir, заданный рабочим процессом.
Я просмотрел журналы сборки и вижу, что свойства CustomizableOutDir и OutDir в аргументах командной строки устанавливаются как MSBuild. Мне все еще нужно передать OutDir, чтобы в конце я смог скопировать свои файлы в TeamBuildOutDir.
Любая идея, почему мой параметр CustomizableOutDir не распознается, или есть лучший способ добиться этого?
9 ответов
Я нашел хороший способ сделать это. Оказывается, так как вы можете установить OutDir в любое удобное для вас значение в рабочем процессе, если вы установите его в пустую строку, MSBuild вместо этого будет использовать выходной путь для конкретного проекта. Это позволяет нам быть более гибкими. Вот мое полное решение (основанное на рабочем процессе сборки по умолчанию):
В задаче "Выполнить MSBuild" установите для OutDir пустую строку. В этой же задаче установите для ваших CommandLineArguments что-то вроде следующего. Это позволит вам иметь ссылку на OutDir TFS по умолчанию из вашего проекта:
String.Format("/p:CommonOutputPath=""{0}\\""", outputDirectory)
В каждом проекте, который вы хотите скопировать в папку удаления, установите OutputPath следующим образом:
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<OutputPath Condition=" '$(CommonOutputPath)'=='' ">bin\Release\</OutputPath>
<OutputPath Condition=" '$(CommonOutputPath)'!='' ">$(CommonOutputPath)YourProjectName\bin\Release\</OutputPath>
</PropertyGroup>
Проверьте все, и у вас должна быть рабочая сборка, которая развертывает каждый из ваших проектов в своей папке в папке drop.
Я тоже решил эту проблему и считаю, что она чище, чем существующие решения в этой теме.
- Перед
Run MSBuild for Project
активность, я добавилAssign
деятельность:projectName = Regex.Replace(New FileInfo(localProject).Name, "\.sln$", "")
, - Затем я добавил
Create Directory
деятельность:outputDirectory + "\" + projectName
- Наконец в деятельности MSBuild я изменился
OutDir
вoutputDirectory + "\" + projectName
,
Шаблон уже заполняется localProject
с полным именем пути .sln
файл строится на Агенте, например, c:\build\path\to\MySolution.sln
, Деятельность по назначению отсекает путь и расширение, помещая вывод в MySolution
, Вам нужно будет создать projectName
переменная и импорт System.Text.RegularExpressions
а также System.IO
,
Преимущество решения OP в том, что вам не нужно редактировать каждый .csproj
, эта информация выводится из имени файла решения.
Мы должны были сделать это, чтобы обойти проблему, когда у нас есть Silverlight и библиотека.Net с тем же именем для сериализации CSLA. Библиотека будет перезаписана, и наши тесты не пройдут.
Я использовал ответ Джонатана и пост Джима Лэмба, но я обнаружил, что вам также нужно установить OutDir пустым.
Таким образом, вам нужно выполнить эти параметры для действий MSBuild (если вы используете следующий макрос, вам также нужно установить параметры действий для Clean, в противном случае вы получите предупреждение о том, что OutputPath не установлен):
- Установите CommandLineArguments в
String.Format("/p:SkipInvalidConfigurations=true;TeamBuildOutDir=""{0}"" {1}", BinariesDirectory, MSBuildArguments)
- Установите OutDir пустым (был BinariesDirectory)
Я также создал макрос, который вы можете запустить в Visual Studio, который удаляет OutputPath из конфигураций и добавляет PropertyGroup, которая содержит OutputPath для всех конфигов, например:
<PropertyGroup Label="OutputPathLabel">
<OutputPath Condition="'$(TeamBuildOutDir)'=='' ">bin\$(Configuration)\</OutputPath>
<OutputPath Condition="'$(TeamBuildOutDir)'!='' ">$(TeamBuildOutDir)\$(SolutionName)\$(MSBuildProjectName)\$(Configuration)\</OutputPath>
</PropertyGroup>
Вот макрос:
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
Надеюсь это поможет!!!
Эти шаги не требуют изменения файла проекта - http://lajak.wordpress.com/2011/05/07/customize-binaries-folder-in-tfs-team-build/
Не уверен, что вы все еще можете заставить Team build 2010 использовать самую последнюю версию msbuild, но есть новое свойство /p:GenerateProjectSpecificOutputFolder=true, если указано, биты будут сброшены в $(OutDir)\$(ProjectName)\ для каждого проекта.
Я установил пакет Опубликованные приложения из Nuget для каждого исполняемого файла в Моем решении, и он создал подпапки в папке _PublishedApplications для каждого проекта во время сборки.
Вот очень простое решение, которое не требует модификации исходных файлов или файлов проекта. При настройке определения сборки "Процесс -> Проекты для сборки" вместо указания файла.sln в проектах для сборки добавьте каждый проект (.csproj или.vbproj). Теперь внутри шага "Запуск MSBuild for Project" вашего рабочего процесса измените свойство OutDir на следующее:
outputDirectory + "/" + serverBuildProjectItem.Substring(serverBuildProjectItem.LastIndexOf("/"), serverBuildProjectItem.Length - serverBuildProjectItem.LastIndexOf("/")).Replace(".csproj", String.Empty)
Это поместит выходные данные сборки каждого проекта в подкаталог с именем проекта.
Вот еще одно очень простое решение, которое не требует модификации исходных файлов или файлов проекта. При настройке определения сборки "Процесс -> Проекты для сборки" вместо указания файла.sln в проектах для сборки добавьте каждый проект (.csproj или.vbproj). Теперь внутри шага "Запуск MSBuild for Project" вашего рабочего процесса измените свойство OutDir на следующее:
OutputDirectory + "\" + System.IO.Path.GetFileNameWithoutExtension(serverBuildProjectItem)
Я не играл с TFS/MSBuild, чтобы поместить выходные файлы в отдельные папки, поэтому не могу дать прямой ответ. Однако вот несколько предложений, которые я не заметил в вашей ссылке:
Вы можете добавить шаги после сборки к проектам, которые копируют необходимые файлы в структуру "развертывания". (Это, конечно, также работает на машинах разработчиков, что может быть проблемой). Мы используем этот подход для наших библиотек, которые создаются и затем копируются в общую папку libs (binaries), в которую другие проекты могут ссылаться.
Вы можете добавить цель MSBuild, чтобы скопировать нужные файлы туда, куда вы хотите. Мы переопределили цели по умолчанию "копировать в папку", чтобы скопировать файлы в другую папку, скрыть их, подписать их цифровой подписью, встроить в установщик, подписать установщик цифровой подписью, а затем скопировать (и другие полезные вещи, такие как файлы карт обфускации) и список изменений с момента последней сборки в папку drop. В конечном итоге добавление вашей собственной цели после сборки дает вам максимальный контроль над тем, что и где находится. (С минусовой стороны, вам, возможно, придется вручную добавлять любые новые dll или exe-файлы к цели копирования после сборки, что может вызвать раздражение)