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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With