2013-06-04 70 views
6

我有一个在命令行上工作得很好的Ant build.xml文件:编译,构建JAR,并且能够从JAR执行主方法。 build.xml文件引用了分散在这里和那里的几个第三方库。在构建JAR时,脚本不会将所有第三方库包含到JAR本身中。相反,它将它们的路径放入JAR的清单中。这有助于保持我的JAR苗条和整齐。在Eclipse中使用Ant的类路径

我希望能够在Eclipse中编辑和调试我的项目,但我找不到一个简单的方法来做到这一点。我可以让我的项目使用Ant文件来构建项目,这似乎工作。然而,Eclipse是很难找到的第三方libaries,因此Eclipse的是有两个问题:

  1. 它显示(在文本编辑器)大量编译错误的,因为 很多类是不确定的,并且
  2. 它不能执行JAR。

我可以通过用手指定,在两个差的地方同时解决上述问题(即,经由Properties->Java Build Path->Libraries构建路径,和经由Run Configurations->Classpath执行类路径)中,所有的第三方库。但似乎我不应该手动执行此操作,因为所有第三方库都已列在我的JAR清单中。我究竟做错了什么?

这是我build.xml文件:

<!-- Set global properties for this build --> 
<property name="src"   location="./src" /> 
<property name="build"  location="./build"/> 
<property name="dist"  location="./dist"/> 
<property name="logs"  location="./logs"/> 
<property name="docs"  location="./docs"/> 
<property name="jar"   location="${dist}/dynamic_analyzer.jar"/> 
<property name="lib"   location="../../thirdparty/lib"/> 
<property name="hive-util" location="../../hive-utils/dist"/> 
<property name="hpdb"  location="../../hive-db/hpdb/dist"/> 
<property name="static"  location="../../hive-backend/static_analyzer/dist"/> 
<property name="mainclass" value="com.datawarellc.main.DynamicMain"/> 

<path id="dep.runtime"> 
    <fileset dir="${lib}"  includes="**/*.jar"/> 
    <fileset dir="${hive-util}" includes="**/*.jar"/> 
    <fileset dir="${hpdb}"  includes="**/*.jar"/> 
    <fileset dir="${static}" includes="**/*.jar"/> 
</path> 

<target name="clean"> 
    <delete dir="${build}"/> 
    <delete dir="${dist}"/> 
    <delete dir="${docs}"/> 
    <delete dir="${logs}"/> 
</target> 

<target name="init"> 
    <tstamp/> 
    <mkdir dir="${build}"/> 
    <mkdir dir="${dist}"/> 
    <mkdir dir="${logs}"/> 
</target> 

<target name="compile" depends="init"> 
    <javac srcdir="${src}" destdir="${build}" debug="on" includeantruntime="false"> 
     <classpath refid="dep.runtime" /> 
    </javac> 

    <!-- Debug output of classpath --> 
    <property name="myclasspath" refid="dep.runtime"/> 
    <echo message="Classpath = ${myclasspath}"/> 

</target> 

<target name="jar" depends="compile"> 
    <!-- Put the classpath in the manifest --> 
    <manifestclasspath property="manifest_cp" jarfile="${jar}" maxParentLevels="10"> 
     <classpath refid="dep.runtime" /> 
    </manifestclasspath> 

    <jar jarfile="${jar}" basedir="${build}"> 
     <manifest> 
      <attribute name="Main-Class" value="${mainclass}"/> 
      <attribute name="Class-Path" value="${manifest_cp}"/> 
     </manifest> 
     <zipfileset dir="${src}" includes="**/*.xml" /> 
    </jar> 
</target> 

你可以看到,我有第三方库的几个目录(${lib}${hive-util}${hpdb},并${static})。我使用这些来创建path,称为dep.runtime。然后在构建我的罐子时将dep.runtime包含在清单中。 如何让Eclipse在执行时为构建路径和类路径使用相同的dep.runtime

+0

这里检查文档:http://help.eclipse.org/juno/index.jsp?topic=%2Forg.eclipse.jdt.doc.user%2Freference%2Fpreferences% 2Fjava%2Fbuildpath%2Fref-preferences-user-libraries.htm (我想这是一个答案,但我没有安装Eclipse) – leeand00

+0

@ leeand00我没有看到该文档如何帮助我。链接所说的菜单正是我用来手动添加所有第三方库的菜单(作为临时解决方法),但这正是我想要避免的。 – stepthom

+0

应该有一个按钮,说在那里添加目录或添加类路径,这应该做的伎俩...让我知道,如果它不。 – leeand00

回答

2

我想出了以下解决方法,灵感来自@ leeand00提供的链接。首先,我编写了一个简单的Perl脚本(称为genClasspath.pl),该脚本生成Eclipse使用的.classpath文件。

#!/usr/bin/perl 
use strict; 

if (@ARGV != 2) { 
    print STDERR "Usage: $0 OUTFILE CLASSPATHSTRING\n"; 
    print STDERR "e.g., $0 .classpath path1:path2:path3\n"; 
    exit 1; 
} 

my $OUTFILE   = $ARGV[0]; 
my $CLASSPATHSTRING = $ARGV[1]; 

open my $out_fh, '>', $OUTFILE or die "Couldn't open output file: $!"; 

print $out_fh q{<?xml version="1.0" encoding="UTF-8"?> 
<classpath> 
    <classpathentry kind="src" path="src"/> 
    <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/> 
    <classpathentry kind="output" path="build"/> 
}; 

my @libs = split(":", $CLASSPATHSTRING); 
foreach my $thisLib (@libs){ 
    print $out_fh " <classpathentry kind=\"lib\" path=\"$thisLib\"/>\n"; 
} 
print $out_fh "</classpath>\n"; 

然后,我有我的build.xml文件调用这个脚本的dep.runtime内容:

<target name="compile" depends="init"> 
    <javac srcdir="${src}" destdir="${build}" debug="on" includeantruntime="false"> 
     <classpath refid="dep.runtime" /> 
    </javac> 

    <property name="myclasspath" refid="dep.runtime"/> 

    <exec dir="." executable="../../scripts/genClasspath.pl" os="Linux"> 
     <arg value=".classpath"/> 
     <arg value="${myclasspath}"/> 
    </exec> 

</target> 

,唯一美中不足的是,我需要在命令行中运行Ant至少有一次我打开前Eclipse中的项目。但是当我这样做时,Eclipse能够很好地编译和执行我的项目,因为类路径与Ant完全相同。

+2

只需注意Maven具有此功能。我意识到这可能不是一种选择,所以我留下了一条评论,而不是答案,但Maven可以生成Eclipse项目文件,并且安装了m2e的Eclipse在修改依赖关系时会自动添加类路径条目。 – davidfmatheson

+0

@davidfmatheson是正确的(但你的问题地址蚂蚁,所以这就是我去...) – leeand00

3

的替代Perl是使用嵌入式groovy task

<project name="demo" default="eclipse-files"> 

    <property name="src.dir"  location="src"/> 
    <property name="classes.dir" location="build/classes"/> 

    <path id="dep.runtime"> 
     <fileset dir="${lib}"  includes="**/*.jar"/> 
     <fileset dir="${hive-util}" includes="**/*.jar"/> 
     <fileset dir="${hpdb}"  includes="**/*.jar"/> 
     <fileset dir="${static}" includes="**/*.jar"/> 
    </path> 

    <target name="bootstrap"> 
     <mkdir dir="${user.home}/.ant/lib"/> 
     <get dest="${user.home}/.ant/lib/groovy-all.jar" src="http://search.maven.org/remotecontent?filepath=org/codehaus/groovy/groovy-all/2.1.4/groovy-all-2.1.4.jar"/> 
    </target> 

    <target name="eclipse-files"> 
     <taskdef name="groovy" classname="org.codehaus.groovy.ant.Groovy"/> 
     <groovy> 
      import groovy.xml.MarkupBuilder 

      project.log "Creating .classpath" 

      new File(".classpath").withWriter { writer -> 
       def xml = new MarkupBuilder(writer) 

       xml.classpath() { 
        classpathentry(kind:"src", path:properties["src.dir"]) 
        classpathentry(kind:"output", path:properties["classes.dir"]) 
        classpathentry(kind:"con", path:"org.eclipse.jdt.launching.JRE_CONTAINER") 

        project.references."dep.runtime".each { 
         classpathentry(kind:"lib", path:it) 
        } 
       } 
      } 
     </groovy> 
    </target> 

    <target name="clean"> 
     <delete file=".classpath"/> 
    </target> 

</project> 

注:

  • 的引导目标将下载的第三方常规罐子(Perl的无依赖性)
  • 的Groovy可以直接访问“dep.runtime”ANT路径并迭代其内容
  • Groovy对编写XML文件有出色的支持。

以下答案与此类似,另外生成Eclipse .project文件。

+0

+1非常酷的方法。我不是Groovy的专家,但拥有全Ant解决方案非常好。 – stepthom

+0

顺便说一句,我接受了我的答案,而不是你的答案,因为对我来说,尽管有Groovy的优点,但使用Perl更容易。但我想象很多人找到你的解决方案一样好。 – stepthom

相关问题