2011-04-01 99 views
20

我想編輯我的項目文件,使我有一個項目,一次構建多個構建配置。我已經使用批處理方法並使用MSBuild任務完成了這一任務(請參見下文)。使用MSBuild建立多個配置

如果我運行該腳本,我得到這個錯誤:

Error 103 The OutputPath property is not set for project "ThisMSBuildProjectFile.csproj". Please check to make sure that you have specified a valid combination of Configuration and Platform for this project. Configuration='Debug' Platform='AnyCPU'.

我得到這個,如果我地添加或刪除從MSBuild任務的OutputPath。如果使用VS2010調試器來逐步執行腳本並調用MSBuild任務 - 調試器再次進入文件,然後進入OutputPath,所以afaik,應該選擇該值,不是?

任何幫助,這將不勝感激 - 這是讓我瘋了。謝謝,保羅。

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> 

回答

18

重要的是要認識到,當您使用「MSBuild」任務時,將啓動一個新的子MSBuild進程。這個含義是,在家長,你定義的任何物品和屬性的MSBuild進程將不會自動傳遞到/可見從孩子的MSBuild過程除非你明確地通過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. 在同一個目錄中,創建第二個文件,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 
    

你應該能夠這項技術適應您的情況。

+0

非常好,謝謝你 - 這不是我正在尋找的東西(因爲我正在尋求最小化對標準CSProj文件的更改),但它看起來像我是過度思考的東西。我現在要採用這種方法。謝謝 – 2011-04-01 15:39:52

+0

Fyi,這種技術被稱爲「任務配料」。有很多方法可以進行批處理,Sayed Ibrahim Hashimi在他的書「Inside the Microsoft Build Engine:Using MSBuild and Team Foundation Build」一書中涵蓋了他們 – 2012-11-26 17:31:33

+0

「重要的是要認識到,當您使用」MSBuild「任務時,一個新的孩子MSBuild進程將開始。「這不是真的。根據http://msdn.microsoft.com/en-us/library/z7f65y0d.aspx:「與使用Exec任務啓動MSBuild.exe不同,此任務使用相同的MSBuild進程來構建子項目。」 這也符合我自己的經驗。 – 2012-12-07 16:49:08

4

財產以後在你的項目文件不對勁。考慮這個XML:

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

這些屬性不能被設置,因爲即使$(Configuration)和$(平臺)都是空的,他們不能在與槓字符匹配串連空字符串;該條件的最小值是'|'並不是 ''。即使通過將條件與'|'進行比較來更正,然後您仍然嘗試在該PropertyGroup中的OutputPath中使用$(Configuration),但$(Configuration)在它使用的位置永遠不會有值。同樣,如果您嘗試將$(Platform)設置爲'AnyCPU',它必須已經具有該值。您可能意味着完全忽略第一個PropertyGroup的條件,並且您可能需要在早期PropertyGroup中爲$(Configuration)和$(Platform)提供默認值,而且沒有條件。將您的整個項目與新項目進行比較,看看是否還有其他古怪的東西。

另請注意,如果您對「構建」目標的重載,則在MSBuild任務上有冗餘條件;在相同的條件下,你不需要任何任務。

+0

當然,這是有原因的,它從標準的csproj文件的 - 和原因,它的存在是作爲後備,如果沒有指定配置。我意識到它不會在我給出的例子中打中,但是當使用MSBuild調試器時,其他條件組按命中。感謝您指出在子節點上的重複! – 2011-04-01 15:37:31

+0

也許你錯過了我的觀點,它根本不是一個回退,它的編碼方式永遠不會評估爲真,因爲左側總是包含至少一個'|'而右側將永遠是空的,它們永遠不會平等。 – 2011-04-01 15:59:46

4

我不太確定,如果我想要通過項目的csproj文件本身這樣一個複雜的配置。我寧願設置一個單獨的MSBuild「BuildBoth.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> 

然後我會運行命令(冗長設置最小),同時針對

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 
+0

嗨,謝謝,我意識到我可以有一個獨立的項目,但是這個想法是讓團隊成員都能夠從VS推送構建而不是脫殼 - 我正在尋找最低限度地改變標準CSProj文件以啓用其餘的團隊要做到這一點。 Thaks回答。 – 2011-04-01 15:34:26