Make ant quiet without the -q flag?

2020-01-26 09:06发布

I have an ant buildfile that is often run from vastly different environments. By default, I'm looking for the same behavior as using:

ant -q

However, since some team member's configurations vary, specifying the -q option in each person's environment is not easily accomplished in a uniform way (some people run ant from eclipse, some from the command line, some from debugging/profiling tools, etc. Each with a different method for specifying ant arguments like -q)

So I'm seeking a way for the ant file to call itself quietly...

Something like the following would be ideal:

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

Can anyone think of anyway to accomplish something like this? All I'm after is for the build to run quietly whenever the default target is ran, regardless of whether -q is set.

4条回答
萌系小妹纸
2楼-- · 2020-01-26 09:36

For controlling the loglevel from within your ant script you could take this simple task =

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;
        }
    }
}

map it to a taskdef and use it like that =

<setloglevel level="error"/>

... only errors should be listed

<setloglevel level="info" />

... loglevel info again

That's what i do to shorten logfiles when using talkative tasks like f.e. cvs task

查看更多
Melony?
3楼-- · 2020-01-26 09:41

After reading Martin's answer, i think it's most comfortable to put the whole stuff in a scriptdef. Here's a solution with 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>

Every scripting language running with Bean Scipting Framework in Java VM may be used for scripting in ant with full access to the ant api - it's a matter of taste. Used Javascript, Beanshell, (J)ruby before and lately switched to Groovy.

查看更多
淡お忘
4楼-- · 2020-01-26 09:55

Based on other answers:

<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>
查看更多
祖国的老花朵
5楼-- · 2020-01-26 09:59

One option might be to set the logging level from within the target.

You can access loggers by means of a short script task. Something like:

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

I'm not familiar with how Eclipse calls Ant, but it might be necessary to iterate over all the build listeners to get 'silence' all round.

Suggest that how ever you end up doing this, you make it easy to switch back to verbose running.

Edit - response to comment: You can access project properties from within the script using 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>

(Somewhat old) API docs are here, including for the project class.

查看更多
登录 后发表回答