【问题标题】:If Any of These Files Don't Exist Execute Target如果这些文件中的任何一个不存在,则执行目标
【发布时间】:2014-11-11 14:15:05
【问题描述】:

如果我的ItemGroup 中的文件都不存在,我想运行一次Target

<ItemGroup>
    <Foo Include="a.txt;b.txt;c.txt" />
</ItemGroup>
<Target Name="Bar" Condition="?">

我的问题是在“?”中放什么。

【问题讨论】:

  • msdn.microsoft.com/en-us/library/7szfhaft.aspx 看起来很简单。从文档中,我猜"Exists('a.txt') And Exists('b.txt') And Exists('c.txt')"。虽然尝试做这些事情是让我对整个 msbuild 系统感到厌烦的原因。
  • @MadScienceDreams 所以问题的目标是插入Foo 的每个元素。在我的实际代码中,我不知道设计时Foo 包含的文件列表。
  • 为什么匿名投反对票?这似乎是一个非常好的“我怎样才能让 MSBuild 做一些在真正的编程语言中如此简单的事情”的问题。如果有一些技术性,请在评论中说明,以便我们都可以学习。

标签: c++ visual-c++ msbuild exists itemgroup


【解决方案1】:

您可以使用另一个目标来浏览文件列表(目标擅长什么!)并将结果留在属性中。制作一个依赖于测试器 Target 和 Bar 的包装器 Target。 Bar 有一个使用第一个目标设置的机制的条件。

请注意,在任务完成之前,不会看到任务中设置的全局属性,因此习惯用法是将产生结果的事物和使用结果的事物包装为空任务的依赖项。

我认为您还需要使测试器成为 Bar 的依赖项,以确保它的顺序正确。

类似这样的:

<Target Name="TestLoop" Outputs="%(Foo.Identity)">
    <PropertyGroup>
        <Tested Condition="Exists(%(Foo.Identity))">Present</Tested>
    </PropertyGroup>
</Target>

触发 TestLoop 后,当且仅当至少有一个文件存在时,Tested 属性才会设置为“存在”。也就是说,它编码了一个循环逻辑或。

现在,如果您将其用作依赖项:

<Target Name="Wrapper" DependsOnTargets="TestLoop;Bar" />

然后您可以让 Bar 查看 TestLoop 留下的状态。 假设它们以正确的顺序执行,而不是并行执行!为确保这一点,还要使 TestLoop 成为 Bar 的先决条件,构建引擎将确定所需的顺序,并且知道在 TestLoop 完成之前不要尝试执行 Bar。

哦,Wrapper 是要求的目标。如上所述,如果您直接询问 Bar ,它将看不到属性更新(我认为)。因此,您可以将它们命名为使 Wrapper 成为暴露的 Bar,而您的 Bar 成为内部 Bar_helper。

【讨论】:

  • 很好,这解决了我正在寻找的问题,但我不知道如何设置依赖项。
  • 我正在运行 Visual Studio 2010,显然我不允许使用全局属性。 MSBuild 错误:“错误 MSB4066:元素 中的属性“名称”无法识别。”我尝试将该行切换到&lt;Tested Condition="Exists(%(Foo.Identity))"&gt;Present&lt;/Tested&gt;,这似乎有效。
  • 所以它最初对我不起作用,因为我没有按照您的建议创建一个依赖于两者的Wrapper 目标。你能解释一下为什么包装器目标很重要以及为什么我不能这样做:&lt;Target Name="Bar" DependsOnTargets="TestLoop" Condition="$(Tested)=='Present'"&gt;
  • @JonathanMee 是的,我在属性上输入了错误的语法(在编辑中修复)。
  • 我一定是在用大拇指阅读,我可以发誓你输入了:“是的,我在属性上输入了错误的语法(在编辑中修复)。”
猜你喜欢
  • 2016-06-26
  • 1970-01-01
  • 2019-07-27
  • 2021-03-11
  • 2014-12-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多