Какой лучший способ получить TFS для вывода каждого проекта в свой собственный каталог?

Я помещаю большую базу кода в Team Foundation Server. Я хотел бы, чтобы процесс сборки создавал сборку "готовых к развертыванию" наших проектов.

Обычный способ, которым мы это выполняем, состоит в том, чтобы каждый выход проекта находился в своей собственной папке. Так, например, мы завершаем что-то вроде

C:\project1\
            assembly1.dll
            assembly2.dll
            project1.exe
            project1.exe.config
C:\project2\
            assembly2.dll
            assembly3.dll
            project2.exe
            project2.exe.config
C:\project3\
            assembly1.dll
            assembly3.dll
            project3.exe
            project3.exe.config

Каким образом нам это нравится.

TFS, однако, похоже, хочет вставить все в один каталог.

C:\output\
          assembly1.dll
          assembly2.dll
          assembly3.dll
          project1.exe
          project1.exe.config
          project2.exe
          project2.exe.config
          project3.exe
          project3.exe.config

который, хотя и сохраняет некоторый объем дискового пространства (сборки существуют только один раз каждый), не так, как мы этого хотим.

Какой лучший способ указать, где TFS/MSBuild должен поместить выходные файлы? Нужно ли мне редактировать файлы sln/csproj индивидуально для достижения этого или я могу сделать это в файле TFSBuild.proj? (то есть в файле MSBuild)

Ответ 1

Я просто добавил в блог другой метод:

http://mikehadlow.blogspot.com/2009/06/tfs-build-publishedwebsites-for-exe-and.html но если вы не можете потрудиться по ссылке, здесь она полностью:

В целом хорошая практика - собрать весь код под командованием вашей команды в одном uber-решении, как описано в этом Паттерне и практике PDF, Team Development с TFS Guide. Если вы затем сконфигурируете сервер сборки TFS для создания этого решения, его поведение по умолчанию заключается в том, чтобы вывести вывод сборки в одну папку "Release".

Любые проекты веб-приложений в вашем решении также будут выводиться в папку с именем _PublishedWebsites \. Это очень приятно, потому что это означает, что вы можете просто robocopy развернуть веб-приложение.

К сожалению, для других типов проектов, таких как WinForms, консоль или библиотека, не наблюдается аналогичного поведения по умолчанию. Было бы очень приятно, если бы у нас была папка _PublishedApplications\sub с выходом любого выбранного проекта (ов). К счастью, это не так сложно сделать.

Путь _PublishedWebsites работает довольно просто. Если вы посмотрите на файл проекта вашего веб-приложения, вы увидите импорт в нижней части:

<Import Project="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v9.0\WebApplications\Microsoft.WebApplication.targets" />

На моей машине свойство MSBuildExtensionsPath оценивается в C:\Program Files\MSBuild, если мы открываем файл Microsoft.WebApplication.targets, мы можем видеть, что его довольно простой файл MSBuild, который распознает, когда сборка не является сборкой рабочего стола, т.е. его сборку TFS, и копирует вывод на:

$(OutDir)_PublishedWebsites\$(MSBuildProjectName)

Я просто скопировал файл Micrsoft.WebApplication.targets, поместил его под контроль источника с относительным путем из моих файлов проекта и изменил _PublishedWebsites на _PublishedApplications и переименовал файл CI.exe.targets. Для каждого проекта, который я хочу вывести на _PublishedApplications, я просто добавил этот импорт в нижней части файла проекта:

<Import Project="<your relative path>\CI.exe.targets" />

Вы можете отредактировать CI.exe.targets(или все, что вы хотите назвать), чтобы выполнить ваши ставки. В моем случае единственное изменение до сих пор заключается в том, чтобы добавить пару строк для копирования файла App.config:

<Copy SourceFiles="$(OutDir)$(TargetFileName).config" DestinationFolder="$(WebProjectOutputDir)\bin" SkipUnchangedFiles="true" />

Theres много материала в Microsoft.WebApplication.targets, что касается только веб-приложений и может быть удалено для других типов проектов, но я оставляю это как упражнение для читателя.

Ответ 2

TFS 2012 +

Мне нравится это решение...

Измените определение сборки. В разделе "Процесс" установите MSBuild arguments в

/p:GenerateProjectSpecificOutputFolder=true

Вот так:

enter image description here

Ответ 3

По умолчанию каждый файл проекта (*.csproj, *.vbproj и т.д.) указывает выходной каталог по умолчанию (обычно это bin\Debug, bin\Release и т.д.). Team Build на самом деле отменяет это, так что вы не склонны к какому-либо приложению, которое разработчик устанавливает в файле проекта, а также для того, чтобы Team Build могла делать предположения о том, где находятся выходы.

Самый простой способ переопределить это поведение - установить CustomizableOutDir в true в группе элементов SolutionToBuild, как показано ниже:

<ItemGroup>
  <SolutionToBuild Include="$(BuildProjectFolderPath)\path\MySolution.sln" />
    <Properties>CustomizableOutDir=true</Properties>
  </SolutionToBuild>
</ItemGroup>

Это приведет к тому, что структура папок-папок будет примерно соответствовать тому, что вы получите локально, если вы построите решение.

Этот метод определенно предпочтительнее переопределять цели Core *, которые могут вызвать проблемы с обновлением.

Ответ 4

Для каждого SolutionToBuild node установите свойство OutDir в значение $(OutDir)\SubFolder
Например:

  <ItemGroup>
   <SolutionToBuild Include="Project1.sln" >
    <Properties>OutDir=$(OutDir)\Project1\</Properties>      
   </SolutionToBuild>
   <SolutionToBuild Include="Project2.sln" >
    <Properties>OutDir=$(OutDir)\Project2\</Properties>      
   </SolutionToBuild>
   <SolutionToBuild Include="Project3.sln" >
    <Properties>OutDir=$(OutDir)\Project3\</Properties>      
   </SolutionToBuild>
  <ItemGroup>

(Это работает в TF2008, но не TF2005.)

Ответ 5

Обновление для TFS 2010 (и предстоящей TFS 2012). Джейсон Стэнроум написал хороший блог, излагающий, как это сделать.

http://blog.codeassassin.com/2012/02/03/override-the-tfs-team-build-outdir-property/

(выше ссылка мертва... ссылка на кешированную версию)

https://webcache.googleusercontent.com/search?q=cache:4rKu4oB3TwcJ:blog.stangroome.com/2012/02/03/override-the-tfs-team-build-outdir-property/+&cd=1&hl=en&ct=clnk&gl=ca

Переопределить свойство сборки OutDir Team Team TFS

Обновление: с .NET 4.5 существует более простой способ.

Очень распространенная жалоба пользователей системы сборки Team Foundation Servers заключается в том, что она изменяет структуру папок результатов проекта. По умолчанию Visual Studio помещает все файлы в каждую соответствующую/bin/или/bin//папку, но Team Build просто использует плоскую структуру папок, помещая все файлы в корневой каталог папок или, опять же,//подпапку в drop папка со всеми выходами проекта, смешанными вместе.

Кроме того, поскольку Team Build достигает этого, установив свойство OutDir через командную строку MSBuild.exe в сочетании с приоритетом свойств MSBuilds, это значение не может быть легко быть изменено из самого MSBuild, а популярное решение - отредактировать шаблон сборки процесса *.xaml для использования другого имени свойства. Но я предпочитаю не прикасаться к Workflow, если это абсолютно необходимо.

Вместо этого я использую как решение до цели, так и функции встроенной задачи MSBuild v4, чтобы переопределить реализацию MSBuild по умолчанию, используемую для создания отдельных проектов в решении. В моей альтернативной реализации я предотвращаю передачу свойства OutDir и передаю свойство PreferredOutDir вместо этого, какие отдельные проекты могут использовать при желании.

Первая часть, заменяющая свойство OutDir свойства PreferredOutDir на уровне решения, достигается просто путем добавления нового файла в каталог, в котором находится ваш файл решения. Этот новый файл должен быть назван в соответствии с шаблоном "before..sln.targets", например, для файла решения под названием "Foo.sln", тогда новый файл будет "before.Foo.sln.targets". Содержимое этого нового файла должно выглядеть следующим образом. Убедитесь, что этот новый файл установлен в исходное состояние.

Вторая часть, позволяющая каждому проекту управлять структурой выходных папок, - это просто вопрос добавления строки к файлам проектов *.csproj или *.vbproj(в зависимости от языка). Найдите первый элемент внутри файла проекта, который не имеет указанного атрибута Condition, и найдите соответствующий закрывающий тег для этого элемента. Непосредственно над закрывающим тегом добавьте строку примерно так:

<OutDir Condition=" '$(PreferredOutDir)' != '' ">$(PreferredOutDir)$(MSBuildProjectName)\</OutDir>

В этом примере проект будет выводиться в раскрывающуюся папку Team Build под подпапкой с именем так же, как файл проекта (без расширения .csproj). Вы можете выбрать другой шаблон. Кроме того, веб-проекты обычно создают свою собственную папку вывода под вложенной папкой _PublishedWebSites в раскрывающемся списке Team Build, чтобы поддерживать это поведение, просто установите свойство OutDir равным свойству PreferredOutDir.

Вы можете проверить, работали ли ваши изменения на вашем локальном компьютере, прежде чем проверять его просто, запустив MSBuild из командной строки и указав свойство OutDir так же, как Team Build, например:

msbuild Foo.sln /p:OutDir=c:\TestDropFolder\

Ответ 6

Я немного опоздал, чтобы партия ответила на этот вопрос, но есть очень простой способ реализовать ответ Майка Хэдлоуза. Кто-то написал пакет nuget, который делает именно то, о чем говорит Майк. Вы можете найти его здесь: http://www.nuget.org/packages/PublishedApplications

Ответ 7

Для тех, кто интересуется тем, как это работает с TFS 2010, этот столбец имеет несколько ответов, из которых связанный для меня работал очень хорошо.

Ответ 8

У вас может быть один buildscript для каждого проекта, который будет делать именно то, что вы хотите. Просто создайте новый файл TFSBuild, добавьте проекты, которые вы хотите создать в группу элементов (в том порядке, в котором вы их построили), установите, где вы хотите, чтобы это было. Это делается путем переопределения свойства - в файле TFSBuild.

Но я также согласен с предыдущим плакатом - почему бы вам просто не запустить с помощью единой сборки script и добавить zip-задачу в конце? Поддержание сборки для каждого проекта добавляет служебные расходы...

Ответ 9

Строка этого в группе свойств:

<CustomizableOutDir>true</CustomizableOutDir>

Он переопределит глобальное свойство "CustomizableOutDir", которое по умолчанию установлено на False. Установка этого параметра в свойствах SolutionToBuild не будет работать.

Ответ 10

Вы достигаете этого, переопределяя целевую реализацию CoreDropBuild по умолчанию.

В вашем файле TFSBuild.proj(по умолчанию хранятся в TeamBuildTypes/< Тип сборки > ) добавьте следующую цель:

    <!-- Override default implementation -->
    <Target 
       Name="CoreDropBuild"
       Condition=" '$(SkipDropBuild)'!='true' and '$(IsDesktopBuild)'!='true' "
       DependsOnTargets="$(CoreDropBuildDependsOn)">
...
    </Target>

Внутри этой цели вы можете манипулировать выходом так, как хотите. По умолчанию нужно просто скопировать все из $(BinariesRoot)\$(BuildType) в $(DropLocation)\$(BuildNumber).

Обычно я использую проект Microsoft.Sdc.Tasks для возможности копирования файлов.

Ответ 11

Простое решение:

Заменить все <SolutionToBuild> узлы с <SolutionToPublish> . Это, конечно же, будет работать только для опубликованных проектов (например, веб-проектов и приложений), а не для проектов библиотек.

Проще всего:)