You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@maven.apache.org by "Michael Zav'yalov (JIRA)" <ji...@apache.org> on 2016/09/21 15:06:21 UTC
[jira] [Commented] (MCOMPILER-278) Incremental build does not track
inter-module dependencies.
[ https://issues.apache.org/jira/browse/MCOMPILER-278?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=15510220#comment-15510220 ]
Michael Zav'yalov commented on MCOMPILER-278:
---------------------------------------------
I do not see full good fix, but can we have a partial fix where jar checksum can be used to detect modifications?
Here is a patch for this:
Index: src/main/java/org/apache/maven/plugin/compiler/AbstractCompilerMojo.java
===================================================================
--- src/main/java/org/apache/maven/plugin/compiler/AbstractCompilerMojo.java (revision 1761542)
+++ src/main/java/org/apache/maven/plugin/compiler/AbstractCompilerMojo.java (working copy)
@@ -18,7 +18,6 @@
* specific language governing permissions and limitations
* under the License.
*/
-
import org.apache.maven.execution.MavenSession;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecution;
@@ -49,20 +48,28 @@
import org.codehaus.plexus.compiler.util.scan.mapping.SuffixMapping;
import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
import java.lang.reflect.Method;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Date;
+import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.logging.Level;
+import java.util.logging.Logger;
/**
- * TODO: At least one step could be optimized, currently the plugin will do two
- * scans of all the source code if the compiler has to have the entire set of
- * sources. This is currently the case for at least the C# compiler and most
- * likely all the other .NET compilers too.
+ * TODO: At least one step could be optimized, currently the plugin will do two scans of all the source code if the compiler has to have the
+ * entire set of sources. This is currently the case for at least the C# compiler and most likely all the other .NET compilers too.
*
* @author others
* @author <a href="mailto:trygvis@inamo.no">Trygve Laugstøl</a>
@@ -70,1139 +77,1251 @@
* @since 2.0
*/
public abstract class AbstractCompilerMojo
- extends AbstractMojo
+ extends AbstractMojo
{
- // ----------------------------------------------------------------------
- // Configurables
- // ----------------------------------------------------------------------
- /**
- * Indicates whether the build will continue even if there are compilation errors.
- *
- * @since 2.0.2
- */
- @Parameter(property = "maven.compiler.failOnError", defaultValue = "true")
- private boolean failOnError = true;
+ private static final String DEPENDENCY_INFO_FILENAME = "dependencies.info";
- /**
- * Set to <code>true</code> to include debugging information in the compiled class files.
- */
- @Parameter(property = "maven.compiler.debug", defaultValue = "true")
- private boolean debug = true;
+ // ----------------------------------------------------------------------
+ // Configurables
+ // ----------------------------------------------------------------------
+ /**
+ * Indicates whether the build will continue even if there are compilation errors.
+ *
+ * @since 2.0.2
+ */
+ @Parameter(property = "maven.compiler.failOnError", defaultValue = "true")
+ private boolean failOnError = true;
- /**
- * Set to <code>true</code> to show messages about what the compiler is doing.
- */
- @Parameter(property = "maven.compiler.verbose", defaultValue = "false")
- private boolean verbose;
+ /**
+ * Set to <code>true</code> to include debugging information in the compiled class files.
+ */
+ @Parameter(property = "maven.compiler.debug", defaultValue = "true")
+ private boolean debug = true;
- /**
- * Sets whether to show source locations where deprecated APIs are used.
- */
- @Parameter(property = "maven.compiler.showDeprecation", defaultValue = "false")
- private boolean showDeprecation;
+ /**
+ * Set to <code>true</code> to show messages about what the compiler is doing.
+ */
+ @Parameter(property = "maven.compiler.verbose", defaultValue = "false")
+ private boolean verbose;
- /**
- * Set to <code>true</code> to optimize the compiled code using the compiler's optimization methods.
- */
- @Parameter(property = "maven.compiler.optimize", defaultValue = "false")
- private boolean optimize;
+ /**
+ * Sets whether to show source locations where deprecated APIs are used.
+ */
+ @Parameter(property = "maven.compiler.showDeprecation", defaultValue = "false")
+ private boolean showDeprecation;
- /**
- * Set to <code>true</code> to show compilation warnings.
- */
- @Parameter(property = "maven.compiler.showWarnings", defaultValue = "false")
- private boolean showWarnings;
+ /**
+ * Set to <code>true</code> to optimize the compiled code using the compiler's optimization methods.
+ */
+ @Parameter(property = "maven.compiler.optimize", defaultValue = "false")
+ private boolean optimize;
- /**
- * The -source argument for the Java compiler.
- */
- @Parameter(property = "maven.compiler.source", defaultValue = "1.5")
- protected String source;
+ /**
+ * Set to <code>true</code> to show compilation warnings.
+ */
+ @Parameter(property = "maven.compiler.showWarnings", defaultValue = "false")
+ private boolean showWarnings;
- /**
- * The -target argument for the Java compiler.
- */
- @Parameter(property = "maven.compiler.target", defaultValue = "1.5")
- protected String target;
+ /**
+ * The -source argument for the Java compiler.
+ */
+ @Parameter(property = "maven.compiler.source", defaultValue = "1.5")
+ protected String source;
- /**
- * The -encoding argument for the Java compiler.
- *
- * @since 2.1
- */
- @Parameter(property = "encoding", defaultValue = "${project.build.sourceEncoding}")
- private String encoding;
+ /**
+ * The -target argument for the Java compiler.
+ */
+ @Parameter(property = "maven.compiler.target", defaultValue = "1.5")
+ protected String target;
- /**
- * Sets the granularity in milliseconds of the last modification
- * date for testing whether a source needs recompilation.
- */
- @Parameter(property = "lastModGranularityMs", defaultValue = "0")
- private int staleMillis;
+ /**
+ * The -encoding argument for the Java compiler.
+ *
+ * @since 2.1
+ */
+ @Parameter(property = "encoding", defaultValue = "${project.build.sourceEncoding}")
+ private String encoding;
- /**
- * The compiler id of the compiler to use. See this
- * <a href="non-javac-compilers.html">guide</a> for more information.
- */
- @Parameter(property = "maven.compiler.compilerId", defaultValue = "javac")
- private String compilerId;
+ /**
+ * Sets the granularity in milliseconds of the last modification date for testing whether a source needs recompilation.
+ */
+ @Parameter(property = "lastModGranularityMs", defaultValue = "0")
+ private int staleMillis;
- /**
- * Version of the compiler to use, ex. "1.3", "1.5", if {@link #fork} is set to <code>true</code>.
- */
- @Parameter(property = "maven.compiler.compilerVersion")
- private String compilerVersion;
+ /**
+ * The compiler id of the compiler to use. See this
+ * <a href="non-javac-compilers.html">guide</a> for more information.
+ */
+ @Parameter(property = "maven.compiler.compilerId", defaultValue = "javac")
+ private String compilerId;
- /**
- * Allows running the compiler in a separate process.
- * If <code>false</code> it uses the built in compiler, while if <code>true</code> it will use an executable.
- */
- @Parameter(property = "maven.compiler.fork", defaultValue = "false")
- private boolean fork;
+ /**
+ * Version of the compiler to use, ex. "1.3", "1.5", if {@link #fork} is set to <code>true</code>.
+ */
+ @Parameter(property = "maven.compiler.compilerVersion")
+ private String compilerVersion;
- /**
- * Initial size, in megabytes, of the memory allocation pool, ex. "64", "64m"
- * if {@link #fork} is set to <code>true</code>.
- *
- * @since 2.0.1
- */
- @Parameter(property = "maven.compiler.meminitial")
- private String meminitial;
+ /**
+ * Allows running the compiler in a separate process. If <code>false</code> it uses the built in compiler, while if <code>true</code> it
+ * will use an executable.
+ */
+ @Parameter(property = "maven.compiler.fork", defaultValue = "false")
+ private boolean fork;
- /**
- * Sets the maximum size, in megabytes, of the memory allocation pool, ex. "128", "128m"
- * if {@link #fork} is set to <code>true</code>.
- *
- * @since 2.0.1
- */
- @Parameter(property = "maven.compiler.maxmem")
- private String maxmem;
+ /**
+ * Initial size, in megabytes, of the memory allocation pool, ex. "64", "64m" if {@link #fork} is set to <code>true</code>.
+ *
+ * @since 2.0.1
+ */
+ @Parameter(property = "maven.compiler.meminitial")
+ private String meminitial;
- /**
- * Sets the executable of the compiler to use when {@link #fork} is <code>true</code>.
- */
- @Parameter(property = "maven.compiler.executable")
- private String executable;
+ /**
+ * Sets the maximum size, in megabytes, of the memory allocation pool, ex. "128", "128m" if {@link #fork} is set to <code>true</code>.
+ *
+ * @since 2.0.1
+ */
+ @Parameter(property = "maven.compiler.maxmem")
+ private String maxmem;
- /**
- * <p>
- * Sets whether annotation processing is performed or not. Only applies to JDK 1.6+
- * If not set, both compilation and annotation processing are performed at the same time.
- * </p>
- * <p>Allowed values are:</p>
- * <ul>
- * <li><code>none</code> - no annotation processing is performed.</li>
- * <li><code>only</code> - only annotation processing is done, no compilation.</li>
- * </ul>
- *
- * @since 2.2
- */
- @Parameter
- private String proc;
+ /**
+ * Sets the executable of the compiler to use when {@link #fork} is <code>true</code>.
+ */
+ @Parameter(property = "maven.compiler.executable")
+ private String executable;
- /**
- * <p>
- * Names of annotation processors to run. Only applies to JDK 1.6+
- * If not set, the default annotation processors discovery process applies.
- * </p>
- *
- * @since 2.2
- */
- @Parameter
- private String[] annotationProcessors;
+ /**
+ * <p>
+ * Sets whether annotation processing is performed or not. Only applies to JDK 1.6+ If not set, both compilation and annotation
+ * processing are performed at the same time.
+ * </p>
+ * <p>
+ * Allowed values are:</p>
+ * <ul>
+ * <li><code>none</code> - no annotation processing is performed.</li>
+ * <li><code>only</code> - only annotation processing is done, no compilation.</li>
+ * </ul>
+ *
+ * @since 2.2
+ */
+ @Parameter
+ private String proc;
- /**
- * <p>
- * Sets the arguments to be passed to the compiler (prepending a dash) if {@link #fork} is set to <code>true</code>.
- * </p>
- * <p>
- * This is because the list of valid arguments passed to a Java compiler
- * varies based on the compiler version.
- * </p>
- * <p>
- * To pass <code>-Xmaxerrs 1000 -Xlint -Xlint:-path -Averbose=true</code> you should include the following:
- * </p>
- * <pre>
- * <compilerArguments>
- * <Xmaxerrs>1000</Xmaxerrs>
- * <Xlint/>
- * <Xlint:-path/>
- * <Averbose>true</Averbose>
- * </compilerArguments>
- * </pre>
- *
- * @since 2.0.1
- * @deprecated use {@link #compilerArgs} instead.
- */
- @Parameter
- @Deprecated
- protected Map<String, String> compilerArguments;
+ /**
+ * <p>
+ * Names of annotation processors to run. Only applies to JDK 1.6+ If not set, the default annotation processors discovery process
+ * applies.
+ * </p>
+ *
+ * @since 2.2
+ */
+ @Parameter
+ private String[] annotationProcessors;
- /**
- * <p>
- * Sets the arguments to be passed to the compiler if {@link #fork} is set to <code>true</code>.
- * Example:
- * <pre>
- * <compilerArgs>
- * <arg>-Xmaxerrs=1000</arg>
- * <arg>-Xlint</arg>
- * </compilerArgs>
- * </pre>
- *
- * @since 3.1
- */
- @Parameter
- protected List<String> compilerArgs;
-
- /**
- * <p>
- * Sets the unformatted single argument string to be passed to the compiler if {@link #fork} is set to <code>true</code>.
- * To pass multiple arguments such as <code>-Xmaxerrs 1000</code> (which are actually two arguments) you have to use {@link #compilerArguments}.
- * </p>
- * <p>
- * This is because the list of valid arguments passed to a Java compiler
- * varies based on the compiler version.
- * </p>
- */
- @Parameter
- protected String compilerArgument;
+ /**
+ * <p>
+ * Sets the arguments to be passed to the compiler (prepending a dash) if {@link #fork} is set to <code>true</code>.
+ * </p>
+ * <p>
+ * This is because the list of valid arguments passed to a Java compiler varies based on the compiler version.
+ * </p>
+ * <p>
+ * To pass <code>-Xmaxerrs 1000 -Xlint -Xlint:-path -Averbose=true</code> you should include the following:
+ * </p>
+ * <pre>
+ * <compilerArguments>
+ * <Xmaxerrs>1000</Xmaxerrs>
+ * <Xlint/>
+ * <Xlint:-path/>
+ * <Averbose>true</Averbose>
+ * </compilerArguments>
+ * </pre>
+ *
+ * @since 2.0.1
+ * @deprecated use {@link #compilerArgs} instead.
+ */
+ @Parameter
+ @Deprecated
+ protected Map<String, String> compilerArguments;
- /**
- * Sets the name of the output file when compiling a set of
- * sources to a single file.
- * <p/>
- * expression="${project.build.finalName}"
- */
- @Parameter
- private String outputFileName;
+ /**
+ * <p>
+ * Sets the arguments to be passed to the compiler if {@link #fork} is set to <code>true</code>. Example:
+ * <pre>
+ * <compilerArgs>
+ * <arg>-Xmaxerrs=1000</arg>
+ * <arg>-Xlint</arg>
+ * </compilerArgs>
+ * </pre>
+ *
+ * @since 3.1
+ */
+ @Parameter
+ protected List<String> compilerArgs;
- /**
- * Keyword list to be appended to the <code>-g</code> command-line switch. Legal values are none or a
- * comma-separated list of the following keywords: <code>lines</code>, <code>vars</code>, and <code>source</code>.
- * If debug level is not specified, by default, nothing will be appended to <code>-g</code>.
- * If debug is not turned on, this attribute will be ignored.
- *
- * @since 2.1
- */
- @Parameter(property = "maven.compiler.debuglevel")
- private String debuglevel;
+ /**
+ * <p>
+ * Sets the unformatted single argument string to be passed to the compiler if {@link #fork} is set to <code>true</code>. To pass
+ * multiple arguments such as <code>-Xmaxerrs 1000</code> (which are actually two arguments) you have to use {@link #compilerArguments}.
+ * </p>
+ * <p>
+ * This is because the list of valid arguments passed to a Java compiler varies based on the compiler version.
+ * </p>
+ */
+ @Parameter
+ protected String compilerArgument;
- /**
- *
- */
- @Component
- private ToolchainManager toolchainManager;
+ /**
+ * Sets the name of the output file when compiling a set of sources to a single file.
+ * <p/>
+ * expression="${project.build.finalName}"
+ */
+ @Parameter
+ private String outputFileName;
- // ----------------------------------------------------------------------
- // Read-only parameters
- // ----------------------------------------------------------------------
+ /**
+ * Keyword list to be appended to the <code>-g</code> command-line switch. Legal values are none or a comma-separated list of the
+ * following keywords: <code>lines</code>, <code>vars</code>, and <code>source</code>. If debug level is not specified, by default,
+ * nothing will be appended to <code>-g</code>. If debug is not turned on, this attribute will be ignored.
+ *
+ * @since 2.1
+ */
+ @Parameter(property = "maven.compiler.debuglevel")
+ private String debuglevel;
- /**
- * The directory to run the compiler from if fork is true.
- */
- @Parameter(defaultValue = "${basedir}", required = true, readonly = true)
- private File basedir;
+ /**
+ *
+ */
+ @Component
+ private ToolchainManager toolchainManager;
- /**
- * The target directory of the compiler if fork is true.
- */
- @Parameter(defaultValue = "${project.build.directory}", required = true, readonly = true)
- private File buildDirectory;
+ // ----------------------------------------------------------------------
+ // Read-only parameters
+ // ----------------------------------------------------------------------
+ /**
+ * The directory to run the compiler from if fork is true.
+ */
+ @Parameter(defaultValue = "${basedir}", required = true, readonly = true)
+ private File basedir;
- /**
- * Plexus compiler manager.
- */
- @Component
- private CompilerManager compilerManager;
+ /**
+ * The target directory of the compiler if fork is true.
+ */
+ @Parameter(defaultValue = "${project.build.directory}", required = true, readonly = true)
+ private File buildDirectory;
- /**
- * The current build session instance. This is used for toolchain manager API calls.
- */
- @Component
- private MavenSession session;
+ /**
+ * Plexus compiler manager.
+ */
+ @Component
+ private CompilerManager compilerManager;
- /**
- * Strategy to re use javacc class created:
- * <ul>
- * <li><code>reuseCreated</code> (default): will reuse already created but in case of multi-threaded builds,
- * each thread will have its own instance</li>
- * <li><code>reuseSame</code>: the same Javacc class will be used for each compilation even for multi-threaded build</li>
- * <li><code>alwaysNew</code>: a new Javacc class will be created for each compilation</li>
- * </ul>
- * Note this parameter value depends on the os/jdk you are using, but the default value should work on most of env.
- *
- * @since 2.5
- */
- @Parameter(defaultValue = "${reuseCreated}", property = "maven.compiler.compilerReuseStrategy")
- private String compilerReuseStrategy = "reuseCreated";
+ /**
+ * The current build session instance. This is used for toolchain manager API calls.
+ */
+ @Component
+ private MavenSession session;
- /**
- * @since 2.5
- */
- @Parameter(defaultValue = "false", property = "maven.compiler.skipMultiThreadWarning")
- private boolean skipMultiThreadWarning;
+ /**
+ * Strategy to re use javacc class created:
+ * <ul>
+ * <li><code>reuseCreated</code> (default): will reuse already created but in case of multi-threaded builds, each thread will have its
+ * own instance</li>
+ * <li><code>reuseSame</code>: the same Javacc class will be used for each compilation even for multi-threaded build</li>
+ * <li><code>alwaysNew</code>: a new Javacc class will be created for each compilation</li>
+ * </ul>
+ * Note this parameter value depends on the os/jdk you are using, but the default value should work on most of env.
+ *
+ * @since 2.5
+ */
+ @Parameter(defaultValue = "${reuseCreated}", property = "maven.compiler.compilerReuseStrategy")
+ private String compilerReuseStrategy = "reuseCreated";
- /**
- * compiler can now use javax.tools if available in your current jdk, you can disable this feature
- * using -Dmaven.compiler.forceJavacCompilerUse=true or in the plugin configuration
- *
- * @since 3.0
- */
- @Parameter(defaultValue = "false", property = "maven.compiler.forceJavacCompilerUse")
- private boolean forceJavacCompilerUse;
+ /**
+ * @since 2.5
+ */
+ @Parameter(defaultValue = "false", property = "maven.compiler.skipMultiThreadWarning")
+ private boolean skipMultiThreadWarning;
- /**
- * @since 3.0 needed for storing the status for the incremental build support.
- */
- @Parameter(property = "mojoExecution")
- private MojoExecution mojoExecution;
+ /**
+ * compiler can now use javax.tools if available in your current jdk, you can disable this feature using
+ * -Dmaven.compiler.forceJavacCompilerUse=true or in the plugin configuration
+ *
+ * @since 3.0
+ */
+ @Parameter(defaultValue = "false", property = "maven.compiler.forceJavacCompilerUse")
+ private boolean forceJavacCompilerUse;
- /**
- * We need this to determine the start timestamp of the build.
- *
- * @since 3.0
- */
- @Component
- protected MavenSession mavenSession;
+ /**
+ * @since 3.0 needed for storing the status for the incremental build support.
+ */
+ @Parameter(property = "mojoExecution")
+ private MojoExecution mojoExecution;
- /**
- * file extensions to check timestamp for incremental build
- * <b>default contains only <code>.class</code></b>
- *
- * @since 3.1
- */
- @Parameter
- private List<String> fileExtensions;
+ /**
+ * We need this to determine the start timestamp of the build.
+ *
+ * @since 3.0
+ */
+ @Component
+ protected MavenSession mavenSession;
- /**
- * to enable/disable incrementation compilation feature
- * @since 3.1
- */
- @Parameter(defaultValue = "true", property = "maven.compiler.useIncrementalCompilation")
- private boolean useIncrementalCompilation = true;
+ /**
+ * file extensions to check timestamp for incremental build
+ * <b>default contains only <code>.class</code></b>
+ *
+ * @since 3.1
+ */
+ @Parameter
+ private List<String> fileExtensions;
- protected abstract SourceInclusionScanner getSourceInclusionScanner( int staleMillis );
+ /**
+ * to enable/disable incrementation compilation feature
+ *
+ * @since 3.1
+ */
+ @Parameter(defaultValue = "true", property = "maven.compiler.useIncrementalCompilation")
+ private boolean useIncrementalCompilation = true;
- protected abstract SourceInclusionScanner getSourceInclusionScanner( String inputFileEnding );
+ protected abstract SourceInclusionScanner getSourceInclusionScanner(int staleMillis);
- protected abstract List<String> getClasspathElements();
+ protected abstract SourceInclusionScanner getSourceInclusionScanner(String inputFileEnding);
- protected abstract List<String> getCompileSourceRoots();
+ protected abstract List<String> getClasspathElements();
- protected abstract File getOutputDirectory();
+ protected abstract List<String> getCompileSourceRoots();
- protected abstract String getSource();
+ protected abstract File getOutputDirectory();
- protected abstract String getTarget();
+ protected abstract String getSource();
- protected abstract String getCompilerArgument();
+ protected abstract String getTarget();
- protected abstract Map<String, String> getCompilerArguments();
+ protected abstract String getCompilerArgument();
- protected abstract File getGeneratedSourcesDirectory();
+ protected abstract Map<String, String> getCompilerArguments();
- public void execute()
- throws MojoExecutionException, CompilationFailureException
- {
- // ----------------------------------------------------------------------
- // Look up the compiler. This is done before other code than can
- // cause the mojo to return before the lookup is done possibly resulting
- // in misconfigured POMs still building.
- // ----------------------------------------------------------------------
+ protected abstract File getGeneratedSourcesDirectory();
- Compiler compiler;
+ public void execute()
+ throws MojoExecutionException, CompilationFailureException
+ {
+ // ----------------------------------------------------------------------
+ // Look up the compiler. This is done before other code than can
+ // cause the mojo to return before the lookup is done possibly resulting
+ // in misconfigured POMs still building.
+ // ----------------------------------------------------------------------
- getLog().debug( "Using compiler '" + compilerId + "'." );
+ Compiler compiler;
- try
- {
- compiler = compilerManager.getCompiler( compilerId );
- }
- catch ( NoSuchCompilerException e )
- {
- throw new MojoExecutionException( "No such compiler '" + e.getCompilerId() + "'." );
- }
+ getLog().debug("Using compiler '" + compilerId + "'.");
- //-----------toolchains start here ----------------------------------
- //use the compilerId as identifier for toolchains as well.
- Toolchain tc = getToolchain();
- if ( tc != null )
- {
- getLog().info( "Toolchain in compiler-plugin: " + tc );
- if ( executable != null )
- {
- getLog().warn( "Toolchains are ignored, 'executable' parameter is set to " + executable );
- }
- else
- {
- fork = true;
- //TODO somehow shaky dependency between compilerId and tool executable.
- executable = tc.findTool( compilerId );
- }
- }
- // ----------------------------------------------------------------------
- //
- // ----------------------------------------------------------------------
+ try
+ {
+ compiler = compilerManager.getCompiler(compilerId);
+ }
+ catch (NoSuchCompilerException e)
+ {
+ throw new MojoExecutionException("No such compiler '" + e.getCompilerId() + "'.");
+ }
- List<String> compileSourceRoots = removeEmptyCompileSourceRoots( getCompileSourceRoots() );
+ //-----------toolchains start here ----------------------------------
+ //use the compilerId as identifier for toolchains as well.
+ Toolchain tc = getToolchain();
+ if (tc != null)
+ {
+ getLog().info("Toolchain in compiler-plugin: " + tc);
+ if (executable != null)
+ {
+ getLog().warn("Toolchains are ignored, 'executable' parameter is set to " + executable);
+ }
+ else
+ {
+ fork = true;
+ //TODO somehow shaky dependency between compilerId and tool executable.
+ executable = tc.findTool(compilerId);
+ }
+ }
+ // ----------------------------------------------------------------------
+ //
+ // ----------------------------------------------------------------------
- if ( compileSourceRoots.isEmpty() )
- {
- getLog().info( "No sources to compile" );
+ List<String> compileSourceRoots = removeEmptyCompileSourceRoots(getCompileSourceRoots());
- return;
- }
+ if (compileSourceRoots.isEmpty())
+ {
+ getLog().info("No sources to compile");
- if ( getLog().isDebugEnabled() )
- {
- getLog().debug( "Source directories: " + compileSourceRoots.toString().replace( ',', '\n' ) );
- getLog().debug( "Classpath: " + getClasspathElements().toString().replace( ',', '\n' ) );
- getLog().debug( "Output directory: " + getOutputDirectory() );
- }
+ return;
+ }
- // ----------------------------------------------------------------------
- // Create the compiler configuration
- // ----------------------------------------------------------------------
+ if (getLog().isDebugEnabled())
+ {
+ getLog().debug("Source directories: " + compileSourceRoots.toString().replace(',', '\n'));
+ getLog().debug("Classpath: " + getClasspathElements().toString().replace(',', '\n'));
+ getLog().debug("Output directory: " + getOutputDirectory());
+ }
- CompilerConfiguration compilerConfiguration = new CompilerConfiguration();
+ // ----------------------------------------------------------------------
+ // Create the compiler configuration
+ // ----------------------------------------------------------------------
+ CompilerConfiguration compilerConfiguration = new CompilerConfiguration();
- compilerConfiguration.setOutputLocation( getOutputDirectory().getAbsolutePath() );
+ compilerConfiguration.setOutputLocation(getOutputDirectory().getAbsolutePath());
- compilerConfiguration.setClasspathEntries( getClasspathElements() );
+ compilerConfiguration.setClasspathEntries(getClasspathElements());
- compilerConfiguration.setSourceLocations( compileSourceRoots );
+ compilerConfiguration.setSourceLocations(compileSourceRoots);
- compilerConfiguration.setOptimize( optimize );
+ compilerConfiguration.setOptimize(optimize);
- compilerConfiguration.setDebug( debug );
+ compilerConfiguration.setDebug(debug);
- if ( debug && StringUtils.isNotEmpty( debuglevel ) )
- {
- String[] split = StringUtils.split( debuglevel, "," );
- for ( int i = 0; i < split.length; i++ )
+ if (debug && StringUtils.isNotEmpty(debuglevel))
+ {
+ String[] split = StringUtils.split(debuglevel, ",");
+ for (int i = 0; i < split.length; i++)
+ {
+ if (!(split[i].equalsIgnoreCase("none") || split[i].equalsIgnoreCase("lines")
+ || split[i].equalsIgnoreCase("vars") || split[i].equalsIgnoreCase("source")))
{
- if ( !( split[i].equalsIgnoreCase( "none" ) || split[i].equalsIgnoreCase( "lines" )
- || split[i].equalsIgnoreCase( "vars" ) || split[i].equalsIgnoreCase( "source" ) ) )
- {
- throw new IllegalArgumentException( "The specified debug level: '" + split[i] + "' is unsupported. "
- + "Legal values are 'none', 'lines', 'vars', and 'source'." );
- }
+ throw new IllegalArgumentException("The specified debug level: '" + split[i] + "' is unsupported. "
+ + "Legal values are 'none', 'lines', 'vars', and 'source'.");
}
- compilerConfiguration.setDebugLevel( debuglevel );
- }
+ }
+ compilerConfiguration.setDebugLevel(debuglevel);
+ }
- compilerConfiguration.setVerbose( verbose );
+ compilerConfiguration.setVerbose(verbose);
- compilerConfiguration.setShowWarnings( showWarnings );
+ compilerConfiguration.setShowWarnings(showWarnings);
- compilerConfiguration.setShowDeprecation( showDeprecation );
+ compilerConfiguration.setShowDeprecation(showDeprecation);
- compilerConfiguration.setSourceVersion( getSource() );
+ compilerConfiguration.setSourceVersion(getSource());
- compilerConfiguration.setTargetVersion( getTarget() );
+ compilerConfiguration.setTargetVersion(getTarget());
- compilerConfiguration.setProc( proc );
+ compilerConfiguration.setProc(proc);
- compilerConfiguration.setGeneratedSourcesDirectory( getGeneratedSourcesDirectory() );
+ compilerConfiguration.setGeneratedSourcesDirectory(getGeneratedSourcesDirectory());
- compilerConfiguration.setAnnotationProcessors( annotationProcessors );
+ compilerConfiguration.setAnnotationProcessors(annotationProcessors);
- compilerConfiguration.setSourceEncoding( encoding );
+ compilerConfiguration.setSourceEncoding(encoding);
- Map<String, String> effectiveCompilerArguments = getCompilerArguments();
+ Map<String, String> effectiveCompilerArguments = getCompilerArguments();
- String effectiveCompilerArgument = getCompilerArgument();
+ String effectiveCompilerArgument = getCompilerArgument();
- if ( ( effectiveCompilerArguments != null ) || ( effectiveCompilerArgument != null ) || ( compilerArgs != null ) )
- {
- LinkedHashMap<String, String> cplrArgsCopy = new LinkedHashMap<String, String>();
- if ( effectiveCompilerArguments != null )
+ if ((effectiveCompilerArguments != null) || (effectiveCompilerArgument != null) || (compilerArgs != null))
+ {
+ LinkedHashMap<String, String> cplrArgsCopy = new LinkedHashMap<String, String>();
+ if (effectiveCompilerArguments != null)
+ {
+ for (Map.Entry<String, String> me : effectiveCompilerArguments.entrySet())
{
- for ( Map.Entry<String, String> me : effectiveCompilerArguments.entrySet() )
- {
- String key = me.getKey();
- String value = me.getValue();
- if ( !key.startsWith( "-" ) )
- {
- key = "-" + key;
- }
+ String key = me.getKey();
+ String value = me.getValue();
+ if (!key.startsWith("-"))
+ {
+ key = "-" + key;
+ }
- if ( key.startsWith( "-A" ) && StringUtils.isNotEmpty( value ) )
- {
- cplrArgsCopy.put( key + "=" + value, null );
- }
- else
- {
- cplrArgsCopy.put( key, value );
- }
- }
+ if (key.startsWith("-A") && StringUtils.isNotEmpty(value))
+ {
+ cplrArgsCopy.put(key + "=" + value, null);
+ }
+ else
+ {
+ cplrArgsCopy.put(key, value);
+ }
}
- if ( !StringUtils.isEmpty( effectiveCompilerArgument ) )
+ }
+ if (!StringUtils.isEmpty(effectiveCompilerArgument))
+ {
+ cplrArgsCopy.put(effectiveCompilerArgument, null);
+ }
+ if (compilerArgs != null)
+ {
+ for (String arg : compilerArgs)
{
- cplrArgsCopy.put( effectiveCompilerArgument, null );
+ cplrArgsCopy.put(arg, null);
}
- if ( compilerArgs != null )
+ }
+ compilerConfiguration.setCustomCompilerArguments(cplrArgsCopy);
+ }
+
+ compilerConfiguration.setFork(fork);
+
+ if (fork)
+ {
+ if (!StringUtils.isEmpty(meminitial))
+ {
+ String value = getMemoryValue(meminitial);
+
+ if (value != null)
{
- for ( String arg : compilerArgs )
- {
- cplrArgsCopy.put( arg, null );
- }
+ compilerConfiguration.setMeminitial(value);
}
- compilerConfiguration.setCustomCompilerArguments( cplrArgsCopy );
- }
+ else
+ {
+ getLog().info("Invalid value for meminitial '" + meminitial + "'. Ignoring this option.");
+ }
+ }
- compilerConfiguration.setFork( fork );
+ if (!StringUtils.isEmpty(maxmem))
+ {
+ String value = getMemoryValue(maxmem);
- if ( fork )
- {
- if ( !StringUtils.isEmpty( meminitial ) )
+ if (value != null)
{
- String value = getMemoryValue( meminitial );
-
- if ( value != null )
- {
- compilerConfiguration.setMeminitial( value );
- }
- else
- {
- getLog().info( "Invalid value for meminitial '" + meminitial + "'. Ignoring this option." );
- }
+ compilerConfiguration.setMaxmem(value);
}
-
- if ( !StringUtils.isEmpty( maxmem ) )
+ else
{
- String value = getMemoryValue( maxmem );
-
- if ( value != null )
- {
- compilerConfiguration.setMaxmem( value );
- }
- else
- {
- getLog().info( "Invalid value for maxmem '" + maxmem + "'. Ignoring this option." );
- }
+ getLog().info("Invalid value for maxmem '" + maxmem + "'. Ignoring this option.");
}
- }
+ }
+ }
- compilerConfiguration.setExecutable( executable );
+ compilerConfiguration.setExecutable(executable);
- compilerConfiguration.setWorkingDirectory( basedir );
+ compilerConfiguration.setWorkingDirectory(basedir);
- compilerConfiguration.setCompilerVersion( compilerVersion );
+ compilerConfiguration.setCompilerVersion(compilerVersion);
- compilerConfiguration.setBuildDirectory( buildDirectory );
+ compilerConfiguration.setBuildDirectory(buildDirectory);
- compilerConfiguration.setOutputFileName( outputFileName );
+ compilerConfiguration.setOutputFileName(outputFileName);
- if ( CompilerConfiguration.CompilerReuseStrategy.AlwaysNew.getStrategy().equals( this.compilerReuseStrategy ) )
- {
- compilerConfiguration.setCompilerReuseStrategy( CompilerConfiguration.CompilerReuseStrategy.AlwaysNew );
- }
- else if ( CompilerConfiguration.CompilerReuseStrategy.ReuseSame.getStrategy().equals(
- this.compilerReuseStrategy ) )
- {
- if ( getRequestThreadCount() > 1 )
+ if (CompilerConfiguration.CompilerReuseStrategy.AlwaysNew.getStrategy().equals(this.compilerReuseStrategy))
+ {
+ compilerConfiguration.setCompilerReuseStrategy(CompilerConfiguration.CompilerReuseStrategy.AlwaysNew);
+ }
+ else if (CompilerConfiguration.CompilerReuseStrategy.ReuseSame.getStrategy().equals(
+ this.compilerReuseStrategy))
+ {
+ if (getRequestThreadCount() > 1)
+ {
+ if (!skipMultiThreadWarning)
{
- if ( !skipMultiThreadWarning )
- {
- StringBuilder sb = new StringBuilder(
- "You are in a multi-thread build and compilerReuseStrategy is set to reuseSame. This can cause issues in some environments (os/jdk)! Consider using reuseCreated strategy." );
- sb.append( System.getProperty( "line.separator" ) );
- sb.append(
- "If your env is fine with reuseSame, you can skip this warning with the configuration field skipMultiThreadWarning or -Dmaven.compiler.skipMultiThreadWarning=true" );
- getLog().warn( sb.toString() );
- }
+ StringBuilder sb = new StringBuilder(
+ "You are in a multi-thread build and compilerReuseStrategy is set to reuseSame. This can cause issues in some environments (os/jdk)! Consider using reuseCreated strategy.");
+ sb.append(System.getProperty("line.separator"));
+ sb.append(
+ "If your env is fine with reuseSame, you can skip this warning with the configuration field skipMultiThreadWarning or -Dmaven.compiler.skipMultiThreadWarning=true");
+ getLog().warn(sb.toString());
}
- compilerConfiguration.setCompilerReuseStrategy( CompilerConfiguration.CompilerReuseStrategy.ReuseSame );
- }
- else
- {
+ }
+ compilerConfiguration.setCompilerReuseStrategy(CompilerConfiguration.CompilerReuseStrategy.ReuseSame);
+ }
+ else
+ {
- compilerConfiguration.setCompilerReuseStrategy( CompilerConfiguration.CompilerReuseStrategy.ReuseCreated );
- }
+ compilerConfiguration.setCompilerReuseStrategy(CompilerConfiguration.CompilerReuseStrategy.ReuseCreated);
+ }
- getLog().debug( "CompilerReuseStrategy: " + compilerConfiguration.getCompilerReuseStrategy().getStrategy() );
+ getLog().debug("CompilerReuseStrategy: " + compilerConfiguration.getCompilerReuseStrategy().getStrategy());
- compilerConfiguration.setForceJavacCompilerUse( forceJavacCompilerUse );
+ compilerConfiguration.setForceJavacCompilerUse(forceJavacCompilerUse);
- boolean canUpdateTarget;
+ boolean canUpdateTarget;
- IncrementalBuildHelper incrementalBuildHelper = new IncrementalBuildHelper( mojoExecution, mavenSession );
+ IncrementalBuildHelper incrementalBuildHelper = new IncrementalBuildHelper(mojoExecution, mavenSession);
- Set<File> sources = null;
+ Set<File> sources = null;
- IncrementalBuildHelperRequest incrementalBuildHelperRequest = null;
+ IncrementalBuildHelperRequest incrementalBuildHelperRequest = null;
+ Map<File, byte[]> dependencyInfo = null;
- if ( useIncrementalCompilation )
- {
- getLog().debug( "useIncrementalCompilation enabled" );
- try
- {
- canUpdateTarget = compiler.canUpdateTarget( compilerConfiguration );
+ if (useIncrementalCompilation)
+ {
+ getLog().debug("useIncrementalCompilation enabled");
+ try
+ {
+ canUpdateTarget = compiler.canUpdateTarget(compilerConfiguration);
- sources = getCompileSources( compiler, compilerConfiguration );
+ sources = getCompileSources(compiler, compilerConfiguration);
- incrementalBuildHelperRequest = new IncrementalBuildHelperRequest().inputFiles( sources );
+ incrementalBuildHelperRequest = new IncrementalBuildHelperRequest().inputFiles(sources);
+ dependencyInfo = createDependencyInfo();
- if ( ( compiler.getCompilerOutputStyle().equals( CompilerOutputStyle.ONE_OUTPUT_FILE_FOR_ALL_INPUT_FILES )
- && !canUpdateTarget ) || isDependencyChanged() || isSourceChanged( compilerConfiguration, compiler )
- || incrementalBuildHelper.inputFileTreeChanged( incrementalBuildHelperRequest ) )
- {
- getLog().info( "Changes detected - recompiling the module!" );
+ if ((compiler.getCompilerOutputStyle().equals(CompilerOutputStyle.ONE_OUTPUT_FILE_FOR_ALL_INPUT_FILES)
+ && !canUpdateTarget) || isDependencyChanged(incrementalBuildHelper, dependencyInfo)
+ || isSourceChanged(compilerConfiguration, compiler)
+ || incrementalBuildHelper.inputFileTreeChanged(incrementalBuildHelperRequest))
+ {
+ getLog().info("Changes detected - recompiling the module!");
- compilerConfiguration.setSourceFiles( sources );
- }
- else
- {
- getLog().info( "Nothing to compile - all classes are up to date" );
-
- return;
- }
+ compilerConfiguration.setSourceFiles(sources);
}
- catch ( CompilerException e )
+ else
{
- throw new MojoExecutionException( "Error while computing stale sources.", e );
+ getLog().info("Nothing to compile - all classes are up to date");
+
+ return;
}
- }
- else
- {
- getLog().debug( "useIncrementalCompilation disabled" );
- Set<File> staleSources;
- try
- {
- staleSources =
- computeStaleSources( compilerConfiguration, compiler, getSourceInclusionScanner( staleMillis ) );
+ }
+ catch (CompilerException e)
+ {
+ throw new MojoExecutionException("Error while computing stale sources.", e);
+ }
+ }
+ else
+ {
+ getLog().debug("useIncrementalCompilation disabled");
+ Set<File> staleSources;
+ try
+ {
+ staleSources
+ = computeStaleSources(compilerConfiguration, compiler, getSourceInclusionScanner(staleMillis));
- canUpdateTarget = compiler.canUpdateTarget( compilerConfiguration );
+ canUpdateTarget = compiler.canUpdateTarget(compilerConfiguration);
- if ( compiler.getCompilerOutputStyle().equals( CompilerOutputStyle.ONE_OUTPUT_FILE_FOR_ALL_INPUT_FILES )
- && !canUpdateTarget )
- {
- getLog().info( "RESCANNING!" );
- // TODO: This second scan for source files is sub-optimal
- String inputFileEnding = compiler.getInputFileEnding( compilerConfiguration );
+ if (compiler.getCompilerOutputStyle().equals(CompilerOutputStyle.ONE_OUTPUT_FILE_FOR_ALL_INPUT_FILES)
+ && !canUpdateTarget)
+ {
+ getLog().info("RESCANNING!");
+ // TODO: This second scan for source files is sub-optimal
+ String inputFileEnding = compiler.getInputFileEnding(compilerConfiguration);
- sources = computeStaleSources( compilerConfiguration, compiler,
- getSourceInclusionScanner( inputFileEnding ) );
+ sources = computeStaleSources(compilerConfiguration, compiler,
+ getSourceInclusionScanner(inputFileEnding));
- compilerConfiguration.setSourceFiles( sources );
- }
- else
- {
- compilerConfiguration.setSourceFiles( staleSources );
- }
+ compilerConfiguration.setSourceFiles(sources);
}
- catch ( CompilerException e )
+ else
{
- throw new MojoExecutionException( "Error while computing stale sources.", e );
+ compilerConfiguration.setSourceFiles(staleSources);
}
+ }
+ catch (CompilerException e)
+ {
+ throw new MojoExecutionException("Error while computing stale sources.", e);
+ }
- if ( staleSources.isEmpty() )
- {
- getLog().info( "Nothing to compile - all classes are up to date" );
+ if (staleSources.isEmpty())
+ {
+ getLog().info("Nothing to compile - all classes are up to date");
- return;
- }
- }
- // ----------------------------------------------------------------------
- // Dump configuration
- // ----------------------------------------------------------------------
+ return;
+ }
+ }
+ // ----------------------------------------------------------------------
+ // Dump configuration
+ // ----------------------------------------------------------------------
- if ( getLog().isDebugEnabled() )
- {
- getLog().debug( "Classpath:" );
+ if (getLog().isDebugEnabled())
+ {
+ getLog().debug("Classpath:");
- for ( String s : getClasspathElements() )
- {
- getLog().debug( " " + s );
- }
+ for (String s : getClasspathElements())
+ {
+ getLog().debug(" " + s);
+ }
- getLog().debug( "Source roots:" );
+ getLog().debug("Source roots:");
- for ( String root : getCompileSourceRoots() )
+ for (String root : getCompileSourceRoots())
+ {
+ getLog().debug(" " + root);
+ }
+
+ try
+ {
+ if (fork)
{
- getLog().debug( " " + root );
+ if (compilerConfiguration.getExecutable() != null)
+ {
+ getLog().debug("Excutable: ");
+ getLog().debug(" " + compilerConfiguration.getExecutable());
+ }
}
- try
+ String[] cl = compiler.createCommandLine(compilerConfiguration);
+ if (cl != null && cl.length > 0)
{
- if ( fork )
- {
- if ( compilerConfiguration.getExecutable() != null )
- {
- getLog().debug( "Excutable: " );
- getLog().debug( " " + compilerConfiguration.getExecutable() );
- }
- }
-
- String[] cl = compiler.createCommandLine( compilerConfiguration );
- if ( cl != null && cl.length > 0 )
- {
- StringBuilder sb = new StringBuilder();
- sb.append( cl[0] );
- for ( int i = 1; i < cl.length; i++ )
- {
- sb.append( " " );
- sb.append( cl[i] );
- }
- getLog().debug( "Command line options:" );
- getLog().debug( sb );
- }
+ StringBuilder sb = new StringBuilder();
+ sb.append(cl[0]);
+ for (int i = 1; i < cl.length; i++)
+ {
+ sb.append(" ");
+ sb.append(cl[i]);
+ }
+ getLog().debug("Command line options:");
+ getLog().debug(sb);
}
- catch ( CompilerException ce )
- {
- getLog().debug( ce );
- }
- }
+ }
+ catch (CompilerException ce)
+ {
+ getLog().debug(ce);
+ }
+ }
- // ----------------------------------------------------------------------
- // Compile!
- // ----------------------------------------------------------------------
+ // ----------------------------------------------------------------------
+ // Compile!
+ // ----------------------------------------------------------------------
+ if (StringUtils.isEmpty(compilerConfiguration.getSourceEncoding()))
+ {
+ getLog().warn("File encoding has not been set, using platform encoding " + ReaderFactory.FILE_ENCODING
+ + ", i.e. build is platform dependent!");
+ }
- if ( StringUtils.isEmpty( compilerConfiguration.getSourceEncoding() ) )
- {
- getLog().warn( "File encoding has not been set, using platform encoding " + ReaderFactory.FILE_ENCODING
- + ", i.e. build is platform dependent!" );
- }
+ CompilerResult compilerResult;
- CompilerResult compilerResult;
+ if (useIncrementalCompilation)
+ {
+ incrementalBuildHelperRequest.outputDirectory(getOutputDirectory());
+ incrementalBuildHelper.beforeRebuildExecution(incrementalBuildHelperRequest);
- if ( useIncrementalCompilation )
- {
- incrementalBuildHelperRequest.outputDirectory( getOutputDirectory() );
+ getLog().debug("incrementalBuildHelper#beforeRebuildExecution");
+ }
- incrementalBuildHelper.beforeRebuildExecution( incrementalBuildHelperRequest );
+ try
+ {
+ try
+ {
+ compilerResult = compiler.performCompile(compilerConfiguration);
+ }
+ catch (CompilerNotImplementedException cnie)
+ {
+ List<CompilerError> messages = compiler.compile(compilerConfiguration);
+ compilerResult = convertToCompilerResult(messages);
+ }
+ }
+ catch (Exception e)
+ {
+ // TODO: don't catch Exception
+ throw new MojoExecutionException("Fatal error compiling", e);
+ }
- getLog().debug( "incrementalBuildHelper#beforeRebuildExecution" );
- }
+ if (useIncrementalCompilation)
+ {
+ if (incrementalBuildHelperRequest.getOutputDirectory().exists())
+ {
+ getLog().debug("incrementalBuildHelper#afterRebuildExecution");
+ // now scan the same directory again and create a diff
+ incrementalBuildHelper.afterRebuildExecution(incrementalBuildHelperRequest);
+ keepDependencyInfo(incrementalBuildHelper, dependencyInfo);
+ }
+ else
+ {
+ getLog().debug(
+ "skip incrementalBuildHelper#afterRebuildExecution as the output directory doesn't exist");
+ }
+ }
- try
- {
- try
- {
- compilerResult = compiler.performCompile( compilerConfiguration );
- }
- catch ( CompilerNotImplementedException cnie )
- {
- List<CompilerError> messages = compiler.compile( compilerConfiguration );
- compilerResult = convertToCompilerResult( messages );
- }
- }
- catch ( Exception e )
- {
- // TODO: don't catch Exception
- throw new MojoExecutionException( "Fatal error compiling", e );
- }
+ List<CompilerMessage> warnings = new ArrayList<CompilerMessage>();
+ List<CompilerMessage> errors = new ArrayList<CompilerMessage>();
+ for (CompilerMessage message : compilerResult.getCompilerMessages())
+ {
+ if (message.isError())
+ {
+ errors.add(message);
+ }
+ else
+ {
+ warnings.add(message);
+ }
+ }
- if ( useIncrementalCompilation )
- {
- if ( incrementalBuildHelperRequest.getOutputDirectory().exists() )
+ if (failOnError && !compilerResult.isSuccess())
+ {
+ if (!warnings.isEmpty())
+ {
+ getLog().info("-------------------------------------------------------------");
+ getLog().warn("COMPILATION WARNING : ");
+ getLog().info("-------------------------------------------------------------");
+ for (CompilerMessage warning : warnings)
{
- getLog().debug( "incrementalBuildHelper#afterRebuildExecution" );
- // now scan the same directory again and create a diff
- incrementalBuildHelper.afterRebuildExecution( incrementalBuildHelperRequest );
+ getLog().warn(warning.toString());
}
- else
- {
- getLog().debug(
- "skip incrementalBuildHelper#afterRebuildExecution as the output directory doesn't exist" );
- }
- }
+ getLog().info(warnings.size() + ((warnings.size() > 1) ? " warnings " : " warning"));
+ getLog().info("-------------------------------------------------------------");
+ }
- List<CompilerMessage> warnings = new ArrayList<CompilerMessage>();
- List<CompilerMessage> errors = new ArrayList<CompilerMessage>();
- for ( CompilerMessage message : compilerResult.getCompilerMessages() )
- {
- if ( message.isError() )
+ if (!errors.isEmpty())
+ {
+ getLog().info("-------------------------------------------------------------");
+ getLog().error("COMPILATION ERROR : ");
+ getLog().info("-------------------------------------------------------------");
+ for (CompilerMessage error : errors)
{
- errors.add( message );
+ getLog().error(error.toString());
}
- else
- {
- warnings.add( message );
- }
- }
+ getLog().info(errors.size() + ((errors.size() > 1) ? " errors " : " error"));
+ getLog().info("-------------------------------------------------------------");
+ }
- if ( failOnError && !compilerResult.isSuccess() )
- {
- if ( !warnings.isEmpty() )
- {
- getLog().info( "-------------------------------------------------------------" );
- getLog().warn( "COMPILATION WARNING : " );
- getLog().info( "-------------------------------------------------------------" );
- for ( CompilerMessage warning : warnings )
- {
- getLog().warn( warning.toString() );
- }
- getLog().info( warnings.size() + ( ( warnings.size() > 1 ) ? " warnings " : " warning" ) );
- getLog().info( "-------------------------------------------------------------" );
- }
+ if (!errors.isEmpty())
+ {
+ throw new CompilationFailureException(errors);
+ }
+ else
+ {
+ throw new CompilationFailureException(warnings);
+ }
+ }
+ else
+ {
+ for (CompilerMessage message : compilerResult.getCompilerMessages())
+ {
+ getLog().warn(message.toString());
+ }
+ }
+ }
- if ( !errors.isEmpty() )
- {
- getLog().info( "-------------------------------------------------------------" );
- getLog().error( "COMPILATION ERROR : " );
- getLog().info( "-------------------------------------------------------------" );
- for ( CompilerMessage error : errors )
- {
- getLog().error( error.toString() );
- }
- getLog().info( errors.size() + ( ( errors.size() > 1 ) ? " errors " : " error" ) );
- getLog().info( "-------------------------------------------------------------" );
- }
+ protected CompilerResult convertToCompilerResult(List<CompilerError> compilerErrors)
+ {
+ if (compilerErrors == null)
+ {
+ return new CompilerResult();
+ }
+ List<CompilerMessage> messages = new ArrayList<CompilerMessage>(compilerErrors.size());
+ boolean success = true;
+ for (CompilerError compilerError : compilerErrors)
+ {
+ messages.add(
+ new CompilerMessage(compilerError.getFile(), compilerError.getKind(), compilerError.getStartLine(),
+ compilerError.getStartColumn(), compilerError.getEndLine(),
+ compilerError.getEndColumn(), compilerError.getMessage()));
+ if (compilerError.isError())
+ {
+ success = false;
+ }
+ }
- if ( !errors.isEmpty() )
- {
- throw new CompilationFailureException( errors );
- }
- else
- {
- throw new CompilationFailureException( warnings );
- }
- }
- else
- {
- for ( CompilerMessage message : compilerResult.getCompilerMessages() )
- {
- getLog().warn( message.toString() );
- }
- }
- }
+ return new CompilerResult(success, messages);
+ }
- protected CompilerResult convertToCompilerResult( List<CompilerError> compilerErrors )
- {
- if ( compilerErrors == null )
- {
- return new CompilerResult();
- }
- List<CompilerMessage> messages = new ArrayList<CompilerMessage>( compilerErrors.size() );
- boolean success = true;
- for ( CompilerError compilerError : compilerErrors )
- {
- messages.add(
- new CompilerMessage( compilerError.getFile(), compilerError.getKind(), compilerError.getStartLine(),
- compilerError.getStartColumn(), compilerError.getEndLine(),
- compilerError.getEndColumn(), compilerError.getMessage() ) );
- if ( compilerError.isError() )
- {
- success = false;
- }
- }
+ /**
+ * @return all source files for the compiler
+ */
+ private Set<File> getCompileSources(Compiler compiler, CompilerConfiguration compilerConfiguration)
+ throws MojoExecutionException, CompilerException
+ {
+ String inputFileEnding = compiler.getInputFileEnding(compilerConfiguration);
+ if (StringUtils.isEmpty(inputFileEnding))
+ {
+ // see MCOMPILER-199 GroovyEclipseCompiler doesn't set inputFileEnding
+ // so we can presume it's all files from the source directory
+ inputFileEnding = ".*";
+ }
+ SourceInclusionScanner scanner = getSourceInclusionScanner(inputFileEnding);
- return new CompilerResult( success, messages );
- }
+ SourceMapping mapping = getSourceMapping(compilerConfiguration, compiler);
- /**
- * @return all source files for the compiler
- */
- private Set<File> getCompileSources( Compiler compiler, CompilerConfiguration compilerConfiguration )
- throws MojoExecutionException, CompilerException
- {
- String inputFileEnding = compiler.getInputFileEnding( compilerConfiguration );
- if ( StringUtils.isEmpty( inputFileEnding ) )
- {
- // see MCOMPILER-199 GroovyEclipseCompiler doesn't set inputFileEnding
- // so we can presume it's all files from the source directory
- inputFileEnding = ".*";
- }
- SourceInclusionScanner scanner = getSourceInclusionScanner( inputFileEnding );
+ scanner.addSourceMapping(mapping);
- SourceMapping mapping = getSourceMapping( compilerConfiguration, compiler );
+ Set<File> compileSources = new HashSet<File>();
- scanner.addSourceMapping( mapping );
+ for (String sourceRoot : getCompileSourceRoots())
+ {
+ File rootFile = new File(sourceRoot);
- Set<File> compileSources = new HashSet<File>();
+ if (!rootFile.isDirectory())
+ {
+ continue;
+ }
- for ( String sourceRoot : getCompileSourceRoots() )
- {
- File rootFile = new File( sourceRoot );
+ try
+ {
+ compileSources.addAll(scanner.getIncludedSources(rootFile, null));
+ }
+ catch (InclusionScanException e)
+ {
+ throw new MojoExecutionException(
+ "Error scanning source root: \'" + sourceRoot + "\' for stale files to recompile.", e);
+ }
+ }
- if ( !rootFile.isDirectory() )
- {
- continue;
- }
+ return compileSources;
+ }
- try
- {
- compileSources.addAll( scanner.getIncludedSources( rootFile, null ) );
- }
- catch ( InclusionScanException e )
- {
- throw new MojoExecutionException(
- "Error scanning source root: \'" + sourceRoot + "\' for stale files to recompile.", e );
- }
- }
+ /**
+ * @param compilerConfiguration
+ * @param compiler
+ * @return <code>true</code> if at least a single source file is newer than it's class file
+ */
+ private boolean isSourceChanged(CompilerConfiguration compilerConfiguration, Compiler compiler)
+ throws CompilerException, MojoExecutionException
+ {
+ Set<File> staleSources
+ = computeStaleSources(compilerConfiguration, compiler, getSourceInclusionScanner(staleMillis));
- return compileSources;
- }
+ if (getLog().isDebugEnabled())
+ {
+ for (File f : staleSources)
+ {
+ getLog().debug("Stale source detected: " + f.getAbsolutePath());
+ }
+ }
+ return staleSources != null && staleSources.size() > 0;
+ }
- /**
- * @param compilerConfiguration
- * @param compiler
- * @return <code>true</code> if at least a single source file is newer than it's class file
- */
- private boolean isSourceChanged( CompilerConfiguration compilerConfiguration, Compiler compiler )
- throws CompilerException, MojoExecutionException
- {
- Set<File> staleSources =
- computeStaleSources( compilerConfiguration, compiler, getSourceInclusionScanner( staleMillis ) );
+ /**
+ * try to get thread count if a Maven 3 build, using reflection as the plugin must not be maven3 api dependant
+ *
+ * @return number of thread for this build or 1 if not multi-thread build
+ */
+ protected int getRequestThreadCount()
+ {
+ try
+ {
+ Method getRequestMethod = session.getClass().getMethod("getRequest");
+ Object mavenExecutionRequest = getRequestMethod.invoke(this.session);
+ Method getThreadCountMethod = mavenExecutionRequest.getClass().getMethod("getThreadCount");
+ String threadCount = (String) getThreadCountMethod.invoke(mavenExecutionRequest);
+ return Integer.valueOf(threadCount);
+ }
+ catch (Exception e)
+ {
+ getLog().debug("unable to get threadCount for the current build: " + e.getMessage());
+ }
+ return 1;
+ }
- if ( getLog().isDebugEnabled() )
- {
- for ( File f : staleSources )
- {
- getLog().debug( "Stale source detected: " + f.getAbsolutePath() );
- }
- }
- return staleSources != null && staleSources.size() > 0;
- }
+ protected Date getBuildStartTime()
+ {
+ try
+ {
+ Method getRequestMethod = session.getClass().getMethod("getRequest");
+ Object mavenExecutionRequest = getRequestMethod.invoke(session);
+ Method getStartTimeMethod = mavenExecutionRequest.getClass().getMethod("getStartTime");
+ Date buildStartTime = (Date) getStartTimeMethod.invoke(mavenExecutionRequest);
+ return buildStartTime;
+ }
+ catch (Exception e)
+ {
+ getLog().debug("unable to get start time for the current build: " + e.getMessage());
+ }
+ return new Date();
+ }
- /**
- * try to get thread count if a Maven 3 build, using reflection as the plugin must not be maven3 api dependant
- *
- * @return number of thread for this build or 1 if not multi-thread build
- */
- protected int getRequestThreadCount()
- {
- try
- {
- Method getRequestMethod = session.getClass().getMethod( "getRequest" );
- Object mavenExecutionRequest = getRequestMethod.invoke( this.session );
- Method getThreadCountMethod = mavenExecutionRequest.getClass().getMethod( "getThreadCount" );
- String threadCount = (String) getThreadCountMethod.invoke( mavenExecutionRequest );
- return Integer.valueOf( threadCount );
- }
- catch ( Exception e )
- {
- getLog().debug( "unable to get threadCount for the current build: " + e.getMessage() );
- }
- return 1;
- }
+ private String getMemoryValue(String setting)
+ {
+ String value = null;
- protected Date getBuildStartTime()
- {
- try
- {
- Method getRequestMethod = session.getClass().getMethod( "getRequest" );
- Object mavenExecutionRequest = getRequestMethod.invoke( session );
- Method getStartTimeMethod = mavenExecutionRequest.getClass().getMethod( "getStartTime" );
- Date buildStartTime = (Date) getStartTimeMethod.invoke( mavenExecutionRequest );
- return buildStartTime;
- }
- catch ( Exception e )
- {
- getLog().debug( "unable to get start time for the current build: " + e.getMessage() );
- }
+ // Allow '128' or '128m'
+ if (isDigits(setting))
+ {
+ value = setting + "m";
+ }
+ else if ((isDigits(setting.substring(0, setting.length() - 1))) && (setting.toLowerCase().endsWith(
+ "m")))
+ {
+ value = setting;
+ }
+ return value;
+ }
- return new Date();
- }
+ //TODO remove the part with ToolchainManager lookup once we depend on
+ //3.0.9 (have it as prerequisite). Define as regular component field then.
+ private Toolchain getToolchain()
+ {
+ Toolchain tc = null;
+ if (toolchainManager != null)
+ {
+ tc = toolchainManager.getToolchainFromBuildContext("jdk", session);
+ }
+ return tc;
+ }
+ private boolean isDigits(String string)
+ {
+ for (int i = 0; i < string.length(); i++)
+ {
+ if (!Character.isDigit(string.charAt(i)))
+ {
+ return false;
+ }
+ }
+ return true;
+ }
- private String getMemoryValue( String setting )
- {
- String value = null;
+ private Set<File> computeStaleSources(CompilerConfiguration compilerConfiguration, Compiler compiler,
+ SourceInclusionScanner scanner)
+ throws MojoExecutionException, CompilerException
+ {
+ SourceMapping mapping = getSourceMapping(compilerConfiguration, compiler);
- // Allow '128' or '128m'
- if ( isDigits( setting ) )
- {
- value = setting + "m";
- }
- else if ( ( isDigits( setting.substring( 0, setting.length() - 1 ) ) ) && ( setting.toLowerCase().endsWith(
- "m" ) ) )
- {
- value = setting;
- }
- return value;
- }
+ File outputDirectory;
+ CompilerOutputStyle outputStyle = compiler.getCompilerOutputStyle();
+ if (outputStyle == CompilerOutputStyle.ONE_OUTPUT_FILE_FOR_ALL_INPUT_FILES)
+ {
+ outputDirectory = buildDirectory;
+ }
+ else
+ {
+ outputDirectory = getOutputDirectory();
+ }
- //TODO remove the part with ToolchainManager lookup once we depend on
- //3.0.9 (have it as prerequisite). Define as regular component field then.
- private Toolchain getToolchain()
- {
- Toolchain tc = null;
- if ( toolchainManager != null )
- {
- tc = toolchainManager.getToolchainFromBuildContext( "jdk", session );
- }
- return tc;
- }
+ scanner.addSourceMapping(mapping);
- private boolean isDigits( String string )
- {
- for ( int i = 0; i < string.length(); i++ )
- {
- if ( !Character.isDigit( string.charAt( i ) ) )
+ Set<File> staleSources = new HashSet<File>();
+
+ for (String sourceRoot : getCompileSourceRoots())
+ {
+ File rootFile = new File(sourceRoot);
+
+ if (!rootFile.isDirectory())
+ {
+ continue;
+ }
+
+ try
+ {
+ staleSources.addAll(scanner.getIncludedSources(rootFile, outputDirectory));
+ }
+ catch (InclusionScanException e)
+ {
+ throw new MojoExecutionException(
+ "Error scanning source root: \'" + sourceRoot + "\' for stale files to recompile.", e);
+ }
+ }
+
+ return staleSources;
+ }
+
+ private SourceMapping getSourceMapping(CompilerConfiguration compilerConfiguration, Compiler compiler)
+ throws CompilerException, MojoExecutionException
+ {
+ CompilerOutputStyle outputStyle = compiler.getCompilerOutputStyle();
+
+ SourceMapping mapping;
+ if (outputStyle == CompilerOutputStyle.ONE_OUTPUT_FILE_PER_INPUT_FILE)
+ {
+ mapping = new SuffixMapping(compiler.getInputFileEnding(compilerConfiguration),
+ compiler.getOutputFileEnding(compilerConfiguration));
+ }
+ else if (outputStyle == CompilerOutputStyle.ONE_OUTPUT_FILE_FOR_ALL_INPUT_FILES)
+ {
+ mapping = new SingleTargetSourceMapping(compiler.getInputFileEnding(compilerConfiguration),
+ compiler.getOutputFile(compilerConfiguration));
+
+ }
+ else
+ {
+ throw new MojoExecutionException("Unknown compiler output style: '" + outputStyle + "'.");
+ }
+ return mapping;
+ }
+
+ /**
+ * @todo also in ant plugin. This should be resolved at some point so that it does not need to be calculated continuously - or should the
+ * plugins accept empty source roots as is?
+ */
+ private static List<String> removeEmptyCompileSourceRoots(List<String> compileSourceRootsList)
+ {
+ List<String> newCompileSourceRootsList = new ArrayList<String>();
+ if (compileSourceRootsList != null)
+ {
+ // copy as I may be modifying it
+ for (String srcDir : compileSourceRootsList)
+ {
+ if (!newCompileSourceRootsList.contains(srcDir) && new File(srcDir).exists())
{
- return false;
+ newCompileSourceRootsList.add(srcDir);
}
- }
- return true;
- }
+ }
+ }
+ return newCompileSourceRootsList;
+ }
- private Set<File> computeStaleSources( CompilerConfiguration compilerConfiguration, Compiler compiler,
- SourceInclusionScanner scanner )
- throws MojoExecutionException, CompilerException
- {
- SourceMapping mapping = getSourceMapping( compilerConfiguration, compiler );
+ /**
+ * We just compare the timestamps of all local dependency files (inter-module dependency classpath) and the own generated classes and if
+ * we got a file which is >= the buid-started timestamp, then we catched a file which got changed during this build.
+ *
+ * @return <code>true</code> if at least one single dependency has changed.
+ */
+ protected boolean isDependencyChanged(IncrementalBuildHelper incrementalBuildHelper, Map<File, byte[]> dependencyInfo) throws MojoExecutionException
+ {
+ if (mavenSession == null)
+ {
+ // we just cannot determine it, so don't do anything beside logging
+ getLog().info("Cannot determine build start date, skipping incremental build detection.");
+ return false;
+ }
- File outputDirectory;
- CompilerOutputStyle outputStyle = compiler.getCompilerOutputStyle();
- if ( outputStyle == CompilerOutputStyle.ONE_OUTPUT_FILE_FOR_ALL_INPUT_FILES )
- {
- outputDirectory = buildDirectory;
- }
- else
- {
- outputDirectory = getOutputDirectory();
- }
+ if (fileExtensions == null || fileExtensions.isEmpty())
+ {
+ fileExtensions = new ArrayList<String>();
+ fileExtensions.add(".class");
+ }
- scanner.addSourceMapping( mapping );
+ Date buildStartTime = getBuildStartTime();
- Set<File> staleSources = new HashSet<File>();
+ final File mojoConfigFile = new File(incrementalBuildHelper.getMojoStatusDirectory(), DEPENDENCY_INFO_FILENAME);
+ if (!mojoConfigFile.exists())
+ {
+ getLog().debug("No file " + DEPENDENCY_INFO_FILENAME + " - assume rebuild.");
+ return true;
+ }
- for ( String sourceRoot : getCompileSourceRoots() )
- {
- File rootFile = new File( sourceRoot );
+ Map<File, byte[]> origDependencyInfo;
+ try
+ {
+ FileInputStream fis = new FileInputStream(mojoConfigFile);
+ ObjectInputStream ois = new ObjectInputStream(fis);
+ origDependencyInfo = (Map<File, byte[]>) ois.readObject();
+ ois.close();
+ }
+ catch (FileNotFoundException ex)
+ {
+ getLog().debug("No file " + DEPENDENCY_INFO_FILENAME + " - assume rebuild.", ex);
+ return true;
+ }
+ catch (IOException ex)
+ {
+ getLog().debug("Can't read file " + DEPENDENCY_INFO_FILENAME + " - assume rebuild.", ex);
+ return true;
+ }
+ catch (ClassNotFoundException ex)
+ {
+ getLog().debug("Unexpected exception - assume rebuild.", ex);
+ return true;
+ }
- if ( !rootFile.isDirectory() )
+ for (String classPathElement : getClasspathElements())
+ {
+ File artifactPath = new File(classPathElement);
+ if (artifactPath.isDirectory())
+ {
+ // ProjectArtifacts are artifacts which are available in the local project
+ // that's the only ones we are interested in now.
+ if (hasNewFile(artifactPath, buildStartTime))
{
- continue;
+ getLog().debug("New dependency detected: " + artifactPath.getAbsolutePath());
+ return true;
}
-
- try
+ }
+ else if (artifactPath.isFile())
+ {
+ // + dependent jar files and class files.
+ final File checksum_file = new File(artifactPath.getAbsolutePath() + ".sha1");
+ byte[] checksum = dependencyInfo.get(checksum_file);
+ if (checksum == null)
{
- staleSources.addAll( scanner.getIncludedSources( rootFile, outputDirectory ) );
+ // ignore such dependency.
}
- catch ( InclusionScanException e )
+
+ byte[] origChecksum = origDependencyInfo.get(checksum_file);
+ if (checksum == null)
{
- throw new MojoExecutionException(
- "Error scanning source root: \'" + sourceRoot + "\' for stale files to recompile.", e );
+ // ignore such dependency.
}
- }
+ if (origChecksum == null || !Arrays.equals(origChecksum, checksum))
+ {
+ getLog().debug("New dependency detected: " + artifactPath.getAbsolutePath());
+ return true;
+ }
+ }
+ }
- return staleSources;
- }
+ // obviously there was no new file detected.
+ return false;
+ }
- private SourceMapping getSourceMapping( CompilerConfiguration compilerConfiguration, Compiler compiler )
- throws CompilerException, MojoExecutionException
- {
- CompilerOutputStyle outputStyle = compiler.getCompilerOutputStyle();
+ /**
+ * @param classPathEntry entry to check
+ * @param buildStartTime time build start
+ * @return if any changes occured
+ */
+ private boolean hasNewFile(File classPathEntry, Date buildStartTime)
+ {
+ if (!classPathEntry.exists())
+ {
+ return false;
+ }
- SourceMapping mapping;
- if ( outputStyle == CompilerOutputStyle.ONE_OUTPUT_FILE_PER_INPUT_FILE )
- {
- mapping = new SuffixMapping( compiler.getInputFileEnding( compilerConfiguration ),
- compiler.getOutputFileEnding( compilerConfiguration ) );
- }
- else if ( outputStyle == CompilerOutputStyle.ONE_OUTPUT_FILE_FOR_ALL_INPUT_FILES )
- {
- mapping = new SingleTargetSourceMapping( compiler.getInputFileEnding( compilerConfiguration ),
- compiler.getOutputFile( compilerConfiguration ) );
+ if (classPathEntry.isFile())
+ {
+ return classPathEntry.lastModified() >= buildStartTime.getTime() && fileExtensions.contains(
+ FileUtils.getExtension(classPathEntry.getName()));
+ }
- }
- else
- {
- throw new MojoExecutionException( "Unknown compiler output style: '" + outputStyle + "'." );
- }
- return mapping;
- }
+ File[] children = classPathEntry.listFiles();
- /**
- * @todo also in ant plugin. This should be resolved at some point so that it does not need to
- * be calculated continuously - or should the plugins accept empty source roots as is?
- */
- private static List<String> removeEmptyCompileSourceRoots( List<String> compileSourceRootsList )
- {
- List<String> newCompileSourceRootsList = new ArrayList<String>();
- if ( compileSourceRootsList != null )
- {
- // copy as I may be modifying it
- for ( String srcDir : compileSourceRootsList )
- {
- if ( !newCompileSourceRootsList.contains( srcDir ) && new File( srcDir ).exists() )
- {
- newCompileSourceRootsList.add( srcDir );
- }
- }
- }
- return newCompileSourceRootsList;
- }
+ for (File child : children)
+ {
+ if (hasNewFile(child, buildStartTime))
+ {
+ return true;
+ }
+ }
- /**
- * We just compare the timestamps of all local dependency files (inter-module dependency classpath)
- * and the own generated classes
- * and if we got a file which is >= the buid-started timestamp, then we catched a file which got
- * changed during this build.
- *
- * @return <code>true</code> if at least one single dependency has changed.
- */
- protected boolean isDependencyChanged()
- {
- if ( mavenSession == null )
- {
- // we just cannot determine it, so don't do anything beside logging
- getLog().info( "Cannot determine build start date, skipping incremental build detection." );
- return false;
- }
+ return false;
+ }
- if ( fileExtensions == null || fileExtensions.isEmpty() )
- {
- fileExtensions = new ArrayList<String>();
- fileExtensions.add( ".class" );
- }
+ private Map<File, byte[]> createDependencyInfo()
+ {
+ Map<File, byte[]> dependencyInfo = new HashMap<File, byte[]>();
- Date buildStartTime = getBuildStartTime();
+ for (String classPathElement : getClasspathElements())
+ {
+ File artifactPath = new File(classPathElement);
+ if (artifactPath.isFile())
+ {
+ // + dependent jar files and class files.
+ File checksum_file = new File(artifactPath.getAbsolutePath() + ".sha1");
+ if (!checksum_file.exists())
+ {
+ continue; // jar files without checksum are not supported.
+ }
+ byte[] checksum = new byte[(int) checksum_file.length()];
+ try
+ {
+ FileInputStream fis = new FileInputStream(checksum_file);
+ fis.read(checksum, 0, (int) checksum_file.length());
+ fis.close();
- for ( String classPathElement : getClasspathElements() )
- {
- // ProjectArtifacts are artifacts which are available in the local project
- // that's the only ones we are interested in now.
- File artifactPath = new File( classPathElement );
- if ( artifactPath.isDirectory() )
+ dependencyInfo.put(checksum_file, checksum);
+ }
+ catch (FileNotFoundException ex)
{
- if ( hasNewFile( artifactPath, buildStartTime ) )
- {
- getLog().debug( "New dependency detected: " + artifactPath.getAbsolutePath() );
- return true;
- }
+ getLog().debug("Can't read md5 file " + checksum_file + " - ignore it.", ex);
}
- }
+ catch (IOException ex)
+ {
+ getLog().debug("Can't read md5 file " + checksum_file + " - ignore it.", ex);
+ }
+ }
+ }
- // obviously there was no new file detected.
- return false;
- }
+ return dependencyInfo;
+ }
- /**
- * @param classPathEntry entry to check
- * @param buildStartTime time build start
- * @return if any changes occured
- */
- private boolean hasNewFile( File classPathEntry, Date buildStartTime )
- {
- if ( !classPathEntry.exists() )
- {
- return false;
- }
+ private void keepDependencyInfo(IncrementalBuildHelper incrementalBuildHelper, Map<File, byte[]> dependencyInfo) throws MojoExecutionException
+ {
+ final File mojoConfigFile = new File(incrementalBuildHelper.getMojoStatusDirectory(), DEPENDENCY_INFO_FILENAME);
+
+ if (dependencyInfo == null)
+ {
+ if (mojoConfigFile.exists())
+ {
+ mojoConfigFile.delete();
+ }
+ return;
+ }
- if ( classPathEntry.isFile() )
- {
- return classPathEntry.lastModified() >= buildStartTime.getTime() && fileExtensions.contains(
- FileUtils.getExtension( classPathEntry.getName() ) );
- }
-
- File[] children = classPathEntry.listFiles();
-
- for ( File child : children )
- {
- if ( hasNewFile( child, buildStartTime ) )
- {
- return true;
- }
- }
-
- return false;
- }
+ try
+ {
+ FileOutputStream fos = new FileOutputStream(mojoConfigFile);
+ ObjectOutputStream oos = new ObjectOutputStream(fos);
+ oos.writeObject(dependencyInfo);
+ oos.close();
+ }
+ catch (FileNotFoundException ex)
+ {
+ getLog().debug("Unexpected exception", ex);
+ }
+ catch (IOException ex)
+ {
+ getLog().debug("Can't write file " + DEPENDENCY_INFO_FILENAME, ex);
+ }
+ }
}
> Incremental build does not track inter-module dependencies.
> -----------------------------------------------------------
>
> Key: MCOMPILER-278
> URL: https://issues.apache.org/jira/browse/MCOMPILER-278
> Project: Maven Compiler Plugin
> Issue Type: Bug
> Affects Versions: 3.1
> Reporter: Michael Zav'yalov
>
> When useIncrementalCompilation=true the plugin actually assumes that this incremental compilation is supported by compiler itself (I state it because of all source files are always sent to compiler).
> But plugin provides an additional optimization - it can detect that there are no changes at all, so calling compiler can be skipped. It is especially critical for javac that does not support incremental build since 1.3.
> Unfortunately, plugin ignores claspath dependencies that are not directory, i.e. - jars, so when dependent jar is modified (in incompatible way) - our project is not re-compiled.
--
This message was sent by Atlassian JIRA
(v6.3.4#6332)