【问题标题】:Execute Ant task just if a condition is met仅在满足条件时执行 Ant 任务
【发布时间】:2013-01-11 20:13:38
【问题描述】:

只有满足条件时,我才需要在特定目标中执行 Ant 任务。

我找到了一种在目标级别定义条件的方法,但不是在任务级别。我还发现了一个实现 IF task 的贡献。

我的问题是,您知道通过标准 Ant 任务实现此目标的任何方法吗?

更长的解释:我正在尝试启动 Tomcat 服务器以防它停止。要检测它是否已停止,我使用以下代码:

<echo message="Checking whether Tomcat is running"/>
<condition property="tomcat.running">
  <socket server="${tomcat.host}" port="${tomcat.port}"/> 
</condition>

所以我在这个目标中的下一个任务是一个 exec 任务,只有在 ${tomcat.running} 为 false 时才应该执行。正如我所说,我不想在目标中添加单个任务来使用除非属性。

【问题讨论】:

    标签: ant


    【解决方案1】:

    Ant 目标可以有一个可选的if 或unless 子句。这意味着只有在使用if 子句设置属性或使用unless 子句1 未设置属性时才执行任务。有趣的是,if 或 unless 子句在任何依赖任务第一次执行后检查。

    这意味着,您可以在标准 Ant 中执行此操作,作为仅在满足特定条件时执行 Ant 任务的一种方式:

     <target name="test.if.tomcat.is.running">
          <condition property="tomcat.running">
              <socket server="${tomcat.host}" port="${tomcat.port}"/> 
          </condition>
    </target>
    
    <target name="my.target"
        if="tomcat.running"
        depends="test.if.tomcat.is.running">
        <yaddah/>
        <yaddah/>
        <yaddah/>
    </target>
    

    您指定希望 Ant 执行 Target my.target。 Ant 注意到 my.target 依赖于 test.if.tomcat.is.running 目标,并将首先执行该目标。如果 Tomcat 实际正在运行,test.if.tomcat.is.running 任务将设置 tomcat.running 属性。否则,不设置该属性。

    最后,Ant 会回到my.target 目标,查看是否设置了属性tomcat.running,如果设置了则只会执行目标my.target。

    或者,您可以使用 Ant-contrib 任务,这可以使您的整个构建过程更容易理解。

    如果你想走 Ant-Contrib 路线,有一个简单的方法来设置 Ant-Contrib,所以 Ant-contrib jar 实际上是你项目的一部分。如果有人从版本控制系统中签出您的项目,他们也会获得 Ant-contrib jar,因此不必自己安装 Ant-Contrib。

    下载 Ant-Contrib jar,并将其放入项目根目录中名为 antlib/ac 的目录中。 antlib 可用于各种可选任务 jar,例如 Findbugs 或 PMD。只需将每个可选的 Ant jar 放在 antlib 下自己的目录中(就像我将 Ant-Contrib 放在 ac 目录下一样)。

    然后,在您的 build.xml 中,您以这种方式指定 Ant-Contrib 任务:

    <taskdef resource="net/sf/antcontrib/antlib.xml">
       <classpath>
           <fileset dir="${basedir}/antlib/ac"/>
       </classpath>
    </taskdef>
    

    现在,您可以使用 Ant-Contrib 任务,而不必担心它们是否安装在特定机器上。您签出您的项目,并且您可以自动访问这些任务。


    1. 没错,if/unless 子句检查是否设置了属性,而不是 true/false,这会引起很多混乱。我看到开发人员将属性设置为false 或no,然后想知道为什么目标实际上正在执行,因为if 子句设置为false。

    【讨论】:

    • 谢谢,但正如我在原帖中所说,我正在寻找一种避免创建目标的方法。使用该解决方案,我需要为每个条件执行指定一个新目标。根据您的回答,我知道没有办法,这就是 ANT Contrib 项目的原因。对吗?
    • 嗯,您正在创建 新目标,但这些目标并不是您的用户自己会使用的目标。将它们视为内部目标。它确实使构建过程变得有点棘手,这也是人们喜欢 Ant-Contrib 的原因之一。 Ant-Contrib 任务的问题在于它们不是标准 Ant 的一部分,这通常意味着您必须告诉人们在他们构建您的项目之前安装 Ant-Contrib。但是,如果您按照我在回答第二部分中所述的方式进行操作,则不再是问题。
    【解决方案2】:

    自版本 1.9.1(*) 起,ant 支持以更细粒度的方式在任何任务上拥有 if-and unless-conditions >,如果您在项目元素中声明必要的命名空间。

    (*) 请使用最新版本的 ant(撰写本文时为 1.9.6),因为 1.9.1 版本包含缺陷 WRT 这个新功能,正如用户 @Rebse 亲切指出的那样。

    在下面的示例中,您可以尝试评论/取消评论属性...

    <project name="test"
             xmlns:if="ant:if"
             xmlns:unless="ant:unless">
    
      <property name="is.good" value="hohoho"/>
      <!--property name="hide.base" value="boo"/-->
    
      <target name="foo">
         <echo unless:set="hide.base">${basedir}</echo>
         <echo if:set="is.good">GOOD</echo>
      </target>
    </project>
    

    ...并观察如下输出:

    Buildfile: D:\test\ant\taskcondition\build.xml
    foo:
         [echo] D:\test\ant\taskcondition
         [echo] GOOD
    BUILD SUCCESSFUL
    Total time: 191 milliseconds
    

    【讨论】:

    【解决方案3】:

    如果你想要一个“if else”类型的实现:

    <target name="test.if.tomcat.is.running">
          <condition property="tomcat.running" value="true" else="false">
              <socket server="${tomcat.host}" port="${tomcat.port}"/> 
          </condition>
    </target>
    
    <target name="my.target.running"
        if="${tomcat.running}"
        depends="test.if.tomcat.is.running">
    ...
    </target>
    
    <target name="my.target.ifnotrunning"
        unless="${tomcat.running}"
        depends="test.if.tomcat.is.running">
       .....
    </target>
    

    【讨论】:

    【解决方案4】:

    在某些情况下,您无法使您的 Ant 目标依赖于另一个 Ant 目标,因为 if 应该基于在 exec 之前初始化的值进行评估(我可以提供一个清晰的示例,但是为简单起见,我不会)。

    在类 Unix 系统上,一个替代方案(在某些情况下更可取)如下:

    <!-- the property that contains the value to be checked agains IF -->
    <property name="myprop" value="true"/>
    
    <!-- the Ant's exec combined with OS-IF command -->
    <exec executable="bash">
            <arg value="-c" />
            <arg value="if [ &quot;${myprop}&quot; != &quot;$${myprop}&quot;] || [&quot;${tag_exists}&quot; != &quot;true&quot; ]; then my-bash-command _arguments_; fi" />
    </exec>
    

    在上面 my-bash-command 说明了您要执行的命令/程序,而 arguments 说明了该命令/程序的参数命令。

    请注意,当 myprop 未设置时,${myprop} 将简单地计算为字符串“$”+“{”+“myprop”+“}”(即“ ${myprop}"),因此我们必须将 myprop 的值与该字符串进行比较。

    另一方面,当 myprop 设置时,它的值可能是字符串 true/false 所以为了检查 IF 我们的条件满足我们应该将 myprop 与字符串 true (或您可能拥有的任何值)进行比较。

    结论:使用 Ant 的 exec 结合 OS 命令 IF 我们可以执行任意 OS 命令/程序,而不需要另一个 Ant目标。使用与上述相同的逻辑,类似 IF 的语句可以调整为即使在 Windows 上也可以工作。

    【讨论】:

      猜你喜欢
      • 2013-08-08
      • 1970-01-01
      • 2013-09-09
      • 2020-01-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多