Task: Using the Gradle Java Plugin I want to redirect all java compiler warnings to a file for further analysis (Jenkins static code analysis tools).
Environment: Windows 7 x64 JDK 1.7.0_51 64-Bit Gradle 1.4 (tried 1.12 -> same result) STS (Eclipse) Gradle IDE multiple projects
Problem: I expected the best result when using the javac compiler option -Xstdout:
tasks.withType(JavaCompile){
def myLogPath = file("$project.buildDir/reports/compile")
doFirst {
myLogPath.getParentFile().mkdir()
myLogPath.mkdir()
}
options.compilerArgs = ["-Xlint","-Xlint:-serial","-Xmaxwarns","-1","-Xstdout",myLogPath.getPath() + "/" + name + ".log"]
}
This resulted in an error message “invalid flag: -Xstdout” with a stack trace:
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':share:compileJava'.
> invalid flag: -Xstdout
* Try:
Run with --info or --debug option to get more log output.
* Exception is:
org.gradle.api.tasks.TaskExecutionException: Execution failed for task ':share:compileJava'.
at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:72)
at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.execute(ExecuteActionsTaskExecuter.java:49)
(...)
Caused by: java.lang.IllegalArgumentException: invalid flag: -Xstdout
at com.sun.tools.javac.api.JavacTool.processOptions(JavacTool.java:231)
at com.sun.tools.javac.api.JavacTool.getTask(JavacTool.java:199)
at com.sun.tools.javac.api.JavacTool.getTask(JavacTool.java:68)
at org.gradle.api.internal.tasks.compile.jdk6.Jdk6JavaCompiler.createCompileTask(Jdk6JavaCompiler.java:57)
at org.gradle.api.internal.tasks.compile.jdk6.Jdk6JavaCompiler.execute(Jdk6JavaCompiler.java:39)
at org.gradle.api.internal.tasks.compile.jdk6.Jdk6JavaCompiler.execute(Jdk6JavaCompiler.java:33)
at org.gradle.api.internal.tasks.compile.NormalizingJavaCompiler.delegateAndHandleErrors(NormalizingJavaCompiler.java:95)
at org.gradle.api.internal.tasks.compile.NormalizingJavaCompiler.execute(NormalizingJavaCompiler.java:48)
at org.gradle.api.internal.tasks.compile.NormalizingJavaCompiler.execute(NormalizingJavaCompiler.java:34)
at org.gradle.api.internal.tasks.compile.DelegatingJavaCompiler.execute(DelegatingJavaCompiler.java:29)
at org.gradle.api.internal.tasks.compile.DelegatingJavaCompiler.execute(DelegatingJavaCompiler.java:20)
at org.gradle.api.internal.tasks.compile.IncrementalJavaCompilerSupport.execute(IncrementalJavaCompilerSupport.java:33)
at org.gradle.api.internal.tasks.compile.IncrementalJavaCompilerSupport.execute(IncrementalJavaCompilerSupport.java:23)
at org.gradle.api.tasks.compile.Compile.compile(Compile.java:68)
at org.gradle.api.internal.BeanDynamicObject$MetaClassAdapter.invokeMethod(BeanDynamicObject.java:216)
at org.gradle.api.internal.BeanDynamicObject.invokeMethod(BeanDynamicObject.java:122)
at org.gradle.api.internal.CompositeDynamicObject.invokeMethod(CompositeDynamicObject.java:147)
at org.gradle.api.tasks.compile.JavaCompile_Decorated.invokeMethod(Unknown Source)
at org.gradle.util.ReflectionUtil.invoke(ReflectionUtil.groovy:23)
at org.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFactory$4.execute(AnnotationProcessingTaskFactory.java:161)
at org.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFactory$4.execute(AnnotationProcessingTaskFactory.java:156)
at org.gradle.api.internal.AbstractTask$TaskActionWrapper.execute(AbstractTask.java:510)
at org.gradle.api.internal.AbstractTask$TaskActionWrapper.execute(AbstractTask.java:499)
at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:64)
... 80 more
Since the javac executable supports the -Xstdout parameter at command line I wonder whether this might be a gradle issue. Javac had similar problems in JDK6 (https://bugs.openjdk.java.net/browse/JDK-6265137 , https://bugs.openjdk.java.net/browse/JDK-6265400) and according to the stack trace the gradle Java Plugin seems to use jdk6 internally.
As a workaround I tried adding a StandardOutputListener
tasks.withType(JavaCompile){
def myLogPath = file("$project.buildDir/reports/compile")
// unfortunately -Xstdout does not work in this context so we have to log the console output manually
// options.compilerArgs = ["-Xlint","-Xlint:-serial","-Xmaxwarns","-1","-Xstdout",myLogPath.getPath() + "/" + name + ".log"]
def myCompilerlog = file(myLogPath.getPath() + "/" + name + ".log")
def myListener = new StandardOutputListener(){
void onOutput(CharSequence output) {
myCompilerlog << output
}
}
doFirst {
myLogPath.getParentFile().mkdir()
myLogPath.mkdir()
myCompilerlog.delete()
logging.addStandardErrorListener(myListener)
}
options.compilerArgs = ["-Xlint","-Xlint:-serial","-Xmaxwarns","-1"]
}
Basically this works, but has drawbacks: * the warnings are still printed to the console, which is not very nice especially in Eclipse * all gradle (non-javac) errors of these tasks are written to the log too * may have cases (nested compile tasks) with duplicate log lines due to multiple Listeners with the same log file