【问题标题】:MSBuild Property ScopeMSBuild 属性范围
【发布时间】:2011-09-23 20:20:15
【问题描述】:

我又一次与 MSBuild 作斗争。我想要一个用根路径定义的属性值。作为构建的一部分,路径将使用版本信息进行更新。但是,MSBuild 似乎有自己的范围规则,这些规则似乎完全倒退了。举第一个例子:

<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">

  <PropertyGroup>
    <MyPath>\\server\folder</MyPath>
  </PropertyGroup>

  <Target Name="Main">
    <Message Text="In Main Before - MyPath = $(MyPath)"/>
    <CallTarget Targets="Task1" />
    <CallTarget Targets="Task2" />
    <CallTarget Targets="Task3" />
    <Message Text="In Main After - MyPath = $(MyPath)"/>
  </Target>

  <Target Name="Task1">
    <PropertyGroup>
        <MyPath>$(MyPath)\version5</MyPath>
    </PropertyGroup>
    <Message Text="In Task1 - MyPath = $(MyPath)"/>
  </Target>

  <Target Name="Task2">
    <Message Text="In Task2 - MyPath = $(MyPath)"/>
  </Target>

  <Target Name="Task3">
    <Message Text="In Task3 - MyPath = $(MyPath)"/>
  </Target>

</Project>

以下是此命令行的输出:msbuild PropertyScopeTest1.proj /target:Main

Project "C:\Temp\PropertyScopeTest1.proj" on node 1 (Main target(s)).
Main:
  In Main Before - MyPath = \\server\folder
Task1:
  In Task1 - MyPath = \\server\folder\version5
Task2:
  In Task2 - MyPath = \\server\folder\version5
Task3:
  In Task3 - MyPath = \\server\folder\version5
Main:
  In Main After - MyPath = \\server\folder
Done Building Project "C:\Temp\PropertyScopeTest1.proj" (Main target(s)).

现在,在 Main 目标中设置 MyPath 变量的版本略有不同:

<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">

  <PropertyGroup>
    <MyPath>\\server\path</MyPath>
  </PropertyGroup>

  <Target Name="Main">
    <Message Text="In Main Before - MyPath = $(MyPath)"/>
    <PropertyGroup>
        <MyPath>$(MyPath)\version5</MyPath>
    </PropertyGroup>
    <Message Text="In Main After PropertyGroup - MyPath = $(MyPath)"/>
    <CallTarget Targets="Task1" />
    <CallTarget Targets="Task2" />
    <CallTarget Targets="Task3" />
    <Message Text="In Main After - MyPath = $(MyPath)"/>
  </Target>

  <Target Name="Task1">
    <Message Text="In Task1 - MyPath = $(MyPath)"/>
  </Target>

  <Target Name="Task2">
    <Message Text="In Task2 - MyPath = $(MyPath)"/>
  </Target>

  <Target Name="Task3">
    <Message Text="In Task3 - MyPath = $(MyPath)"/>
  </Target>

</Project>

以下是此命令行的输出:msbuild PropertyScopeTest2.proj /target:Main

Project "C:\Temp\PropertyScopeTest2.proj" on node 1 (Main target(s)).
Main:
  In Main Before - MyPath = \\server\path
  In Main After PropertyGroup - MyPath = \\server\path\version5
Task1:
  In Task1 - MyPath = \\server\path
Task2:
  In Task2 - MyPath = \\server\path
Task3:
  In Task3 - MyPath = \\server\path
Main:
  In Main After - MyPath = \\server\path\version5
Done Building Project "C:\Temp\PropertyScopeTest2.proj" (Main target(s)).

我查看了此站点上的其他类似链接,但似乎都在从 MSBuild 项目文件中调用 MSBuild 任务。我想要做的就是更新路径并让它在项目中的任何地方都可用。有什么想法吗?

【问题讨论】:

    标签: msbuild msbuild-propertygroup


    【解决方案1】:

    基于 sll 的回答,使设置新路径的目标成为依赖项而不是使用 CallTarget 将产生预期的行为:

    <?xml version="1.0" encoding="utf-8"?>
    <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">
    
      <PropertyGroup>
        <MyPath>\\server\folder</MyPath>
      </PropertyGroup>
    
      <Target Name="Main" DependsOnTargets="SetMyPathProperty">
        <Message Text="In Main Before - MyPath = $(MyPath)"/>
        <CallTarget Targets="Task1" />
        <Message Text="In Main After - MyPath = $(MyPath)"/>
      </Target>
    
      <Target Name="SetMyPathProperty">
        <PropertyGroup>
          <MyPath>$(MyPath)\version5</MyPath>
        </PropertyGroup>
      </Target>
    
      <Target Name="Task1">
        <Message Text="In Task1 - MyPath = $(MyPath)"/>
      </Target>
    
    </Project>
    

    构建输出:

    Main:
      In Main Before - MyPath = \\server\folder\version5
    Task1:
      In Task1 - MyPath = \\server\folder\version5
    Main:
      In Main After - MyPath = \\server\folder\version5
    

    使 SetMyPathProperty 成为 Task1 而不是 Main 的依赖项将导致与您的 PropertyScopeTest1.proj 相同的行为。

    【讨论】:

    • 这个解决方案对我来说更有意义。我打算明天试试这个,看看它是否适用于我的用例。
    • 刚刚尝试了这个解决方案,这正是我想要的。非常感谢!
    【解决方案2】:

    这是一个非常有趣的问题,在以下文章中通过示例进行了深入研究:Scope of properties and item in an MSBuild script

    基本上存在跨目标执行的本地和全局上下文切换的技巧:

    • 为脚本创建了一个 Project 类的实例,并且 包含全局属性和项的所有值 上下文。
    • 执行目标时,将全局上下文复制到本地 目标将使用的上下文。
    • 目标执行端,本地上下文更新合并 回到全局上下文。
    • 在目标执行完成之前,本地更新不会 可访问使用 CallTarget 或 MSBuild 任务调用的目标

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-09-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-04-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多