如何让TFS 2010将每个项目构建到单独的目录中?
在我们的项目中,我们希望让我们的TFS构建将每个项目放到drop文件夹下自己的文件夹中,而不是将所有文件放到一个平面结构中。为了举例说明,我们希望看到如下内容:如何让TFS 2010将每个项目构建到单独的目录中?,tfs,msbuild,tfsbuild,Tfs,Msbuild,Tfsbuild,在我们的项目中,我们希望让我们的TFS构建将每个项目放到drop文件夹下自己的文件夹中,而不是将所有文件放到一个平面结构中。为了举例说明,我们希望看到如下内容: DropFolder/ Foo/ foo.exe Bar/ bar.dll Baz baz.dll 这基本上与我们所问的问题相同,但现在我们使用基于工作流的构建,这些解决方案似乎不起作用。使用CustomizelOutDir属性的解决方案看起来最适合我们,但我无法识别该属性。我自定义了我们的工作流,
DropFolder/
Foo/
foo.exe
Bar/
bar.dll
Baz
baz.dll
这基本上与我们所问的问题相同,但现在我们使用基于工作流的构建,这些解决方案似乎不起作用。使用CustomizelOutDir属性的解决方案看起来最适合我们,但我无法识别该属性。我自定义了我们的工作流,将其作为命令行参数传递给MSBuild(/p:customableoutdir=true),但MSBuild似乎只是忽略了它,并将输出放入工作流给定的OutDir中
我查看了构建日志,可以看到CustomizedLeOutDir和OutDir属性都在命令行参数中设置为MSBuild。我仍然需要传入OutDir,以便在最后将文件复制到TeamBuildOutDir
你知道为什么我的CustomizedLeOutDir参数没有被识别,或者有更好的方法来实现这一点吗?我没有尝试过让TFS/MSBuild将输出文件放在单独的文件夹中,因此无法直接给出答案。然而,以下是我在你的链接中没有发现的几个建议:
- 您可以向将所需文件复制到“部署”结构的项目中添加生成后步骤。(这当然也会在开发人员的机器上运行,这可能是一个难题)。我们对我们的库使用这种方法,这些库被构建,然后复制到一个共享的libs(binaries)文件夹中,供其他项目引用
- 您可以添加MSBuild目标以将所需文件复制到所需的位置。我们已经覆盖了默认的“复制到放置文件夹”目标,将文件复制到另一个文件夹,对其进行模糊处理,对其进行数字签名,将其构建到安装程序中,对安装程序进行数字签名,然后将其(以及其他有用的内容,如模糊映射文件)和自上次构建以来的更改列表复制到放置文件夹。最终,添加您自己的构建后目标可以让您最大限度地控制将什么放在哪里。(不利的一面是,您可能必须手动将任何新的DLL或EXE添加到生成后复制目标,这可能会让人恼火)
- 我想出了一个好办法。事实证明,由于可以在工作流中将OutDir设置为所需的任何值,因此如果将其设置为空字符串,MSBuild将改为使用特定于项目的OutputPath。这让我们更加灵活。以下是我的整个解决方案(基于默认构建工作流):
在运行MSBuild任务中,将OutDir设置为空字符串。在同一任务中,将CommandLineArguments设置为如下所示。这将允许您从项目中引用TFS默认OutDir:
String.Format("/p:CommonOutputPath=""{0}\\""", outputDirectory)
在每个要复制到drop文件夹的项目中,按如下方式设置OutputPath:
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<OutputPath Condition=" '$(CommonOutputPath)'=='' ">bin\Release\</OutputPath>
<OutputPath Condition=" '$(CommonOutputPath)'!='' ">$(CommonOutputPath)YourProjectName\bin\Release\</OutputPath>
</PropertyGroup>
bin\Release\
$(CommonOutputPath)YourProjectName\bin\Release\
签入所有内容,您应该有一个工作版本,可以将您的每个项目部署到drop文件夹下自己的文件夹中。我们必须这样做,以绕过一个问题,即我们有一个Silverlight和一个用于CSLA序列化的同名.Net库。库将被覆盖,我们的测试将失败 我使用了乔纳森的答案,但是我发现你也需要设置为空 因此,您需要为MSBuild活动执行这些参数(如果使用以下宏,则还需要为Clean设置活动参数,否则会收到未设置OutputPath的警告):
- 将CommandLineArguments设置为
String.Format(“/p:skipinValidConfiguration=true;TeamBuildOutDir=”“{0}”“{1}”,二进制目录,MSBuildArguments)
- 将OutDir设置为空(was二进制目录)
<PropertyGroup Label="OutputPathLabel">
<OutputPath Condition="'$(TeamBuildOutDir)'=='' ">bin\$(Configuration)\</OutputPath>
<OutputPath Condition="'$(TeamBuildOutDir)'!='' ">$(TeamBuildOutDir)\$(SolutionName)\$(MSBuildProjectName)\$(Configuration)\</OutputPath>
</PropertyGroup>
希望这有帮助 这里的步骤不需要修改项目文件-我也解决了这个问题,我认为它比这个线程上现有的解决方案更干净
- 在
活动之前,我添加了一个为Project运行MSBuild
活动:Assign
李>projectName=Regex.Replace(新文件信息(localProject).Name,\.sln$,“”)
- 接下来,我添加了一个
活动:Create Directory
outputDirectory+“\”+projectName
- 最后,在MSBuild活动中,我将
更改为OutDir
李>outputDirectory+“\”+projectName
.sln
文件的完整路径名填充localProject
,例如c:\build\path\to\MySolution.sln
。分配活动切断路径和扩展,将输出放在MySolution
中。您需要创建projectName
变量,并导入System.Text.RegularExpressions
和System.IO
与OP的解决方案相比,它的优点是您不必编辑每个
.csproj
,这些信息是从解决方案文件的名称推断出来的 这里有一个非常简单的解决方案,它不需要修改源文件或项目文件。设置生成定义的过程->要生成的项目时,不要在要生成的项目中指定.sln文件,而是添加每个项目(.csproj或.vbproj)。现在,在工作流的“为项目运行MSBuild”步骤中,将OutDir属性更改为以下内容:
outputDirectory + "/" + serverBuildProjectItem.Substring(serverBuildProjectItem.LastIndexOf("/"), serverBuildProjectItem.Length - serverBuildProjectItem.LastIndexOf("/")).Replace(".csproj", String.Empty)
OutputDirectory + "\" + System.IO.Path.GetFileNameWithoutExtension(serverBuildProjectItem)
这将把每个项目的生成输出放在以项目命名的子目录中。下面是另一个非常简单的解决方案,它不需要修改源文件或项目
OutputDirectory + "\" + System.IO.Path.GetFileNameWithoutExtension(serverBuildProjectItem)