【问题标题】:Make ant quiet without the -q flag?没有 -q 标志让蚂蚁安静?
【发布时间】:2011-07-24 16:19:01
【问题描述】:

我有一个 ant 构建文件,它通常在完全不同的环境中运行。默认情况下,我正在寻找与使用相同的行为:

ant -q

但是,由于某些团队成员的配置不同,因此在每个人的环境中指定 -q 选项并不容易以统一的方式完成(有些人从 eclipse 运行 ant,有些从命令行运行,有些从调试/分析工具运行,等等。每个都有不同的方法来指定 ant 参数,如 -q)

所以我正在寻找一种方法让 ant 文件安静地调用自身...

如下所示是理想的:

<target name="default">
    <antcall quiet="yes" target="build" /> <!-- doesn't work -->
</target>

任何人都可以想办法完成这样的事情吗?我所追求的只是让构建在运行默认目标时安静地运行,无论是否设置了 -q。

【问题讨论】:

    标签: ant build build-process


    【解决方案1】:

    一个选项可能是从目标中设置日志记录级别。

    您可以通过简短的脚本任务访问记录器。比如:

    <target ... >
        <script language="javascript">
            var logger = project.getBuildListeners( ).firstElement( );
            logger.setMessageOutputLevel( 0 );
        </script>
        ...
    </target>
    

    我不熟悉 Eclipse 如何调用 Ant,但可能有必要遍历所有构建侦听器以全面“静默”。

    建议无论您最终如何执行此操作,都可以轻松切换回详细运行。

    编辑 - 评论回复:您可以使用 project.getProperty() 从脚本中访问项目属性:

    <property name="verboseFlag" value="1" />
    <script language="javascript">
        var logger = project.getBuildListeners().firstElement();
        var verboseMode = project.getProperty( "verboseFlag" )
        if ( ! "1".equals( verboseMode ) )
            logger.setMessageOutputLevel( 0 );
    </script>
    

    (有点旧)API docs are here,包括project class

    【讨论】:

    • @martin:哇。我什至不知道 javascript 可以与 Ant 一起使用。棒极了。这非常有效,当我使用 setMessageOutputLevel(1) 时,只打印了我的 echo 命令。这正是我所追求的。现在,我要做的就是测试这是否适用于我们运行 Ant 的其他环境(命令行、eclipse 等)...
    • @martin: 在脚本的“第 2 行”上是否有类似 if(verboseFlagNotSet) logger.setMessageOutputLevel(1); 的说法,也就是说,您知道检查详细标志状态的方法吗?
    • @gmale - 应该可以。我在答案中添加了一个示例。您可以从 JS 中读取(和设置)Ant 属性。
    • @martin:感谢您的回答,它也很有用,但是......对不起,我应该更清楚。 “详细标志”是指 -v 选项。意思是,有没有办法检测用户何时调用了带有详细标志设置的 ant,如:ant -v -f build.xml。因此,当用户指定详细标志时,我想不理会记录器。
    • 日志级别是直接传递给ant日志框架的,我认为ant启动后你无法访问它。但是您可以像我在 groovy 示例中使用的那样使用 ... 进行检查。一种低级方法是 blablabla 然后检查文件长度。另请参阅ant.apache.org/manual/Tasks/echo.html,有一个详细的表格解释了当 ant 使用 -v、-d、-q loglevel 或默认值启动时记录的内容。
    【解决方案2】:

    根据其他答案:

    <macrodef name="quiet">
        <element name="body" implicit="yes"/>
        <sequential>
            <script language="javascript">
                project.getBuildListeners().firstElement().setMessageOutputLevel(0);
            </script>
            <body/>
            <script language="javascript">
                // TODO: restore last log level
                project.getBuildListeners().firstElement().setMessageOutputLevel(2);
            </script>
        </sequential>
    </macrodef>
    
    <target name="test-quiet">
        <quiet>
            <echoproperties/>
        </quiet>
    </target>
    

    【讨论】:

    • 很好,但仍会打印目标名称。
    【解决方案3】:

    要从您的 ant 脚本中控制日志级别,您可以执行这个简单的任务 =

    public class SetLogLevel extends Task
    {
        private int logLevel = -1;
    
        public void execute()
        {
            if (logLevel == -1)
            {
                throw new BuildException("Error - No Loglevel specified !!");
            }
            Vector listeners = this.getProject().getBuildListeners();
            for (Iterator i = listeners.iterator(); i.hasNext();)
            {
                BuildListener listener = (BuildListener) i.next();
                if (listener instanceof BuildLogger)
                {
                    BuildLogger logger = (BuildLogger) listener;
                    logger.setMessageOutputLevel(logLevel);
                }
            }
        }
    
        /**
         * 
         *  @see org.apache.tools.ant.taskdefs.Echo$EchoLevel
         * 
         */
    
        public void setLevel(EchoLevel echoLevel) {
            String option = echoLevel.getValue();
            if (option.equals("error")) {
                logLevel = Project.MSG_ERR;
            } else if (option.equals("warning")) {
                logLevel = Project.MSG_WARN;
            } else if (option.equals("info")) {
                logLevel = Project.MSG_INFO;
            } else if (option.equals("verbose")) {
                logLevel = Project.MSG_VERBOSE;
            } else {
                // must be "debug"
                logLevel = Project.MSG_DEBUG;
            }
        }
    }
    

    将其映射到 taskdef 并像这样使用它 =

    <setloglevel level="error"/>
    

    ...应该只列出错误

    <setloglevel level="info" />
    

    ...再次记录日志级别信息

    这就是我在使用 f.e. 等健谈任务时缩短日志文件的方法。 cvs任务

    【讨论】:

    • 我不熟悉做这种事情(通过 java 扩展 ant),但我会在谷歌上搜索如何让它工作的详细信息,然后试一试......跨度>
    • 基本上都是关于扩展 org.apache.tools.ant.Task
    • 基本上都是关于扩展 org.apache.tools.ant.Task 通常你有多个自写的任务并将它们放入一个 jar 中。在这个 jar 中有一个名为 antlib.xml 的 xml 文件,它在任务名和类名之间进行映射。将那个罐子放在 ant 的视线范围内 - 但不仅仅是在 %ANT_HOME%/lib 中,因为您正在污染您的 ant 安装。最好放入一些 ../extralibs 文件夹并使用 -lib path/to/extralibs 选项启动 ant。然后在你的 antscript 中加载你的任务:
    • 谢谢。这一切都非常有帮助。有趣的是,我的第一个直觉是把那个 Jar 放在我的 ant lib 目录中,因为它会有可重用的 ant 东西。目前,我的 ant lib 中唯一的东西是 ivy。我想把这个 jar 放在本地 ivy 存储库中会很方便,然后我可以像 ant-contrib 一样自动检索它...
    【解决方案4】:

    阅读 Martin 的回答后,我认为将所有内容放在 scriptdef 中是最舒服的。这是一个 groovy =

    的解决方案
    <project>
    
      <taskdef name="groovy" classname="org.codehaus.groovy.ant.Groovy"/>
    
      <!-- testproperty referenced from verboseflag attribute 
           comment out to make it unset -->
      <property name="someverboseflag" value="whatever"/>
    
        <scriptdef name="setloglevel" language="groovy">
          <attribute name="loglevel"/>
          <attribute name="verboseflag"/>
    
         switch (attributes.'loglevel') {
            case 'error':
              project.getBuildListeners()[0].setMessageOutputLevel(0)
              break
            case 'warn':
              project.getBuildListeners()[0].setMessageOutputLevel(1)
              break
            case 'info':
              project.getBuildListeners()[0].setMessageOutputLevel(2)
              break
            case 'verbose':
              project.getBuildListeners()[0].setMessageOutputLevel(3)
              break
            case 'debug':
              project.getBuildListeners()[0].setMessageOutputLevel(4)
              break
         }
    
            if (project.getProperty(attributes.'verboseflag') == null)
            {
              println "Property " + attributes.'verboseflag' + " not set, default => Loglevel WARN !"   
              project.getBuildListeners()[0].setMessageOutputLevel(1)
            }
      </scriptdef>
    
        <!-- the loglevel given in attribute loglevel is only used
             when verboseflag attribute is set, otherwise
             loglevel WARN is used -->
        <setloglevel loglevel="debug" verboseflag="someverboseflag"/>
    
        <!-- test -->
        <echo level="error">getting logged when Loglevel ERROR and higher..</echo>
        <echo level="warning">getting logged when Loglevel WARN and higher..</echo>
        <echo level="info">getting logged when Loglevel INFO and higher..</echo>
        <echo level="verbose">getting logged when Loglevel VERBOSE and higher..</echo>
        <echo level="debug">getting logged when Loglevel DEBUG..</echo>
    
    </project>
    

    在 Java VM 中使用 Bean Scipting Framework 运行的每种脚本语言都可以用于在 ant 中编写脚本,并且可以完全访问 ant api - 这是个人喜好问题。之前使用过 Javascript、Beanshell、(J)ruby,最近改用 Groovy。

    【讨论】:

    • + 1 让我大吃一惊!哈哈。您可以在 ant 脚本中使用 groovy !!!这几乎让我流口水。
    • :-) Groovy 甚至提供了它自己的任务 ...。除了 groovy 之外,还有许多其他语言通过 Ant 中的 Bean Scripting Framework 运行:(J)ruby、Beanshell、Javascript(来自 Mozilla 的 Rhino)、Jython、Judoscript .. 一种适合各种口味/迷信的语言
    • 顺便说一句。还有另一种方法,使用来自 Groovy 的 Ant,没有 xml,请参阅 = groovy.codehaus.org/Using+Ant+from+Groovy
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-08
    • 2015-03-22
    • 2011-04-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多