如何使用 MSBuild 为每个项目的每个构建配置提供不同的 OutputPath?

Posted

技术标签:

【中文标题】如何使用 MSBuild 为每个项目的每个构建配置提供不同的 OutputPath?【英文标题】:How to give a different OutputPath per project per build configuration with MSBuild? 【发布时间】:2012-01-06 12:46:25 【问题描述】:

必须使用一种或多种配置(调试/发布/...)构建多个项目。

需要将构建的输出复制到一个文件夹 (BuildOutputPath)。 有一个默认的 BuildOutputFolder,但对于某些项目,您可以指示输出需要放在一个额外的子文件夹中。

例如:

配置如下: - 调试 - 发布

项目是:

Project1 (BuildOutputFolder) Project2 (BuildOutputFolder) Project3 (BuildOutputFolder\Child)

最终结果应该是这样的:

\\BuildOutput\
     debug\
         project1.dll
         project2.dll
         Child\
               Project3.dll
     release\
         project1.dll
         project2.dll
         Child\
              Project3.dll

我得到了这么远的 atm,但不知道如何覆盖每个项目的 OutputPath。

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0" DefaultTargets="Build" >
  <ItemGroup>
    <ConfigList Include="Debug" />
    <ConfigList Include="Release" />
   </ItemGroup>  

  <PropertyGroup>
    <BuildOutputPath>$(MSBuildProjectDirectory)\BuildOutput\</BuildOutputPath>
  </PropertyGroup>

  <ItemGroup>
    <Projects Include="project1.csproj" />
    <Projects Include="project2.csproj" />
    <Projects Include="project3.csproj" />
  </ItemGroup>

  <Target Name="Build">
    <MSBuild Projects="@(Projects)"
             BuildInParallel="true"
             Properties="Configuration=%(ConfigList.Identity);OutputPath=$(BuildOutputPath)%(ConfigList.Identity)" />

  </Target>
</Project>

您将如何在 MSBuild 项目文件中完成此操作?

【问题讨论】:

【参考方案1】:

您尝试在两种不同的上下文中递归调用任务。 2 个配置和 3 个项目需要 6 次调用构建任务。您需要对项目进行布局,使ConfigList 中的每个项目的调用乘以Projects 中的每个项目。

还可以使用ItemDefinitionGroup 设置默认共享属性:

  <ItemGroup>
    <ConfigList Include="Debug" />
    <ConfigList Include="Release" />
  </ItemGroup>

   <ItemDefinitionGroup>
    <Projects>
      <BuildOutputPath>$(MSBuildProjectDirectory)\BuildOutput\</BuildOutputPath>
    </Projects>
  </ItemDefinitionGroup>

  <ItemGroup>
    <Projects Include="project1.csproj" />
    <Projects Include="project2.csproj" />
    <Projects Include="project3.csproj" >
      <Subfolder>Child</Subfolder>
    </Projects>
  </ItemGroup>

  <Target Name="Build">

    <MSBuild Projects="$(MSBuildProjectFullPath)"
             Targets="_BuildSingleConfiguration"
             Properties="Configuration=%(ConfigList.Identity)" />

  </Target>

  <Target Name="_BuildSingleConfiguration">

    <MSBuild Projects="@(Projects)"
             BuildInParallel="true"
             Properties="Configuration=$(Configuration);OutputPath=%(Projects.BuildOutputPath)$(Configuration)\%(Projects.Subfolder)" />
  </Target>

</Project>

【讨论】:

【参考方案2】:

尝试使用项目元数据来实现

<ItemGroup>
    <Projects Include="project1.csproj">
       <ChildFolder/>
    </Project>
    <Projects Include="project2.csproj">
       <ChildFolder/>
    </Project>
    <Projects Include="project3.csproj">
       <ChildFolder>Child</ChildFolder>
    </Project>
  </ItemGroup>

  <Target Name="Build">
    <MSBuild Projects="@(Projects)"
         BuildInParallel="true"
         Properties="Configuration=%(ConfigList.Identity);OutputPath=$(BuildOutputPath)%(ConfigList.Identity)%(Project.ChildFolder)" />

【讨论】:

我试过了,但是当我将项目元数据放入 MSBuild 属性时,%ConfigList.Identity 被忽略了。

以上是关于如何使用 MSBuild 为每个项目的每个构建配置提供不同的 OutputPath?的主要内容,如果未能解决你的问题,请参考以下文章

如何在文件夹中构建所有解决方案的所有项目?

使用 Msbuild 和 devenv 在项目解决方案下构建特定的 Visual Studio 项目

MSBuild,构建不同配置的依赖项目

MSBuild:是不是可以在实际项目文件中指定项目构建依赖项?

如何解决以下 xmlns MSBuild 错误?

如何配置 Hudson 为每个构建发送电子邮件,而不仅仅是那些改变项目状态的?