2015-07-22 8 views
0

Я хочу запустить ту же задачу для нескольких проектов из одного файла сборки, не копируя задачу в каждый файл проекта.MSBuild Как передать одну и ту же задачу нескольким проектам

Я получаю все файлы проекта в моем решении и:

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

Я тогда называть задачу MSBuild по каждому ProjectToBuild

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

Это не работает, так как цель должна существовать в проекте, который вы строите.

Из MSDN

Мишени должны происходить во всех файлах проекта. Если они этого не делают, возникает ошибка сборки.

Есть ли способ передать задачу DoStuff для проектов, передаваемых в задачу MSBuild?

ответ

0

Поскольку этот проект имеет несколько разных людей из разных часовых поясов и мест, я не хотел добавлять еще одно требование для людей обновлять свои файлы proj вручную каждый раз. В конце концов, я смог сделать то, что хотел.

<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 имя цели, которая была добавлена ​​в каждый файл проекта.

0

Помог ли элемент импорта MSBuild?

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

Просто положите свои задачи в общий файл задача, и импортировать его в каждый из ваших проектов.

Я не верю, что есть какой-либо способ «ввести» вашу задачу в другие проекты.

0

Как указано Wolf5, импортирование некоторого файла с общими целями и/или задачами - это способ сделать это. В нашем проекте мы имеем common.targets 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, соответствующей конкретной сборки вы просто ссылаться на этот common.targets файл, как это:

<Import Project="common.targets"/> 

и использовать общие общие этапы сборки/цели/задачи/свойства.

 Смежные вопросы

  • Нет связанных вопросов^_^