2012-12-12 45 views
2

MSBuild文檔提示了幾個地方,項目不一定與文件相同。如何在不表示文件的項目上使用執行MSBuild批處理?

"MSBuild items are inputs into the build system, and they typically represent files."

"Items are objects that typically represent files."

不過,我似乎無法找到任何例子,其中的項目並不代表文件。特別是,我想對一組非文件項目執行批處理。但是,我創建的每個項目(即使是自定義構建任務)都會以某種方式獲取類似文件的元數據(FullPath,RootDir,文件名,擴展名等)。此外,我對將目標的輸入設置爲一組不是文件的項目以及將該目標的輸出用作什麼的後果感到困惑。

有沒有人有一個使用非文件項目在MSBuild中執行批處理的例子?

編輯

對不起了那麼久纔拿出一個例子。我對事情有了更多的瞭解,但我仍然不確定(而且似乎完全沒有關於此的文檔)。這裏的一切都是關於我的記憶。我現在不在我的工作計算機上,所以我無法驗證它。

以我的經驗,MSBuild不喜歡一次構建多個.sln文件的配置。所以,這樣的:

msbuild.exe SampleMSBuild.sln /p:Configuration=Debug%3BRelease 

(編碼後的分號是必要的,這樣就不會嘗試定義多個屬性)

產生以下:

"D:\src\SampleMSBuild\SampleMSBuild.sln" (default target) (1) -> 
(ValidateSolutionConfiguration target) -> 
    D:\src\SampleMSBuild\SampleMSBuild.sln.metaproj : error MSB4126: The 
    specified solution configuration "Debug;Release|Any CPU" is invalid. 
    Please specify a valid solution configuration using the Configuration 
    and Platform properties (e.g. MSBuild.exe Solution.sln 
    /p:Configuration=Debug /p:Platform="Any CPU") or leave those properties 
    blank to use the default solution configuration. 
    [D:\src\SampleMSBuild\SampleMSBuild.sln] 

所以,現在看來似乎應該可以使用配料和物品來處理這個問題。

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" 
     DefaultTarget="Rebuild" 
     ToolsVersion="4.0"> 
    <ItemGroup> 
    <Configurations Include="Debug" />--> 
    <Configurations Include="Release" />--> 
    </ItemGroup> 

    <UsingTask TaskName="LogMetadata" 
      TaskFactory="CodeTaskFactory" 
      AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll"> 
    <ParameterGroup> 
     <Items ParameterType="Microsoft.Build.Framework.ITaskItem[]" 
      Required="true" /> 
    </ParameterGroup> 
    <Task> 
     <Code Type="Fragment" Language="cs"> 
     <![CDATA[ 
     foreach (var item in Items) { 
      Console.Write(item.ItemSpec); 
      Console.Write(" {"); 
      foreach (string metadataKey in item.MetadataNames) { 
      Console.Write(metadataKey); 
      Console.Write("=\""); 
      Console.Write(item.GetMetadata(metadataKey). 
       ToString().Replace("\"", "\\\"")); 
      Console.Write("\" "); 
      } 
      Console.WriteLine("}"); 
     }]]> 
     </Code> 
    </Task> 
    </UsingTask> 

    <Target Name="Rebuild"> 
    <LogMetadata Items="%(Configurations.Identity)" /> 
    </Target> 
</Project> 

將會產生這樣的:

Debug { 
    FullPath="D:\src\SampleMSBuild\Debug" 
    RootDir="D:\" 
    Filename="Debug" 
    Extension="" 
    RelativeDir="" 
    Directory="src\SampleMSBuild\" 
    RecursiveDir="" 
    Identity="Debug" 
    ModifiedTime="" 
    CreatedTime="" 
    AccessedTime="" 
} 
Release { 
    FullPath="D:\src\SampleMSBuild\Release" 
    RootDir="D:\" 
    Filename="Release" 
    Extension="" 
    RelativeDir="" 
    Directory="src\SampleMSBuild\" 
    RecursiveDir="" 
    Identity="Release" 
    ModifiedTime="" 
    CreatedTime="" 
    AccessedTime="" 
} 

正如你可以看到,該項目具有各種附加到他們的文件的元數據。我不能刪除包含屬性,因爲它是必需的,但我可以在自定義任務中合成這些項目。但是,當我這樣做時,他們仍然以某種方式神奇地獲得所有相同的文件元數據。

這是什麼影響?由於我沒有將這些作爲輸入或輸出指定給目標,文件元數據是否會導致任何問題?由於項目的FullPath元數據中指定的文件不存在,生成系統是否會跳過目標或構建超出需要的目標?如果這些文件確實存在?會導致任何問題嗎?

+0

一些片段或僞代碼可能有助於理解你想要完成什麼。 – KMoraz

回答

1

棘手的問題。我是MSBuild noob,並且發現自己最近需要了解配料,所以我想分享一些我發現的東西。

一般來說,是的,似乎大多數地方都可以看到關於ITaskItems的示例和討論,它們往往是關於文件的。但底層的實現非常靈活,並且可以處理許多其他事情。就我而言,我一直在處理字符串和XML數據。

This MS article給出了非文件ItemGroups和元數據的一些很好的例子。

This article是我可以找到的最好的總結,談論項目的機制以及它們與屬性不同。它還涵蓋了關於@和%語法的所有內容,在字符串和項目之間進行轉換,以及關於這些文件元數據屬性來自哪裏的提示 - MSBuild已針對其進行了優化。

每當你有一個接口用作任務的參數或任何其他接口時,將會有一個接口的某個地方的默認實現。我的猜測是你的代碼示例正在創建一些默認的對象,並定義默認創建的元數據。如果你自己實現這個接口,我會打賭你可以改變這種行爲。可能超出了問題的範圍,但= =

+0

我不知道我在研究這個時如何錯過了MS文章。非常感謝你! –

2

我使用的物品後,對方和做與他們一些「手冊」的任務就是建設了幾種解決方案,所以我定義自己的項目:

<ItemGroup> 
<MergeConfigurations Include="project1\project1.SDK.sln"> 
    <MergeOutAssemblyName>product1.dll</MergeOutAssemblyName> 
    <MergePrimaryAssemblyName>project1.Interfaces.dll</MergePrimaryAssemblyName> 
    <SolutionBinaries>project1\bin\$(FlavorToBuild)</SolutionBinaries> 
</MergeConfigurations> 

<MergeConfigurations Include="project1\project1.Plugin.sln"> 
    <MergeOutAssemblyName>product1.dll</MergeOutAssemblyName> 
    <MergePrimaryAssemblyName>project1.Interfaces.dll</MergePrimaryAssemblyName> 
    <SolutionBinaries>project1\bin\plugin\$(FlavorToBuild)</SolutionBinaries> 
</MergeConfigurations> 
<ItemGroup> 

然後我用目標採取的信息和做什麼是必要的:

<Target Name="MergeSolution" 
     Inputs="%(MergeConfigurations.Identity)" 
     Outputs="%(MergeConfigurations.Identity)\Ignore_this"> 

    <PropertyGroup> 
    <MergeSolution>%(MergeConfigurations.Identity)</MergeSolution> 
    <MergeOutAssemblyName>%(MergeConfigurations.MergeOutAssemblyName)</MergeOutAssemblyName> 
    <MergePrimaryAssemblyName>%(MergeConfigurations.MergePrimaryAssemblyName)</MergePrimaryAssemblyName> 
    <SolutionBinaries>%(MergeConfigurations.SolutionBinaries)</SolutionBinaries> 
    </PropertyGroup> 

    [....] 
</Target> 

希望這有助於指向你需要的方向。

+0

問題特別要求提供項目不是文件的示例。 –

+0

沒錯,但我沒有其他實際的例子,它和文件一樣工作。包含只是一個標識符,可以填充任何你想要的東西。該示例應該顯示如何設置和處理自定義元數據。 – MikeR

+0

@MikeR你能向我解釋爲什麼** \ Ignore_this **這個詞已被使用?它的目的是什麼? – M005

相關問題