2013-06-04 93 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

相關問題