简体   繁体   English

在Eclipse中使用Ant的类路径

[英]Using Ant's classpath in Eclipse

I have an Ant build.xml file that works just fine on the command line: it compiles, builds the JAR, and I am able to execute the main method from the JAR just fine. 我有一个Ant build.xml文件在命令行上运行正常:它编译,构建JAR,我能够从JAR执行main方法就好了。 The build.xml file references several thirdparty libraries that are scattered here and there. build.xml文件引用了分散在这里和那里的几个第三方库。 When building the JAR, the script doesn't include all the thirdparty libraries into the JAR itself. 构建JAR时,脚本不会将所有第三方库都包含在JAR本身中。 Instead, it puts their path into the JAR's manifest. 相反,它将他们的路径放入JAR的清单中。 This helps to keep my JAR slim and tidy. 这有助于保持我的JAR苗条和整洁。

I'd like to be able to edit and debug my project in Eclipse, but I can't find an easy way to do so. 我希望能够在Eclipse中编辑和调试我的项目,但我找不到一个简单的方法。 I can have my project use the Ant file to build the project, and that seems to work. 我可以让我的项目使用Ant文件来构建项目,这似乎有效。 However, Eclipse is having trouble finding the thirdparty libaries, and thus Eclipse is having two problems: 但是,Eclipse无法找到第三方库,因此Eclipse存在两个问题:

  1. it shows (in the text editor) lots of compile errors, because lots of classes are undefined, and 它显示(在文本编辑器中)许多编译错误,因为许多类是未定义的,并且
  2. it can't execute the JAR. 它无法执行JAR。

I can solve both of the above problems by specifying by hand, in two difference places (ie, the build path via Properties->Java Build Path->Libraries , and the execution classpath via Run Configurations->Classpath ), all the third party libraries. 我可以通过手动指定两个不同的地方(即通过Properties->Java Build Path->Libraries构建路径,以及通过Run Configurations->Classpath执行类Run Configurations->Classpath )来解决上述两个问题,所有第三方库。 But it seems like I shouldn't have to do this manually, since all the third party libraries are already listed in my JAR's manifest. 但似乎我不应该手动执行此操作,因为所有第三方库已经列在我的JAR清单中。 What am I doing wrong? 我究竟做错了什么?

Here's my build.xml file: 这是我的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>

You can see that I have third-party libraries in several directories ( ${lib} , ${hive-util} , ${hpdb} , and ${static} ). 您可以看到我在多个目录中有第三方库( ${lib}${hive-util}${hpdb}${static} )。 I use these to create a path called dep.runtime . 我使用它们来创建一个名为dep.runtimepath I then include dep.runtime in the manifest when building my jar. 然后我在构建我的jar时在清单中包含dep.runtime How can I get Eclipse to use the same dep.runtime for the build path and the classpath when executing? 如何让Eclipse在执行时使用相同的dep.runtime作为构建路径和类路径?

An alternative to perl is to use an embedded groovy task : perl的替代方法是使用嵌入式groovy任务

<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>

Notes: 笔记:

  • The bootstrap target will download the 3rd party groovy jar (No dependency on perl) bootstrap目标将下载第三方groovy jar(不依赖于perl)
  • Groovy can access the "dep.runtime" ANT path directly and iterate over its contents Groovy可以直接访问“dep.runtime”ANT路径并迭代其内容
  • Groovy has excellent support for writing XML files. Groovy对编写XML文件有很好的支持。

The following answer is similar and additionally generates the Eclipse .project file. 以下答案类似,另外还生成Eclipse .project文件。

I came up with the following workaround, inspired by the link provided by @leeand00. 我想出了以下解决方法,灵感来自@ leeand00提供的链接。

First, I wrote a simple Perl script (called genClasspath.pl ) that generates the .classpath file that Eclipse uses. 首先,我编写了一个简单的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";

Then, I have my build.xml file call this script with the content of dep.runtime : 然后,我让我的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>

The only catch is that I need to run Ant on the command line at least once before I open the project in Eclipse. 唯一的问题是我需要在Eclipse中打开项目之前至少在命令行上运行一次Ant。 But when I do, Eclipse is able to compile and execute my project just fine, since the classpath is exactly the same as Ant's. 但是当我这样做时,Eclipse能够很好地编译和执行我的项目,因为类路径与Ant完全相同。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM