web-dev-qa-db-ja.com

MSBuildを使用して複数の構成を構築する

プロジェクトファイルを編集して、一度に複数のビルド構成をビルドするプロジェクトを作成できるようにしています。これは、バッチアプローチとMSBuildタスクを使用して行いました(以下を参照)。

スクリプトを実行すると、次のエラーが発生します。

エラー103 OutputPathプロパティがプロジェクト「ThisMSBuildProjectFile.csproj」に設定されていません。このプロジェクトに対して構成とプラットフォームの有効な組み合わせを指定したことを確認してください。 Configuration = 'Debug' Platform = 'AnyCPU'。

MSBuildタスクからOutputPathを追加または省略した場合、これが発生します。 VS2010デバッガーを使用してスクリプトをステップ実行し、MSBuildタスクが呼び出された場合-デバッガーはファイルに再度ステップインしてから、OutputPathにステップインするので、それはすべきですその値を取得しますか?

これに対するどんな助けも大歓迎です-それは私を夢中にさせています。ありがとう、ポール。

ThisMSBuildProjectFile.csproj(取り出された余計なもの):

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.Microsoft.com/developer/msbuild/2003" DefaultTargets="Build">

  <!-- Only Import normal targets if not building multiple projects -->
  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" Condition="'$(Configuration)|$(Platform)' != 'AllBuild|AnyCPU' "/>

  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == '' ">
    <DebugType>pdbonly</DebugType>
    <Optimize>true</Optimize>
    <OutputPath>C:\Folder\Etc\Output\$(Configuration)\</OutputPath>
    <OutDir>C:\Folder\Etc\Output\$(Configuration)\</OutDir>
    <BaseOutputPath>C:\Folder\Etc\Output\$(Configuration)\</BaseOutputPath>
    <DefineConstants>TRACE</DefineConstants>
    <ErrorReport>Prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>
  </PropertyGroup>

  <!-- Common -->
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
    <Platform>AnyCPU</Platform>
    <!-- Repeated properties from above here (including, of course, OutputPath) -->  
   </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
    <!-- Repeated properties from above here (including, of course, OutputPath) --> 
  </PropertyGroup>

  <ItemGroup>
    <Projects Include="C:\Folder\Etc\ThisMSBuildProjectFile.csproj" />
  </ItemGroup>

   <!-- Call this project file again, but with a different configuration - if this was working, this would call multiple  build configs -->
  <Target Name="Build" Condition="'$(Configuration)|$(Platform)' == 'AllBuild|AnyCPU' ">
    <Message Text="hm!"/>
    <!-- Tried thiswith and without the OutputPath property - makes no difference. -->
   <MSBuild  Projects="@(Projects)" Properties="Configuration=Debug;OutputPath=C:\Folder\Etc\Output\" ToolsVersion="4.0" Condition="'$(Configuration)|$(Platform)' == 'AllBuild|AnyCPU' "/>
 </Target>

   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'AllBuild|AnyCPU' ">
    <!-- Repeated properties from above here (including, of course, OutputPath) --> 
  </PropertyGroup>

  <!-- Project files -->
  <ItemGroup>
    <Reference Include="System" />
    <Reference Include="System.Core" />
  </ItemGroup>
  <ItemGroup>
    <Compile Include="Properties\AssemblyInfo.cs" />
    <Compile Include="Blah\Blah.cs" />
  </ItemGroup>
23
p.q

「MSBuild」タスクを使用すると、新しい子MSBuildプロセスが開始されることを理解することが重要です。これの意味するところは、親MSBuildプロセスで定義するすべてのアイテムとプロパティがnot自動的に子MSBuildプロセスに渡される/そこから表示されるnlessを介して明示的に渡されるProperties要素のMSBuild属性(<MSbuild Properties="..." />など)。

あなたの質問に答えるために、指定されたすべての構成に対して子MSBuildプロジェクトを実行する次の自己完結型の例を書きました。

  1. 最初に、MSBuild実験用のディレクトリを作成します(たとえば、C:\temp\msbuildtestを使用しました)

  2. このディレクトリに、最初のファイル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>
    
  3. 同じディレクトリで、2番目のファイルchild.projを作成します(あなたの場合、これはビルドしようとしている実際のC#プロジェクトですが、私のポイントを説明しようとしているので、単純な子を使用していますC#コンパイラを実行する代わりに、プロパティの値を出力するだけのプロジェクト:-))

    <Project xmlns="http://schemas.Microsoft.com/developer/msbuild/2003" DefaultTargets="Build" ToolsVersion="4.0">
        <Target Name="Build">
            <Message Text="Building configuration $(Configuration) with output path $(OutputPath)" Importance="High" />
        </Target>
    </Project>
    
  4. これで、例を実行できます。最初に、ビルドする構成を明示的に指定しない場合のデフォルト:

    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
    

この手法を状況に合わせて調整できるはずです。

20
Milan Gardian

プロジェクトファイルで何かが間違っています。次のXMLについて考えてみましょう。

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

$(Configuration)と$(Platform)が空であっても、バー文字と連結すると、空の文字列と一致することはないため、これらのプロパティを設定することはできません。その条件の最小値は '|'ですとは異なります。条件を '|'と比較して修正した場合でも、そのPropertyGroupのOutputPathで$(Configuration)を使用しようとしますが、$(Configuration)は使用された時点で値を保持しません。同様に、$(Platform)を 'AnyCPU'に設定しようとする場合、その値がすでに存在している必要があります。おそらく、最初のPropertyGroupの条件を完全に除外するつもりで、条件のない初期のPropertyGroupで$(Configuration)と$(Platform)のデフォルト値を提供する必要がある場合もあります。プロジェクト全体を新しいプロジェクトと比較し、このような他の奇妙な点があるかどうかを確認します。

また、「ビルド」ターゲットのオーバーライドでは、MSBuildタスクに冗長な条件があることに注意してください。同じ条件で、どのタスクでも必要ありません。

5
Brian Kretzler

プロジェクトのcsprojファイル自体のこのような複雑な構成を実行するかどうかは、よくわかりません。どちらの構成でもソリューションをビルドする「Both」という特定のターゲットを持つ個別のMSBuild「BuildBoth.proj」ファイルをセットアップしたいのですが。

<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
4
icelava