Ant任务答疑

普遍问题

经常,groovy或者groovyc任务会因为找不到GroovySourceAst类而抛出ClassNotFoundException,从而导致失败。

原因

如果这是因为找不到除了GroovySourceAst以外的类而抛出ClassNotFoundException,从而导致失败的话,那么欢迎来到Ant的世界。就如Ant的外部任务的手册所说的:“不要添加任何东西到CLASSPATH环境变量——这常常就是导致非常费解的错误的原因。请使用Ant添加库的机制。”并且它的库目录一节中说:“当CLASSPATH环境变量为空时,Ant可以非常好的工作,这实际上就是-noclasspath选项所强制执行的。我们接到了比我们想象中多很多的维护电话是关于classpath问题的(尤其是引用的问题)。”所以请尝试通过ant -noclasspath命令来运行Ant,或者甚至是在你的shell中的完成这个功能的ant的别名。

如果找不到的类是GroovySourceAst,并且上面所说的都没有帮助,那么在你的classpath的某处存在antlr的冲突。这可能是因为你正在使用maven而它其中一部分污染了classpath,或者在你的classpath的某处存在一个不同的antlr jar。

解决方案1:groovy-all

使用groovy发行包中的groovy-all-VERSION.jar,而不是普通的groovy的jar。groovy-all-VERSION.jar已经在一个独立的命名空间中包含了antlr和asm库,所以应该不会和其他库存在冲突。

解决方案2:使用loaderref

有时候不能使用groovy-all-VERSION.jar,例如因为你想在创建jar文件前构建groovy。在这种情况下,你需要添加一个loaderref的任务定义。但是只有那样也不行。你需要添加rootLoaderRef任务来设置这个装载器(loader)引用。例如:

<taskdef name="rootLoaderRef"
         classname="org.codehaus.groovy.ant.RootLoaderRef"
         classpathref="task.classpath"/>
 
<rootLoaderRef ref="tmp.groovy.groovyc">
  <classpath refid="execution.classpath"/>
</rootLoaderRef>
 
<rootLoaderRef />
 
<taskdef name="groovy"
         classname="org.codehaus.groovy.ant.Groovy"
         loaderref="tmp.groovy.groovyc"/>

groovy任务现在通过tmp.groovy.groovyc类装载器被建立,这尽量避免了装载冲突的jar文件,如antlr。在使用由rootLoaderRef定义的loaderref的taskdef之前,执行一次rootLoaderRef任务是非常重要的。

解决方案3:建立适当的classpath

你可能需要调整你的classpath设置,来包含你要使用的jar文件。例如,如果你把groovy的jar文件放在了你的Ant LIB目录下,那么Groovy将在Ant的根类装载器(root classloader)中。如果你现在想引用一个外部的库,如一个JDBC驱动程序,你可能需要把这个库也放在你的Ant LIB目录下,从而使它对于在同一个类装载器中的Groovy可见。同时请查看上面有关loaderref的讨论。

同样,Groovy发行包中没有包含完整的Ant发行包。如果你要使用一些可选的Ant任务,你可能需要添加一些额外的jar文件到你的classpath中,来使用这些额外的特征。这里是一份关于一些需要额外的jar文件的Ant任务的不完整的列表:

Ant任务 附加的Jar文件
junitreport ant-trax.jar, xercesImpl.jar, xml-apis.jar
mail mail.jar, activation.jar, smtp.jar (如果使用了SMTP), ant-javamail.jar (如果需要发送MIME email)
sql your_JDBC_driver

全部解决了?

不是,如果在某处存在冲突的ant的jar文件或common-logging的jar文件,那么这些解决方案都没有作用。解决方案2可以解决更多困难的jar问题,只要你的classpath是尽可能干净的。如果你想以防万一,那么你必须派生(fork)javaVM,这意味着你必须像这样的使用任务:

<!-- 派生一个JVM来避免classpath地狱 -->
    <java classname="org.codehaus.groovy.ant.Groovyc" fork="yes" failonerror="true">
      <classpath refid="project.classpath"/>
      <arg value="${build.classes.dir}"/>
      <arg value="${src.dir}"/>
    </java>

参考

 
wiki/advanced_usage_guide/ant_task_troubleshooting.txt · 最后更改: 2008-08-13 14:39 由 johnny
 
Recent changes RSS feed Creative Commons License Donate Powered by PHP Valid XHTML 1.0 Valid CSS Driven by DokuWiki