Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

No verbose output when fork option is used for maven-compiler-plugin

If I want to see the compiler output, usually I enable the verbose option for the maven-compiler-plugin.

However, this will not work when it is used together with the fork option. The compilation is running in another process and it seems that maven does not redirect the output to console.

My code sample looks like this

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.5.1</version>
            <configuration>
                <fork>true</fork>
                <verbose>true</verbose>
            </configuration>
        </plugin>
    </plugins>
</build>

Does anyone know how can I see what is happening during compilation?

In this link I see that using the two options together (fork and verbose) is encouraged.

However, as I already mentioned, in practice the two options do not work well when used together.

like image 653
Alex Avatar asked Sep 03 '25 16:09

Alex


1 Answers

UPDATE (25/06/2016): This issue of the plexus-compiler was fixed and the given code in the question will work as of version 2.8.


After reading through the source code, this is a bug of the plexus-compiler 2.7, which is the library internally used by the maven-compiler-plugin 3.5.1 to compile the Java sources.

So it goes like this in the code: the maven-compiler-plugin populates an object called CompilerConfiguration and sets its fork and verbose according to the given configuration element in the POM. The verbose element is correctly read and added to the compiler arguments:

if ( config.isVerbose() )
{
    args.add( "-verbose" );
}

Then, there is a switch depending on whether we're forking or not.


If we are not, we eventually come down to the code invoking javac and its output is stored in the compilation result:

ok = (Integer) compile.invoke( null, new Object[]{ args, new PrintWriter( out ) } );

messages = parseModernStream( ok.intValue(), new BufferedReader( new StringReader( out.toString() ) ) );

finally returned with:

return new CompilerResult( success, messages );

So far so good, the maven-compiler-plugin will loop around those messages and output them into the console. Since the verbose parameter was set, we'll have all messages.


If we are, then an executable (which defaults to the javac in the PATH) is retrieved and the compiler arguments are correctly set:

for ( String key : config.getCustomCompilerArgumentsAsMap().keySet() )
{
    if ( StringUtils.isNotEmpty( key ) && key.startsWith( "-J" ) )
    {
        cli.addArguments( new String[]{ key } );
    }
}

We can confirm this by running Maven in debug mode with -X, we'll see the message:

[DEBUG] Excutable: 
[DEBUG]  "C:\Program Files\Java\jdk1.8.0_74\bin\javac.exe"
[DEBUG] Command line options:
[DEBUG] -d ... -classpath ... -sourcepath ... -s ... -g -target 1.8 -source 1.8 -verbose

Notice the -verbose at the end.

And then, this is the bug. The standard output will be stored inside an out variable

CommandLineUtils.StringStreamConsumer out = new CommandLineUtils.StringStreamConsumer();

correctly used as parameter of the compile method, but completely ignored afterwards:

returnCode = CommandLineUtils.executeCommandLine( cli, out, err );

messages = parseModernStream( returnCode, new BufferedReader( new StringReader( err.getOutput() ) ) );

Notice how the messages, that will later form what is output by the plugin, is only populated with the errors and not the standard output. So put simply: the standard output is correctly set in verbose mode but it is ignored and not translated into the correct compilation result.


I do not see a workaround for that (except not forking). I created the issue 20 in their GitHub to track this.

like image 162
Tunaki Avatar answered Sep 05 '25 15:09

Tunaki