我想設置一個應用程序,我正在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聲明?
OK,我很害怕,可能是這樣。我可能不得不重新考慮我的方法。感謝您的正確方向。 – Matthew 2014-10-12 03:52:31
我做了類似的工作正常:將文件添加到生成它們的任務中的項目組,而不是在全局級別。任何機會,你可以使用一個新的MSBuild? – 2014-10-12 03:58:59
我相信我已經解決了我遇到的問題,遵循了您的建議,並對導致構建失敗的相關問題進行了一些額外的研究。 – Matthew 2014-10-13 05:47:22