program tip

TFS가 각 프로젝트를 자체 디렉터리에 출력하도록하는 가장 좋은 방법은 무엇입니까?

radiobox 2020. 12. 12. 10:22
반응형

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 관련 파일)


여기에 다른 방법을 블로그에 올렸습니다.

http://mikehadlow.blogspot.com/2009/06/tfs-build-publishedwebsites-for-exe-and.html 그러나 링크를 따라갈 수 없다면 여기 전체가 있습니다.

이 패턴 및 관행 PDF, TFS를 사용한 팀 개발 가이드에 설명 된대로 단일 uber 솔루션에서 팀이 제어하는 ​​모든 코드를 수집하는 것이 일반적으로 좋은 방법입니다. 그런 다음이 솔루션을 빌드하도록 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에는 웹 응용 프로그램에만 관련이 있고 다른 프로젝트 유형에서는 제거 할 수있는 많은 항목이 있지만 독자를위한 연습으로 남겨 두겠습니다.


TFS 2012+

이 솔루션이 마음에 듭니다 ...

빌드 정의를 편집하십시오. 프로세스 섹션에서 다음 MSBuild arguments으로 설정 합니다.

/p:GenerateProjectSpecificOutputFolder=true

이렇게 :

여기에 이미지 설명 입력


기본적으로 각 프로젝트 파일 (* .csproj, * .vbproj 등)은 기본 출력 디렉터리 (일반적으로 bin \ Debug, bin \ Release 등)를 지정합니다. Team Build는 실제로 이것을 재정 의하여 개발자가 프로젝트 파일에 설정하는 속성에 대한 변덕이 아니라 Team Build가 출력 위치에 대한 가정을 할 수 있도록합니다.

이 동작을 재정의하는 가장 쉬운 방법은 다음과 같이 SolutionToBuild 항목 그룹에서 CustomizableOutDir를 true로 설정하는 것입니다.

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

이렇게하면 드롭 폴더 구조가 솔루션을 빌드 한 경우 로컬에서 얻을 수있는 것과 거의 일치합니다.

이 방법은 업그레이드 문제를 일으킬 수있는 Core * 대상을 재정의하는 것보다 확실히 바람직합니다.


각 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에서는 작동하지 않습니다.)


I'm a bit late to the party answering this question but there is a very simple way to implement Mike Hadlows answer. Someone has written a nuget package that does exactly what Mike talks about. You can find it here: http://www.nuget.org/packages/PublishedApplications


Update for TFS 2010 (and upcoming TFS 2012). Jason Stangroome has written a nice blog post outlining how to do this.

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

(above link is dead... linking to cached version)

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

Override the TFS Team Build OutDir property

Update: with .NET 4.5 there is an easier way.

A very common complaint from users of Team Foundation Server’s build system is that it changes the folder structure of the project outputs. By default Visual Studio puts all the files in each project’s respective /bin/ or /bin// folder but Team Build just uses a flat folder structure putting all the files in the drop folder root or, again, a // subfolder in the drop folder, with all project outputs mixed together.

Additionally because Team Build achieves this by setting the OutDir property via the MSBuild.exe command-line combined with MSBuild’s property precedence this value cannot easily be changed from within MSBuild itself and the popular solution is to edit the Build Process Template *.xaml file to use a different property name. But I prefer not to touch the Workflow unless absolutely necessary.

Instead, I use both the Solution Before Target and the Inline Task features of MSBuild v4 to override the default implementation of the MSBuild Task used to build the individual projects in the solution. In my alternative implementation, I prevent the OutDir property from being passed through and I pass through a property called PreferredOutDir instead which individual projects can use if desired.

The first part, substituting the OutDir property for the PreferredOutDir property at the solution level is achieved simply by adding a new file to the directory your solution file resides in. This new file should be named following the pattern “before..sln.targets”, eg for a solution file called “Foo.sln” then new file would be “before.Foo.sln.targets”. The contents of this new file should look like this. Make sure this new file gets checked-in to source control.

The second part, letting each project control its output folder structure, is simply a matter of adding a line to the project’s *.csproj or *.vbproj file (depending on the language). Locate the first element inside the project file that doesn’t have a Condition attribute specified, and the locate the corresponding closing tag for this element. Immediately above the closing tag add a line something like this:

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

In this example the project will output to the Team Build drop folder under a subfolder named the same as the project file (without the .csproj extension). You might choose a different pattern. Also, Web projects usually create their own output folder under a _PublishedWebSites subfolder of the Team Build drop folder, to maintain this behaviour just set the OutDir property to equal the PreferredOutDir property exactly.

You can verify if your changes have worked on your local machine before checking in simply by running MSBuild from the command-line and specifying the OutDir property just like Team Build does, eg:

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


For those curious about how this works with TFS 2010, this post has several answers, of which the linked one worked very well for me.


You could have one buildscript per project, that would do exactly what you want. Just create a new TFSBuild file, add the projects you want to have built to the itemgroup(in the order you want them built), set where you want the output to be. This is done by overriding the - property in your TFSBuild file.

But I also agree with the previous poster - why don't you just run with a single build script, and add a zip-task at the end? Maintaining a buildscript per project does add maintenance overhead...


Sling this in a propertygroup:

<CustomizableOutDir>true</CustomizableOutDir>

It'll override the global 'CustomizableOutDir' property which, by default, is set to False. Setting this in the SolutionToBuild's properties will not work.


You achieve this by overriding the default CoreDropBuild target implementation.

In your TFSBuild.proj file (by default stored under TeamBuildTypes/<Build Type>) add the following target:

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

Within this target you can manipulate the output as you want it. The default is to just copy everything from $(BinariesRoot)\$(BuildType) to $(DropLocation)\$(BuildNumber).

나는 일반적으로 파일 복사 기능을 위해 Microsoft.Sdc.Tasks 프로젝트사용합니다 .


간단한 솔루션 :

모든 <SolutionToBuild> 노드를 <SolutionToPublish>로 바꿉니다. 물론 이것은 라이브러리 프로젝트가 아닌 게시 ​​가능한 프로젝트 (예 : 웹 프로젝트 및 응용 프로그램)에서만 작동합니다.

저것과 같이 쉬운 :)

참고 URL : https://stackoverflow.com/questions/698855/whats-the-best-way-to-get-tfs-to-output-each-project-to-its-own-directory

반응형