2013-06-04 49 views
6

Tôi có một tệp Ant build.xml hoạt động tốt trên dòng lệnh: nó biên dịch, xây dựng JAR và tôi có thể thực thi phương thức chính từ JAR tốt. Tệp build.xml tham chiếu một số thư viện của bên thứ ba nằm rải rác ở đây và ở đó. Khi xây dựng JAR, tập lệnh không bao gồm tất cả các thư viện của bên thứ ba vào bản thân JAR. Thay vào đó, nó đặt con đường của họ vào biểu hiện của JAR. Điều này giúp giữ cho JAR của tôi mỏng và gọn gàng.Sử dụng classpath của Ant trong Eclipse

Tôi muốn có thể chỉnh sửa và gỡ lỗi dự án của mình trong Eclipse, nhưng tôi không thể tìm thấy cách dễ dàng để làm như vậy. Tôi có thể có dự án của tôi sử dụng các tập tin Ant để xây dựng dự án, và điều đó dường như làm việc. Tuy nhiên, Eclipse là có khó khăn khi tìm các libaries thirdparty, và do đó Eclipse là có hai vấn đề:

  1. nó cho thấy (trong trình soạn thảo văn bản) rất nhiều lỗi biên dịch, vì rất nhiều lớp học là không xác định, và
  2. nó không thể thực thi JAR.

tôi có thể giải quyết cả hai vấn đề trên bằng cách xác định bằng tay, ở hai nơi khác nhau (ví dụ, việc xây dựng con đường qua Properties->Java Build Path->Libraries, và classpath thực hiện qua Run Configurations->Classpath), tất cả các thư viện của bên thứ ba. Nhưng có vẻ như tôi không cần phải làm điều này bằng tay, vì tất cả các thư viện của bên thứ ba đã được liệt kê trong bản kê khai của JAR của tôi. Tôi đang làm gì sai?

Dưới đây là build.xml tập tin của tôi:

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

Bạn có thể thấy rằng tôi có thư viện của bên thứ ba trong một số thư mục (${lib}, ${hive-util}, ${hpdb}, và ${static}). Tôi sử dụng chúng để tạo một số path được gọi là dep.runtime. Sau đó, tôi bao gồm dep.runtime trong tệp kê khai khi tạo jar của tôi. Làm thế nào tôi có thể nhận Eclipse sử dụng cùng một dep.runtime cho đường dẫn xây dựng và đường dẫn lớp khi thực thi?

+0

Kiểm tra tài liệu ở đây: http://help.eclipse.org/juno/index.jsp?topic=%2Forg.eclipse.jdt.doc.user%2Freference%2Fpreferences% 2Fjava% 2Fbuildpath% 2Fref-preferences-user-libraries.htm (Tôi muốn làm cho câu trả lời này, nhưng tôi không có cài đặt Eclipse trong tay) – leeand00

+0

@ leeand00 Tôi không thấy tài liệu đó giúp tôi như thế nào. Trình đơn mà liên kết nói về chính xác trình đơn tôi đang sử dụng để thêm tất cả thư viện của bên thứ ba theo cách thủ công (như giải pháp tạm thời), nhưng đó chính xác là những gì tôi đang cố gắng tránh. – stepthom

+0

Nên có một nút cho biết 'thêm thư mục' hoặc' thêm classpath' trong đó, và đó nên làm các trick ... cho tôi biết nếu nó không. – leeand00

Trả lời

2

Tôi đã đưa ra giải pháp sau đây, lấy cảm hứng từ liên kết được cung cấp bởi @ leeand00.

Trước tiên, tôi đã viết một kịch bản Perl đơn giản (được gọi là genClasspath.pl) tạo tệp .classpath mà Eclipse sử dụng.

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

Sau đó, tôi có tôi gọi build.xml tập tin kịch bản này với nội dung của 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> 

Trở ngại duy nhất là tôi cần phải chạy Ant trên dòng lệnh ít nhất một lần trước khi tôi mở dự án trong Eclipse. Nhưng khi tôi làm, Eclipse có thể biên dịch và thực hiện dự án của tôi tốt, vì classpath giống hệt như của Ant.

+2

Chỉ cần lưu ý rằng Maven có chức năng này. Tôi nhận ra rằng đó không phải là một lựa chọn, vì vậy tôi để lại một bình luận, không phải là một câu trả lời, nhưng Maven có thể tạo các tệp dự án Eclipse và Eclipse với m2e được cài đặt sẽ tự động thêm các mục nhập classpath khi bạn sửa đổi các phụ thuộc. – davidfmatheson

+0

@davidfmatheson là đúng (nhưng địa chỉ câu hỏi của bạn kiến, vì vậy đó là những gì tôi đã đi với ...) – leeand00

3

Một thay thế cho chương trình perl là sử dụng một nhúng 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> 

Ghi chú:

  • Mục tiêu bootstrap sẽ tải về bên thứ 3 jar groovy (Không phụ thuộc vào perl)
  • Groovy có thể truy cập trực tiếp vào đường dẫn ANT "dep.runtime" và lặp lại nội dung của nó
  • Groovy có hỗ trợ tuyệt vời để ghi các tệp XML.

Câu trả lời sau đây tương tự và bổ sung tạo tệp Eclipse .project.

+0

+1 Cách tiếp cận khá thú vị. Tôi không có chuyên gia trong Groovy, nhưng thật tuyệt khi có giải pháp toàn Ant. – stepthom

+0

BTW Tôi chấp nhận câu trả lời của tôi thay vì của bạn bởi vì đối với tôi, sử dụng Perl dễ dàng hơn, bất chấp những lợi thế của Groovy. Nhưng tôi tưởng tượng rất nhiều người tìm ra giải pháp của bạn tốt. – stepthom

Các vấn đề liên quan