我再次与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)).
现在,这是一个稍微不同的版本,在主目标中设置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任务。我想要做的就是更新路径并让它在项目的任何地方都可用。有什么想法吗?
答案 0 :(得分:23)
基于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相同的行为。
答案 1 :(得分:19)
这是一个非常有趣的问题,我将通过以下文章中的示例深入研究:Scope of properties and item in an MSBuild script
基本上有一些技巧,在目标执行中有本地和全局上下文切换:
- 为脚本创建了一个Project类实例 包含全局属性和项的所有值 上下文。
- 执行目标时,全局上下文将复制到本地 目标将使用的上下文。
- 目标执行结束,合并本地上下文更新 回到全球背景。
- 在目标执行完成之前,本地更新不会 可以使用CallTarget或MSBuild任务调用的目标访问