如何将相同的任务传递给多个项目

本文关键字:项目 任务 | 更新日期: 2023-09-27 18:04:05

我想从一个构建文件在多个项目上运行相同的任务,而不必将任务复制到每个项目文件。

我得到所有的项目文件在我的解决方案和:

<ItemGroup>
    <ProjectsToBuild Include="..'Modules'**'*csproj"/>
</ItemGroup>

然后我在每个ProjectToBuild上调用MSBuild任务

<MSBuild Projects ="@(ProjectsToBuild)" 
             Targets="DoStuff"
             ContinueOnError ="false" 
             Properties="Configuration=$(Configuration)">
    <Output ItemName="OutputFiles" TaskParameter="TargetOutputs"/>
</MSBuild>

这不起作用,因为目标必须存在于您正在构建的项目中。

从MSDN

目标必须出现在所有项目文件中。

是否有一种方法可以将DoStuff任务传递给正在传递到MSBuild任务的项目?

如何将相同的任务传递给多个项目

MSBuild Import元素会有帮助吗?

https://msdn.microsoft.com/en-us/library/92x05xfs.aspx

把你的任务放到一个通用的任务文件中,然后把它导入到你的每个项目中。

我不相信有任何方法可以把你的任务"注入"到其他项目中。

正如Wolf5所述,导入一些具有共同目标和/或任务的文件是实现此目的的方法。在我们的项目中,我们有共同点。目标XML文件的代码如下:

<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
  <!-- Build file for common build targets -->
  <Import Project="$(MSBuildExtensionsPath)/ExtensionPack/4.0/MSBuild.ExtensionPack.VersionNumber.targets" />
  <UsingTask TaskName="MSBuild.ExtensionPack.Compression.Zip" AssemblyFile="$(MSBuildExtensionsPath)/ExtensionPack/4.0/MSBuild.ExtensionPack.dll" />
  <UsingTask TaskName="BuildRevisionTask" AssemblyName="OurMSBuildTasks, Version=1.0.0.0, Culture=neutral, PublicKeyToken=318ab5a03b21183a"/>

  <PropertyGroup>    
    <!-- Set this property to change the branch where the build is working in -->
    <Branch>MAIN</Branch>
  </PropertyGroup>

  <!-- Called after the workspace initialization -->
  <Target Name="AfterinitializeWorkspace">
    <CallTarget Targets="PrintInfo"/>
  </Target>
</Project>

在这里,您可以使用和其他语句将一些在构建场景中重新出现的公共共享构建步骤放在一起。然后,在与特定构建相对应的.proj文件中,您只需引用此通用。目标文件如下:

<Import Project="common.targets"/>

并使用共享的公共构建步骤/目标/任务/属性

由于这个项目有来自不同时区和位置的几个不同的人,我不想增加另一个要求,让人们每次都手动更新他们的项目文件。然而,最后我还是做了我想做的事。

<Target Name="BuildAll" DependsOnTargets="$(BuildAllDependsOn)"/>
<PropertyGroup>
    <BuildAllDependsOn>UpdateProjects;CoreBuild</BuildAllDependsOn>
</PropertyGroup>
<ItemGroup>
    <ProjectsToBuild Include="$(MSBuildProjectDirectory)'..'MyProjects'**'*csproj" Exclude="$(MSBuildProjectDirectory)'..'MyProjects'**'Team*csproj;$(MSBuildProjectDirectory)'..'MyProjects'**'Image*csproj"/>
</ItemGroup>
<Target Name="CoreBuild">
<Message Text="CoreBuild" />
    <MSBuild Projects ="@(ProjectsToBuild)" 
             Targets ="DoStuff" 
             ContinueOnError ="false" 
             Properties="Configuration=$(Configuration)">
        <Output ItemName="OutputFiles" TaskParameter="TargetOutputs"/>
    </MSBuild>
</Target>
<Target Name="UpdateProjects">
    <Message Text="$(MSBuildProjectDirectory)" />
    <ItemGroup>
      <CSProjects Include="$(MSBuildProjectDirectory)'..'MyProjects'**'*csproj" Exclude="$(MSBuildProjectDirectory)'..'MyProjects'**'Team*csproj;$(MSBuildProjectDirectory)'..'MyProjects'**'Image*csproj" />
    </ItemGroup>
    <Message Text="Updating Projects:[@(CSProjects)]" />
    <UpdateProject ProjectPath="%(CSProjects.Identity)" ImportsPath="$(MSBuildProjectDirectory)'projectImports.Targets" ModuleTargets="$(MSBuildProjectDirectory)'DoStuff.Targets" CommunityTasksPath="$(MSBuildProjectDirectory)" />
 </Target>
<UsingTask
  TaskName="UpdateProject"
  TaskFactory="CodeTaskFactory"
  AssemblyFile="$(MSBuildToolsPath)'Microsoft.Build.Tasks.v12.0.dll">
  <ParameterGroup>
      <ProjectPath Required="true" />
      <ImportsPath Required="true" />
      <ModuleTargets Required="true" />
      <CommunityTasksPath Required="true" />
  </ParameterGroup>
  <Task>
      <Reference Include="System.Xml" />
      <Reference Include="System.Xml.Linq" />
      <Using Namespace="System" />
      <Using Namespace="System.Linq" />
      <Using Namespace="System.Xml.Linq" />
      <Code Type="Fragment" Language="cs">
          <![CDATA[
              var document = XDocument.Load(ProjectPath);
              XNamespace ns = "http://schemas.microsoft.com/developer/msbuild/2003";
              var alreadyAdded = document.Descendants(ns + "Target").Any(el => (string)el.Attribute("DependsOnTargets").Value == "DoStuff");
              if (!alreadyAdded)
                  {
                      var importsDoc = XDocument.Load(ImportsPath);
                      importsDoc.Descendants(ns + "Import").FirstOrDefault().Attribute("Project").Value = ModuleTargets;
                      importsDoc.Descendants(ns + "MSBuildCommunityTasksPath").FirstOrDefault().Value = CommunityTasksPath;
                      document.Descendants(ns + "Project").FirstOrDefault().Add(importsDoc.Root.Elements());
                      document.Save(ProjectPath);
                  }
          ]]>
      </Code>
  </Task>
</UsingTask>

我首先调用UpdateProjects,它用任务的位置更新每个项目文件。我使用代码块(linq to xml)来查找和更新项目文件。如果它已经被更新过,它不会添加相同的东西两次。然后在每个项目文件上调用build,并告诉msbuild添加到每个项目文件中的目标的名称。