2013-06-04 13 views
6

Mam plik Ant build.xml, który działa dobrze w linii poleceń: kompiluje, buduje JAR i mogę wykonać główną metodę z JAR-a. Plik build.xml odwołuje się do wielu bibliotek stron trzecich, które są rozproszone tu i tam. Podczas budowania JAR skrypt nie zawiera wszystkich bibliotek trzeciej strony w samym JAR. Zamiast tego umieszcza ich ścieżkę w manifeście JAR. Pomaga to utrzymać cienki i uporządkowany JAR.Używanie ścieżki klas Anta w Eclipse

Chciałbym móc edytować i debugować mój projekt w Eclipse, ale nie mogę znaleźć łatwego sposobu na zrobienie tego. Mogę zlecić projektowi użycie pliku Ant w celu zbudowania projektu i to wydaje się działać. Jednak Eclipse ma problemy z znalezieniem thirdparty bibliotekami, a więc Eclipse jest o dwa problemy:

  1. to pokazuje (w edytorze tekstu) wiele błędów kompilacji, ponieważ wiele klas są niezdefiniowane i
  2. nie może wykonać JAR.

mogę rozwiązać obu powyższych problemów przez określenie przez strony, w dwóch miejscach różnica (czyli ścieżka budować poprzez Properties->Java Build Path->Libraries, a ścieżka klasy wykonanie poprzez Run Configurations->Classpath), wszystkie biblioteki osób trzecich. Ale wygląda na to, że nie powinienem robić tego ręcznie, ponieważ wszystkie biblioteki stron trzecich są już wymienione w manifeście JAR. Co ja robię źle?

Oto mój build.xml file:

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

Widać, że mam bibliotek innych firm w kilku katalogach (${lib}, ${hive-util}, ${hpdb} i ${static}). Używam ich do utworzenia path o nazwie dep.runtime. Następnie włączam dep.runtime do manifestu podczas budowania mojego słoika. Jak mogę zmusić Eclipse do używania tego samego dep.runtime dla ścieżki budowania i ścieżki klasy podczas wykonywania?

+0

Sprawdź dokumentację tutaj: http://help.eclipse.org/juno/index.jsp?topic=%2Forg.eclipse.jdt.doc.user%2Freference%2Fpreferences% 2Fjava% 2Fbuildpath% 2Fref-preferences-user-library.htm (Zrobiłbym to, ale nie mam instalacji Eclipse pod ręką) – leeand00

+0

@ leeand00 Nie widzę, w jaki sposób ta dokumentacja pomaga mi. Menu, o którym mówi link, to właśnie menu, którego używam do ręcznego dodawania wszystkich bibliotek zewnętrznych (jako tymczasowe obejście), ale właśnie tego staram się unikać. – stepthom

+0

Powinien być przycisk z napisem 'add directory' lub' add classpath', który powinien wystarczyć. Daj mi znać, jeśli nie. – leeand00

Odpowiedz

2

Wpadłem na następujące obejście, zainspirowane linkiem dostarczonym przez @ leeand00.

Najpierw napisałem prosty skrypt Perla (o nazwie genClasspath.pl), który generuje plik .classpath, którego używa Eclipse.

#!/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"; 

Wtedy, mam wezwanie build.xml pliku Ten skrypt z treścią 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> 

Jedynym haczykiem jest to, że trzeba uruchomić Ant w wierszu polecenia przynajmniej raz, zanim otworzę projekt w Eclipse. Ale kiedy to zrobię, Eclipse jest w stanie skompilować i wykonać mój projekt, w porządku, ponieważ ścieżka klas jest dokładnie taka sama jak Ant.

+2

Tylko uwaga, że ​​Maven ma tę funkcjonalność. Rozumiem, że to nie jest opcja, więc zostawiam komentarz, a nie odpowiedź, ale Maven może generować pliki projektu Eclipse, a Eclipse z zainstalowanym m2e automatycznie doda wpisy ścieżki klasy podczas modyfikowania zależności. – davidfmatheson

+0

@davidfmatheson ma rację (ale twoje pytanie dotyczy mrówek, więc to jest to, co zrobiłem z ...) – leeand00

3

Alternatywą Perl jest w użyciu wbudowany 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> 

Uwagi:

  • ładowania początkowego docelowy pobierze Groovy słoik 3rd party (Nie zależność od Perl)
  • Groovy może uzyskać dostęp do ścieżki ANT "dep.runtime" bezpośrednio i powtórzyć jej zawartość
  • Groovy ma doskonałą obsługę pisania plików XML.

Następująca odpowiedź jest podobna i dodatkowo generuje plik projektu Eclipse.

+0

+1 Całkiem fajne podejście. Nie jestem ekspertem od Groovy, ale miło jest mieć rozwiązanie z wszystkimi Antami. – stepthom

+0

BTW Przyjąłem moją odpowiedź zamiast twojej, ponieważ dla mnie używanie Perla jest łatwiejsze, pomimo zalet Groovy. Ale wyobrażam sobie, że wiele osób znajduje twoje rozwiązanie równie dobrze. – stepthom

Powiązane problemy