我创建了几个Custom Conditions供我的项目构建过程使用。这些细节可能不是很相关,但是它们的逻辑很少,用于有条件地抑制ivy:resolve
任务的运行(这是否是一个好主意是一个单独的问题,但是对于我的项目,这需要增加12只需几秒钟即可完成构建过程,甚至只需读取缓存即可)。
我遇到的问题是,首次构建项目时,这些条件(现在位于使用它们的项目的主源代码树中)的实现不可用。在这种情况下,无论如何我都想运行<ivy:resolve>
,这样我就可以完整地构建项目(包括condition
实现),然后可以使用condition
实现供以后使用。
我试图通过希望or
条件懒惰并在其中使用available
元素来实现这一点:
<typedef onerror="report" name="olderormissing" classname="myproject.buildutils.FileOlderOrMissingCondition" classpath="${main.jar}" />
<condition property="ivy.needs.refresh">
<or>
<!-- fetch new if we don't have the helper classes -->
<not><available classname="myproject.buildutils.FileOlderOrMissingCondition" /></not>
<!-- only fetch ivy deps hourly -->
<olderormissing file="${ivy.build.record}" threshold="3600" />
</or>
</condition>
<!-- Ivy task using the above property -->
<target name="resolve" description="--> retrieve dependencies with ivy" if="${ivy.needs.refresh}">
<ivy:retrieve symlink="true" sync="false" pattern="${jars.dir}/[conf]/[artifact].[ext]" keep="true" log="download-only" />
</target>
我曾希望,如果实现类不可用,则
or
条件将从第一个条件中吐出true并忽略缺失的类型。但是,这不起作用,而是失败“或不支持嵌套的“ olderormissing”元素”。也许这种方法是徒劳的?理想情况下,我希望Ant处理此情况而无需将条件实现拆分为需要显式的手动预编译的单独项目或子项目(如果我可以使Ant自动编译子项目,那很好,但是我可以做到)无法找到一种使这种情况尽早发生的方法,以供需求
typedef
使用。一个单独的项目对于在类中实现的两行逻辑肯定感觉过大。This related question on taskdefs似乎相关,但不适用于此用例AFAICT。
最佳答案
好吧,我从Ant taskdef tutorial那里得到了一些线索。 typedef
和condition
可以在设置适当属性的目标中更好地使用,但是仅在设置前体类时才调用。并且我们可以设置一个特殊的引导目标,以仅在相关的Ant扩展类上运行javac
。我们还需要使实际的检索/解决发生在单独的任务中,因此我们可以强制其独立于条件的值而发生。
<condition property="ant.extensions.missing">
<not>
<available classname="readproject.ant.FileOlderOrMissingCondition" classpath="${main.jar}" />
</not>
</condition>
<target name="ant-bootstrapping" depends="init" if="ant.extensions.missing" description="(internal) build the project-internal Ant extensions if needed">
<antcall target="force-resolve" />
<javac srcdir="${src}" destdir="${build}" classpathref="build.classpath" includeantruntime="false" includes="**/ant/**/*.java" debug="on"/>
</target>
<!-- need to set up the conditions internally, since the custom types are defined in the project itself -->
<target name="pre-resolve" depends="ant-bootstrapping" description="(internal) set up internal variables to determine if Ivy needs refreshing">
<typedef onerror="report" name="olderormissing" classname="myproject.ant.FileOlderOrMissingCondition" classpath="${build}" />
<condition property="ivy.needs.refresh">
<!-- only fetch ivy deps hourly -->
<olderormissing file="${ivy.build.record}" threshold="3600" />
</condition>
</target>
<target name="resolve" description="retrieve dependencies with ivy" if="ivy.needs.refresh" depends="pre-resolve">
<antcall target="force-resolve" />
</target>
<target name="force-resolve" description="Force retrieval of Ivy dependencies">
<ivy:retrieve symlink="true" sync="false" pattern="${jars.dir}/[conf]/[artifact].[ext]" keep="true" log="download-only" />
<ivy:report todir="${ivy.reports}" />
<touch file="${ivy.build.record}" />
</target>
然后,像以前一样,我的主要编译目标取决于
resolve
目标,无论是全新安装还是刷新,一切都令人满意地构建,但是Ivy不会使我的构建时间不必要地慢24倍。(我还应该注意,我在这里使用的是
available
而不是typefound
,因为后者不允许我指定类路径,因此没有太多用处)
关于java - Ant 自定义条件typedef:确保在编译期间可以使用编译的类(鸡肉和鸡蛋),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13678987/