2012-12-12 41 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

相关问题