The problem described in this error is actually a long-standing limitation of most java compilers and tools related to .class files that are not sufficiently supported to allow tools to correctly calculate dependencies. Javac doesn't even go that far, and instead is recompiled only when the java file is newer than the corresponding .class file. It is by design, even.
The only true answer I can find is to delete all your class files with every creation, making your assemblies non-incremental. You can do this by adding this to your build.xml file:
<target name="-pre-compile" depends="-pre-compile-delete"/> <target name="-pre-compile-delete"> <do-only-if-manifest-hasCode elseText="hasCode = false. Skipping..."> <delete failonerror="false" dir="${out.classes.absolute.dir}"/> </do-only-if-manifest-hasCode> </target>
The built-in JDK tool to solve this problem is a dependent task . It tries to traverse class files and delete files whose transitive dependencies are changed. However, as noted in the documentation, the dependency has some limitations, all of which again stem from class files that do not contain enough information to provide a complete dependency tree.
Instead, I suggest a simpler but reasonably reliable workaround using the dependet task . Instead of trying to get the minimum incremental compilation using the dependency task, we delete all class files if any of the sources / tanks is newer. We can recompile when this is not really necessary, but assemblies without any changes are still faster, and we do not accidentally skip compilation when necessary.
<target name="-pre-compile" depends="-pre-compile-dependset" /> <target name="-pre-compile-dependset"> <echo>Deleting all class files if newer sources (java or jars) are found...</echo> <do-only-if-manifest-hasCode elseText="hasCode = false. Skipping..."> <path id="project.all.sources.path"> <pathelement path="${source.absolute.dir}"/> <pathelement path="${gen.absolute.dir}"/> </path> <pathconvert refid="project.all.sources.path" property="project.all.sources.list" pathsep="," dirsep="/"> <chainedmapper> <filtermapper> <replacestring from="${basedir}/" to=""/> </filtermapper> <regexpmapper from="^(.*)" to="\1/**"/> </chainedmapper> </pathconvert> <dependset verbose="true"> <sources> <path refid="project.all.jars.path" /> <path refid="tested.project.classpath" /> <fileset dir="${basedir}" includes="${project.all.sources.list}" /> </sources> <targets> <fileset dir="${out.classes.absolute.dir}"/> </targets> </dependset> </do-only-if-manifest-hasCode> </target>
This solution is quite reliable, and I believe that it can be included in the sdk assembly in the end.
source share