我已经创建了几个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
条件将从第一个条件吐出,并忽略缺少的类型。但是,这不起作用,而是以“或不支持嵌套的”oldormissing“元素”失败。也许这种做法是徒劳的?
理想情况下,我希望Ant能够处理这个问题,而无需将条件实现拆分为需要显式手动预编译的单独或子项目(如果我可以让Ant自动编译子项目,那会很棒,但是我无法找到一种方法来尽早发生这种情况,以满足需求typedef
)。对于在类中实现的两行逻辑,一个单独的项目肯定会有点过分。
This related question on taskdefs似乎相关,但并不完全适用于此用例AFAICT。
答案 0 :(得分:0)
好的,我从Ant taskdef tutorial得到了一些线索。 typedef
和condition
可以在设置适当属性的目标中更好地使用,但仅在设置前体类时调用。我们可以设置一个特殊的bootstrapping目标,仅在相关的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
,因为后者不允许我指定类路径,因此没有多大用处)
答案 1 :(得分:0)
为什么不用常春藤来填充lib目录,然后只运行常春藤来填充它。
<available file="lib" type="dir" property="local.lib.present"/>
<target name="resolve" unless="local.lib.present">
<ivy:retrieve symlink="true" pattern="lib/[conf]/[artifact].[ext]"/>
</target>
..
<target name="clean">
<delete dir="build"/>
</target>
<target name="clean-all" depends="clean">
<delete dir="lib"/>
<ivy:clean-cache/>
</target>
拥有一个“清理所有”目标,清除所有缓存并实现干净的构建非常重要。
我看到你正在使用符号链接选项,该选项解决了有关本地构建缓存方法所占用空间的可能问题。