Generate targets with MSBuild then import them in same session

半世苍凉 提交于 2019-12-13 02:53:54

问题


I have an MSBuild project file that generates some of its own targets, then imports them. It works nicely, except that msbuild has to be run twice to do the build—once to generate the rules and again for them to be visible to finish the build. (The logic was ported from a Makefile that itself only needed one run.)

Is it possible to run the generating target, then Import, then run one of the generated targets?

The following listing is a trivialized version of the actual use case which exhibits the same behavior. (Beside the point, the actual case generates targets from a list of filenames of the pattern *-to-*.xsl, using the name to automatically determine the dependency and destination.)

The objective is to make msbuild /t:SecondTarget work on the first try instead of requiring a second.

<Project
  xmlns="http://schemas.microsoft.com/developer/msbuild/2003"
  InitialTargets="AdditionalTargets"
  ToolsVersion="4.0">

  <!--
    A trivial target-generating task. Presume something more useful for
    the actual case.
  -->
  <UsingTask
    TaskName="GenerateAdditionalTargets"
    TaskFactory="CodeTaskFactory"
    AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll">
    <ParameterGroup>
      <Result ParameterType="System.String" Output="true"/>
    </ParameterGroup>
    <Task>
      <Reference Include="System.Xml"/>
      <Reference Include="System.Xml.Linq"/>
      <Using Namespace="System"/>
      <Using Namespace="System.Xml.Linq"/>
      <Code Type="Fragment" Language="cs"><![CDATA[
          var ns = XNamespace.Get("http://schemas.microsoft.com/developer/msbuild/2003");

          var collected = new XElement(ns + "Project",
            new XAttribute("ToolsVersion", "4.0"),
            new XElement(ns + "Target",
              new XAttribute("Name", "SecondTarget"),
              new XElement(ns + "Message",
                new XAttribute("Text", "1.21GW?!")
              )
            )
          );

          Result = collected.ToString(SaveOptions.DisableFormatting);
        ]]></Code>
    </Task>
  </UsingTask>

  <PropertyGroup>
    <AdditionalTargets>additional.targets</AdditionalTargets>
  </PropertyGroup>

  <Target Name="AdditionalTargets">
    <GenerateAdditionalTargets>
      <Output TaskParameter="Result" PropertyName="Targets"/>
    </GenerateAdditionalTargets>
    <WriteLinesToFile File="$(AdditionalTargets)" Lines="$(Targets)" Overwrite="true"/>
  </Target>

  <Import Project="$(AdditionalTargets)" Condition="Exists('$(AdditionalTargets)')"/>
</Project>

回答1:


I don't think this is possible. By design when calling a task it does not have the entire context of the project. It just has what is passed in to it. It's designed this way (at least one reason) so that task invocations cannot have unforeseen consequences which are hard to identify.



来源:https://stackoverflow.com/questions/13482762/generate-targets-with-msbuild-then-import-them-in-same-session

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!