使用MSBuild生成多个配置

使用MSBuild生成多个配置,msbuild,msbuild-task,buildconfiguration,Msbuild,Msbuild Task,Buildconfiguration,我正在尝试编辑我的项目文件,使我能够拥有一个同时构建多个构建配置的项目。我使用批处理方法和MSBuild任务(见下文)完成了这项工作 如果我运行脚本,我会收到一个错误消息: 错误103 OutputPath属性为 未为项目设置 “ThisMSBuildProjectFile.csproj”。 请检查以确保您 已指定以下项的有效组合: 配置和平台 项目配置=“调试” 平台='AnyCPU' 如果我在MSBuild任务中添加或省略OutputPath,就会得到这个结果。如果使用VS2010调试器单步

我正在尝试编辑我的项目文件,使我能够拥有一个同时构建多个构建配置的项目。我使用批处理方法和MSBuild任务(见下文)完成了这项工作

如果我运行脚本,我会收到一个错误消息:

错误103 OutputPath属性为 未为项目设置 “ThisMSBuildProjectFile.csproj”。 请检查以确保您 已指定以下项的有效组合: 配置和平台 项目配置=“调试” 平台='AnyCPU'

如果我在MSBuild任务中添加或省略OutputPath,就会得到这个结果。如果使用VS2010调试器单步执行脚本并调用MSBuild任务,调试器将再次单步执行该文件,然后单步执行OutputPath,那么如果确定,它将拾取该值,否

如果能帮上忙,我将不胜感激——这让我快发疯了。谢谢你,保罗

ThisMSBuildProjectFile.csproj(取出多余的内容):


pdbonly
真的
C:\Folder\Etc\Output\$(配置)\
C:\Folder\Etc\Output\$(配置)\
C:\Folder\Etc\Output\$(配置)\
痕迹
促使
4.
任意CPU

您的项目文件中存在某些错误。考虑这个XML:

<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == '' ">
  <DebugType>pdbonly</DebugType>
  <Optimize>true</Optimize>
  <OutputPath>C:\Folder\Etc\Output\$(Configuration)\</OutputPath> 
  ...
</PropertyGroup>

pdbonly
真的
C:\Folder\Etc\Output\$(配置)\
...
这些属性永远无法设置,因为即使$(配置)和$(平台)为空,当与条形字符关联时,它们也永远无法匹配空字符串;该条件的最小值为“|”,而不是“”。即使通过将条件与“|”进行比较来更正,您也可以继续尝试在该PropertyGroup的OutputPath中使用$(配置),但是$(配置)在使用时永远不会有值。同样,如果您尝试将$(平台)设置为“AnyCPU”,则它必须已经具有该值。您可能打算完全忽略第一个PropertyGroup上的条件,并且可能需要在早期PropertyGroup中为$(配置)和$(平台)提供默认值,而不带任何条件。将你的整个项目与一个新项目进行比较,看看是否还有其他类似的奇怪之处


还要注意,在重写“Build”目标时,MSBuild任务上有一个冗余条件;使用相同的条件时,您不需要在任何任务中使用它。

重要的是,当您使用“MSBuild”任务时,将启动一个新的子MSBuild进程。这意味着您在父MSBuild进程中定义的任何项和属性都不会自动传递给子MSBuild进程或从子MSBuild进程中可见,除非您通过
MSBuild
元素上的
属性明确传递它们(如

为了回答您的问题,我编写了以下自包含示例,该示例为所有指定的配置运行子MSBuild项目:

C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319\msbuild main.proj /property:Config=Debug+Release+Staging+Production
> (cut the noise)
> Build:
>   Building configuration Debug with output path C:\temp_c\d\bin\Debug
> Build:
>   Building configuration Release with output path C:\temp_c\d\bin\Release
> Build:
>   Building configuration Staging with output path C:\temp_c\d\bin\Staging
> Build:
>   Building configuration Production with output path C:\temp_c\d\bin\Production
  • 首先,为MSBuild实验创建一个目录(例如,我使用了
    C:\temp\msbuildtest

  • 在此目录中,创建第一个文件,
    main.proj

    <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="Build" ToolsVersion="4.0">
        <ItemGroup>
            <ConfigList Condition=" '@(ConfigList)' == '' and $(Config) != '' " Include="$(Config.Split('+'))" /><!-- parse all requested configurations into a list -->
            <ConfigList Condition=" '@(ConfigList)' == '' " Include="Debug" /><!-- if no configurations were specified, default to Debug -->
        </ItemGroup>
        <!--
    
        Build the child project for each requested configuration. -->
        <Target Name="Build">
            <MSBuild Projects="$(MSBuildProjectDirectory)\child.proj" Properties="Configuration=%(ConfigList.Identity);OutputPath=$(MSBuildProjectDirectory)\bin\%(ConfigList.Identity)" Targets="Build" />
        </Target>
    </Project>
    
  • 现在您可以运行该示例了。首先是默认值,如果未明确指定要生成的配置:

    C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319\msbuild main.proj
    > (cut the noise)
    > Build:
    >   Building configuration Debug with output path C:\temp_c\d\bin\Debug
    
    然后明确指定多个配置:

    C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319\msbuild main.proj /property:Config=Debug+Release+Staging+Production
    > (cut the noise)
    > Build:
    >   Building configuration Debug with output path C:\temp_c\d\bin\Debug
    > Build:
    >   Building configuration Release with output path C:\temp_c\d\bin\Release
    > Build:
    >   Building configuration Staging with output path C:\temp_c\d\bin\Staging
    > Build:
    >   Building configuration Production with output path C:\temp_c\d\bin\Production
    

  • 您应该能够根据自己的情况调整此技术。

    我不太确定是否需要对项目的csproj文件本身进行如此复杂的配置。我更愿意设置一个单独的MSBuild“buildtweet.proj”文件,该文件具有一个名为“Both”的特定目标,该目标在两种配置中构建解决方案

    <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="Both">
    
        <!-- Calls twice for both configs -->
        <Target Name="Both">
            <MSBuild Projects="buildboth.sln" Targets="Rebuild" Properties="Configuration=Debug"
                             StopOnFirstFailure="true">
            </MSBuild>
    
            <MSBuild Projects="buildboth.sln" Targets="Rebuild" Properties="Configuration=Release"
                             StopOnFirstFailure="true">
            </MSBuild>
        </Target>
    
        <!-- single config targets
    
        <Target Name="Debug">
            <MSBuild Projects="buildboth.sln" Targets="Rebuild" Properties="Configuration=Debug"
                             StopOnFirstFailure="true">
            </MSBuild>
        </Target>
    
        <Target Name="Release">
            <MSBuild Projects="buildboth.sln" Targets="Rebuild" Properties="Configuration=Release"
                             StopOnFirstFailure="true">
            </MSBuild>
        </Target>
        -->
    
    </Project>
    

    您好-谢谢,我意识到我可以有一个独立的项目,但这个想法是让团队成员都能够从VS中推送构建,而不是炮轰出来-我希望最小限度地修改标准CSProj文件,以使团队的其他成员能够这样做。当然,这是因为它来自标准的CSProj文件,如果没有指定配置,这是一个后备方案。我意识到在我给出的示例中不会命中它,但在使用MSBuild调试器时,其他条件组按预期命中。感谢您指出子节点上的重复!也许你没有领会我的意思,这根本不是一个退步,条件的编码方式永远不会计算为真,因为左手边总是包含至少一个“|”,右手边总是空的,它们永远不可能相等。太好了,谢谢你,这不正是我想要的(因为我想尽量减少对标准CSProj文件的更改),但看起来我想得太多了。我现在就采用这种方法。谢谢,这种技术被称为“任务批处理”。有很多方法可以进行批处理,易卜拉欣·哈希米在他的书中介绍了这些方法“在微软构建引擎中:使用MSBudio和Team Foundation Bube”“重要的是要意识到,当使用“MSBug”任务时,将启动一个新的子MSBug进程。“这不是真的。”根据:“不同于使用Excel任务启动MSBuild.exe,这个任务使用相同的MSBug进程来构建子项目。“这也符合我自己的经验。@MilianGardian“And”和“And”之间有区别吗?”@Radu我认为逻辑运算符不区分大小写,但我从未尝试过大写变体:-)。
    <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="Both">
    
        <!-- Calls twice for both configs -->
        <Target Name="Both">
            <MSBuild Projects="buildboth.sln" Targets="Rebuild" Properties="Configuration=Debug"
                             StopOnFirstFailure="true">
            </MSBuild>
    
            <MSBuild Projects="buildboth.sln" Targets="Rebuild" Properties="Configuration=Release"
                             StopOnFirstFailure="true">
            </MSBuild>
        </Target>
    
        <!-- single config targets
    
        <Target Name="Debug">
            <MSBuild Projects="buildboth.sln" Targets="Rebuild" Properties="Configuration=Debug"
                             StopOnFirstFailure="true">
            </MSBuild>
        </Target>
    
        <Target Name="Release">
            <MSBuild Projects="buildboth.sln" Targets="Rebuild" Properties="Configuration=Release"
                             StopOnFirstFailure="true">
            </MSBuild>
        </Target>
        -->
    
    </Project>
    
    C:\Projects\experiments\BuildBoth>msbuild /v:m /target:Both BuildBoth.proj
    Microsoft (R) Build Engine Version 4.0.30319.1
    [Microsoft .NET Framework, Version 4.0.30319.225]
    Copyright (C) Microsoft Corporation 2007. All rights reserved.
    
      BothWpf -> C:\Projects\experiments\BuildBoth\BothWpf\bin\Debug\BothWpf.exe
      BothWpf -> C:\Projects\experiments\BuildBoth\BothWpf\bin\Release\BothWpf.exe