Каков наилучший способ заставить TFS выводить каждый проект в отдельную директорию? - PullRequest
58 голосов
/ 31 марта 2009

Я помещаю большую кодовую базу в 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)

Ответы [ 11 ]

44 голосов
/ 12 июня 2009

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

http://mikehadlow.blogspot.com/2009/06/tfs-build-publishedwebsites-for-exe-and.html но если вы не можете перейти по ссылке, вот она в полном объеме:

Как правило, рекомендуется собирать весь код под управлением вашей команды в одно решение Uber, как описано в этом документе «Шаблоны и практики», PDF, Руководство по разработке команд с TFS. Если вы затем сконфигурируете сервер сборки TFS для сборки этого решения, то по умолчанию будет размещаться вывод сборки в одну папку, «Release».

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

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

Принцип работы _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" />

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

35 голосов
/ 08 мая 2014

TFS 2012 +

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

Отредактируйте определение вашей сборки. В разделе «Процесс» установите MSBuild arguments на

/p:GenerateProjectSpecificOutputFolder=true

Как это:

enter image description here

10 голосов
/ 12 июня 2009

По умолчанию каждый файл проекта (* .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 *, которые могут вызвать проблемы с обновлением.

6 голосов
/ 01 мая 2009

Для каждого узла SolutionToBuild установите для свойства 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 голосов
/ 05 октября 2012

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

4 голосов
/ 09 июля 2012

Обновление для 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

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

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

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

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

Вместо этого я использую функции Solution Before Target и Inline Task в 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\

1 голос
/ 06 декабря 2011

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

0 голосов
/ 08 июля 2010

Слинг это в группу недвижимости:

<CustomizableOutDir>true</CustomizableOutDir>

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

0 голосов
/ 07 апреля 2009

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

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

Все так просто:)

0 голосов
/ 06 апреля 2009

Этого можно добиться, переопределив целевую реализацию 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 для возможностей копирования файлов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...