Java 使用Ant';Eclipse中的类路径

Java 使用Ant';Eclipse中的类路径,java,eclipse,ant,Java,Eclipse,Ant,我有一个Antbuild.xml文件,它在命令行上运行得很好:它编译、构建JAR,并且我能够从JAR中很好地执行main方法。build.xml文件引用了分散在各处的几个第三方库。在构建JAR时,脚本并不将所有第三方库都包含在JAR中。相反,它将它们的路径放入JAR的清单中。这有助于保持我的罐子苗条整洁 我希望能够在Eclipse中编辑和调试我的项目,但我找不到一种简单的方法来做到这一点。我可以让我的项目使用Ant文件来构建项目,这似乎是可行的。然而,Eclipse在查找第三方库时遇到了困难,因

我有一个Ant
build.xml
文件,它在命令行上运行得很好:它编译、构建JAR,并且我能够从JAR中很好地执行main方法。
build.xml
文件引用了分散在各处的几个第三方库。在构建JAR时,脚本并不将所有第三方库都包含在JAR中。相反,它将它们的路径放入JAR的清单中。这有助于保持我的罐子苗条整洁

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

  • 它(在文本编辑器中)显示了许多编译错误,因为 很多类是未定义的,并且
  • 它无法执行JAR
  • 我可以通过手动在两个不同的位置(即通过
    属性->Java构建路径->库的构建路径和通过
    运行配置->类路径的执行类路径)指定所有第三方库来解决上述两个问题。但似乎我不应该手动执行此操作,因为所有第三方库都已列在我的JAR清单中。我做错了什么

    这是我的
    build.xml
    文件:

    
    


    您可以看到我在几个目录中有第三方库(
    ${lib}
    ${hive util}
    ${hpdb}
    ,和
    ${static}
    )。我使用它们创建一个名为
    dep.runtime
    路径。然后,在构建jar时,我将
    dep.runtime
    包含在清单中如何让Eclipse在执行时对构建路径和类路径使用相同的
    dep.runtime

    首先,我编写了一个简单的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";
    

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

    perl的另一种替代方法是使用嵌入式:

    
    导入groovy.xml.MarkupBuilder
    project.log“创建.classpath”
    新文件(“.classpath”)。带writer{writer->
    def xml=新的MarkupBuilder(编写器)
    xml.classpath(){
    classpathentry(种类:“src”,路径:properties[“src.dir”])
    classpathentry(种类:“输出”,路径:属性[“classes.dir”])
    classpathentry(种类:“con”,路径:“org.eclipse.jdt.launching.JRE_容器”)
    项目。参考。“dep.runtime”。每个{
    classpathentry(种类:“lib”,路径:it)
    }
    }
    }
    
    注:

    • 引导目标将下载第三方groovy jar(不依赖perl)
    • Groovy可以直接访问“dep.runtime”ANT路径并迭代其内容
    • Groovy非常支持编写XML文件
    下面的答案与此类似,并另外生成Eclipse.project文件


    检查此处的文档:(我会回答这个问题,但我手头没有Eclipse安装)@leeand00我不知道该文档对我有什么帮助。链接中提到的菜单正是我用来手动添加所有第三方库的菜单(作为临时解决方案),但这正是我试图避免的。应该有一个按钮,上面写着
    adddirectory
    addclasspath
    ,如果没有,请告诉我。哦,在这里等:@leeand00让我看看我是否理解你的意思:我应该编写一个脚本来编辑
    .classpath
    文件。然后,我应该从
    build.xml
    文件调用脚本,将
    dep.runtime
    变量的内容传递给脚本。诸如此类的吗?请注意Maven有这个功能。我意识到这可能不是一个选项,所以我留下一条评论,而不是答案,但Maven可以生成Eclipse项目文件,安装了m2e的Eclipse会在您修改依赖项时自动添加类路径项。@DavidMatheson是对的(但您的问题地址是ant,所以我使用了…)+1非常酷的方法。我不是Groovy方面的专家,但是拥有一个全Ant的解决方案很好。顺便说一句,我接受了我的答案,而不是你的答案,因为对我来说,尽管Groovy有很多优点,但使用Perl更容易。但我想很多人也会找到你的解决方案。
    #!/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";
    
    <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>
    
    <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>