2014-10-08 85 views
1

我想設置一個應用程序,我正在Visual Studio中通過導入幾個腳本在項目中包括一組標準的程序集級屬性進入項目文件,因爲它們是由MSBuild編譯的。有問題的屬性由從其中一個腳本調用的MSBuild任務生成,而另一個腳本將生成的代碼文件包含爲編譯項目。使用屬性有條件地編譯使用MSBuild的源代碼文件

到目前爲止,我的自定義任務是生成包含文件OK並將其傳回給MSBuild創建的文件的路徑,但由於某種原因,MSBuild頑固地拒絕將生成的文件包含在項目的構建中。這可以通過驗證編譯的.dll文件的版本信息資源中沒有生成的程序集屬性中的任何值來確認。

我的自定義任務腳本(Build.targets):

<?xml version="1.0" encoding="utf-8"?> 
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> 
    <UsingTask AssemblyFile="..\Build.Tasks\$(OutDir)Build.Tasks.dll" TaskName="GenerateAssemblyInfo" /> 
    <Target Name="GenerateAssemblyAttributes" Condition="'$(SkipGenerateAssemblyAttributes)' == 'false'"> 
     <GenerateAssemblyInfo AssemblyName="$(AssemblyName)" CompilationSymbols="$(DefineConstants)" IncludeFileFolder="$(AssemblyInfoFileFolder)"> 
      <Output TaskParameter="IncludeFilePath" PropertyName="AssemblyInfoFilePath"/> 
     </GenerateAssemblyInfo> 
     <Message Text="Generated AssemblyInfo include file $(AssemblyInfoFilePath)."/> 
    </Target> 
</Project> 

條件編譯腳本(Build.props):

<?xml version="1.0" encoding="utf-8"?> 
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> 
    <ItemGroup Condition="Exists('$(AssemblyInfoFilePath)')"> 
     <Compile Include="$(AssemblyInfoFilePath)"/> 
    </ItemGroup> 
</Project> 

我創建測試/演示問題的一個樣本項目:

<Project DefaultTargets="GenerateAssemblyAttributes;Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> 
    <PropertyGroup> 
    <AssemblyInfoFileFolder>Properties</AssemblyInfoFileFolder> 
    <SkipGenerateAssemblyAttributes>false</SkipGenerateAssemblyAttributes> 
    </PropertyGroup> 
    <PropertyGroup> 
    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> 
    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> 
    ... 
    <OutputType>Library</OutputType> 
    <AppDesignerFolder>Properties</AppDesignerFolder> 
    <RootNamespace>BuildTest</RootNamespace> 
    <AssemblyName>BuildTest</AssemblyName> 
    </PropertyGroup> 
    <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> 
    <DebugSymbols>true</DebugSymbols> 
    <DebugType>full</DebugType> 
    <Optimize>false</Optimize> 
    <OutputPath>bin\Debug\</OutputPath> 
    <DefineConstants>DEBUG;TRACE</DefineConstants> 
    ... 
    </PropertyGroup> 
    <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> 
    <DebugType>pdbonly</DebugType> 
    <Optimize>true</Optimize> 
    <OutputPath>bin\Release\</OutputPath> 
    <DefineConstants>TRACE</DefineConstants> 
    ... 
    </PropertyGroup> 
    <Import Project="..\Build.Tasks\Build.targets" /> 
    <ItemGroup> 
    <Reference Include="System" /> 
    <Reference Include="System.Data" /> 
    <Reference Include="System.Xml" /> 
    </ItemGroup> 
    <Import Project="..\Build.Tasks\Build.props" /> 
    <ItemGroup> 
    <Compile Include="Class1.cs" /> 
    <Compile Include="Properties\AssemblyInfo.cs" /> 
    </ItemGroup> 
    <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> 
</Project> 

如果在Build.props腳本中,我用012替代$(AssemblyInfoFilePath)屬性生成文件的路徑(例如Properties\_AssemblyInfo.cs),或者我用一個Compile項替換Build.props腳本的導入,直接引用生成的文件(例如<Compile Include="Properties\_AssemblyInfo.cs" Condition="Exists('Properties\_AssemblyInfo.cs')" />),然後文件被包含在構建中,就像我期望的那樣。只要我將$(AssemblyInfoFilePath)屬性放回到<Compile>項目中,MSBuild就會再次忽略該文件,無論是否存在「Exists」條件。

正在創建和自定義任務的輸出設置$(AssemblyInfoFilePath)屬性,無論是從調用任務的目標之內我已經證明了(診斷構建輸出摘錄如下):

Target "GenerateAssemblyAttributes" in file "... Build.Tasks\Build.targets": 
    Using "GenerateAssemblyInfo" task from assembly "... Build.Tasks\..\Build.Tasks\bin\Debug\Build.Tasks.dll". 
    Task "GenerateAssemblyInfo" 
    Build 2.0.5394.41529 
    Done executing task "GenerateAssemblyInfo". 
    Task "Message" 
    Generated AssemblyInfo include file Properties\_AssemblyInfo.cs. 
    Done executing task "Message". 
Done building target "GenerateAssemblyAttributes" in project "BuildTest.csproj". 
Target "BeforeBuild" in file "C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\Microsoft.Common.targets": 
... 

,也通過將另一個目標添加到應用程序項目文件中,取決於GenerateAssemblyAttributes目標,該目標也使用<Message>元素來輸出該屬性的值。

我只是不能解決爲什麼,如果包含生成的源代碼文件的路徑屬性從自定義任務的輸出正確設置,MSBuild的行爲就像它甚至不存在?使用Visual Studio 2005和MSBuild 2.0。

編輯:所以,如果我修改我的Build.targets文件,像這樣:

<?xml version="1.0" encoding="utf-8"?> 
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> 
    <UsingTask AssemblyFile="..\Build.Tasks\$(OutDir)Build.Tasks.dll" TaskName="GenerateAssemblyInfo" /> 
    <Target Name="GenerateAssemblyAttributes" Condition="'$(SkipGenerateAssemblyAttributes)' == 'false'"> 
     <GenerateAssemblyInfo AssemblyName="$(AssemblyName)" CompilationSymbols="$(DefineConstants)" IncludeFileFolder="$(AssemblyInfoFileFolder)"> 
      <Output TaskParameter="IncludeFilePath" PropertyName="AssemblyInfoFilePath"/> 
     </GenerateAssemblyInfo> 
     <Message Text="Generated AssemblyInfo include file $(AssemblyInfoFilePath)."/> 
    <CreateItem Include="$(AssemblyInfoFilePath)" Condition ="Exists('$(AssemblyInfoFilePath)')"> 
     <Output TaskParameter="Include" ItemName="Compile"/> 
    </CreateItem> 
    </Target> 
</Project> 

並取出Build.props從應用項目文件文件,然後生成最終被「說對了一半」因爲自定義任務生成的源代碼文件包含在構建中。不幸的是,的MSBuild然後進行到產生在每個應用項目的所述第一源代碼文件中的下面的錯誤包括:(引用)在正在構建的項目:

錯誤147項「source_code_file的.cs 「在」Sources「參數中指定了多次。 「Sources」參數不支持重複的項目。 C:\ WINDOWS \ Microsoft.NET \框架\ V2.0.50727 \ Microsoft.CSharp。針對

如果執行自定義任務和創建(添加)「編譯」項目生成的源代碼文件的目標僅是指源代碼文件的路徑,它是如何不相關的源代碼文件得到重複的源代碼文件列表發送到編譯器作爲MSBuild聲明?

回答

1

我現在有MSBuild包括生成的源代碼文件,其路徑在我的自定義生成任務的屬性輸出中指定,通過向「編譯」項目添加項目來編譯每個應用程序集合組中調用自定義任務的目標(如上所述)。

編譯器報告的「重複來源」問題已經通過在應用程序項目文件中添加另一個目標,以在編譯程序集之前從「編譯」項目組中刪除重複項而得到解決。

<?xml version="1.0" encoding="utf-8"?> 
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> 
    <Target Name="RemoveSourceCodeDuplicates" > 
    <RemoveDuplicates Inputs="@(Compile)"> 
     <Output TaskParameter="Filtered" ItemName="Compile"/> 
    </RemoveDuplicates> 
    </Target> 
</Project> 

,並在應用項目文件:

<Project DefaultTargets="GenerateAssemblyAttributes;Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> 
    ... 
    <Import Project="..\Build.Tasks\RemoveDuplicates.targets"/> 
    <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> 
    ... 
</Project> 
1

這是評估順序。在執行任何任務之前對<Itemgroup>進行評估。 相反,將這些項目添加爲生成它們的任務的一部分,而不是在全局級別。對於舊版本的MSBuild來說,這並不美妙:我不知道在什麼時候添加了簡單地將項目組放入任務元素的能力。

此外,通配符的Include只會添加存在的執行時間,因此您會遇到問題,它無法在乾淨的構建中工作,但在第二次嘗試後似乎可以正常工作,如果它正在解決路徑(就像你有硬編碼一樣)。

+0

OK,我很害怕,可能是這樣。我可能不得不重新考慮我的方法。感謝您的正確方向。 – Matthew 2014-10-12 03:52:31

+0

我做了類似的工作正常:將文件添加到生成它們的任務中的項目組,而不是在全局級別。任何機會,你可以使用一個新的MSBuild? – 2014-10-12 03:58:59

+0

我相信我已經解決了我遇到的問題,遵循了您的建議,並對導致構建失敗的相關問題進行了一些額外的研究。 – Matthew 2014-10-13 05:47:22

相關問題