如何在Android工具中绕过javac增量构建,而不检测应该导致重新编译的更改?
我和我的同事最近将我们的Android工具升级到r19,并发现谷歌引入的新增量构建系统存在问题。增量编译似乎是一个很难解决的问题,而且看起来他们并没有解决它,所以如果我们不小心的话,我们现在的APK就坏了 我向谷歌报告了这个问题,但我想知道是否有其他人看到过这个问题,如果是的话,也许他们可以游说谷歌修复它,这样工程人员就不会关注由于错误的构建脚本而损坏的构建 请看这里:如何在Android工具中绕过javac增量构建,而不检测应该导致重新编译的更改?,android,ant,build,dependencies,javac,Android,Ant,Build,Dependencies,Javac,我和我的同事最近将我们的Android工具升级到r19,并发现谷歌引入的新增量构建系统存在问题。增量编译似乎是一个很难解决的问题,而且看起来他们并没有解决它,所以如果我们不小心的话,我们现在的APK就坏了 我向谷歌报告了这个问题,但我想知道是否有其他人看到过这个问题,如果是的话,也许他们可以游说谷歌修复它,这样工程人员就不会关注由于错误的构建脚本而损坏的构建 请看这里: 作为一种解决方法,我修改了Ant脚本,在Google的Ant脚本中的-build设置步骤之前删除了所有类文件。该错误中描述的问
作为一种解决方法,我修改了Ant脚本,在Google的Ant脚本中的-build设置步骤之前删除了所有类文件。该错误中描述的问题实际上与.class文件没有维护足够的信息以允许工具正确计算依赖项有关。Javac甚至没有走那么远,相反,只有当java文件比相应的.class文件更新时才重新编译。这甚至是故意的 我能找到的唯一肯定的答案是每次构建时删除所有类文件,使构建不是增量的。可以通过将以下内容添加到build.xml中来实现:
<target name="-pre-compile" depends="-pre-compile-delete"/>
<target name="-pre-compile-delete">
<!-- Workaround for https://code.google.com/p/android/issues/detail?id=31242 -->
<do-only-if-manifest-hasCode elseText="hasCode = false. Skipping...">
<delete failonerror="false" dir="${out.classes.absolute.dir}"/>
</do-only-if-manifest-hasCode>
</target>
JDK解决这一问题的内置工具是。它尝试遍历类文件,并删除其可传递依赖项已更改的文件。然而,正如文档中所指出的,depend有一些局限性,这些局限性都源于类文件没有包含足够的信息来提供完整的依赖关系树
相反,我建议使用。如果任何源/jar较新,我们将删除所有类文件,而不是尝试使用depend任务获得最小的增量编译。我们可以在实际上不需要的时候重新编译,但是没有更改的构建速度更快,并且在需要编译的情况下,我们不会无意中跳过编译
<target name="-pre-compile" depends="-pre-compile-dependset" />
<target name="-pre-compile-dependset">
<!-- Alternative workaround for https://code.google.com/p/android/issues/detail?id=31242 -->
<echo>Deleting all class files if newer sources (java or jars) are found...</echo>
<do-only-if-manifest-hasCode elseText="hasCode = false. Skipping...">
<!-- The names of these properties suggest they are single directories, but -->
<!-- some projects with Android.mk files treat them like paths (with multiple dirs). -->
<!-- Massage these paths get all the files inside multiple dirs. -->
<path id="project.all.sources.path">
<pathelement path="${source.absolute.dir}"/>
<pathelement path="${gen.absolute.dir}"/>
</path>
<!-- convert project.all.sources.path to project.all.sources.list -->
<pathconvert
refid="project.all.sources.path"
property="project.all.sources.list"
pathsep=","
dirsep="/">
<!-- Make the path elements relative to basedir and glob to match all files -->
<!-- The result will look like: "src/**,gen/**" -->
<chainedmapper>
<filtermapper>
<replacestring from="${basedir}/" to=""/>
</filtermapper>
<regexpmapper from="^(.*)" to="\1/**"/>
</chainedmapper>
</pathconvert>
<dependset verbose="true">
<sources>
<!-- merge the project's own classpath and the tested project's classpath -->
<path refid="project.all.jars.path" />
<path refid="tested.project.classpath" />
<!-- All source files -->
<fileset dir="${basedir}" includes="${project.all.sources.list}" />
</sources>
<targets>
<fileset dir="${out.classes.absolute.dir}"/>
</targets>
</dependset>
</do-only-if-manifest-hasCode>
</target>
如果找到较新的源(java或JAR),则删除所有类文件。。。
这个解决方案足够可靠,我相信它最终会被整合到sdk构建中 看起来dependens仍然有局限性,任务描述了这些局限性,例如:如果Java编译器优化了类关系,那么就可能存在没有类依赖性的源依赖性。