There\'s a lot of discussion about Ant and Eclipse, but no previously answered seems to help me.
Here\'s the deal: I am trying to build a Java program that compiles succ
I use the ivy to manage my ANT classpaths, I highly recommend learning how it works.
There is an eclipse plugin that will manage the eclipse classpath from the same ivy.xml file that ANT uses to define it's dependencies.
From the raw ant distribution, first run "ant -f fetch.xml" (or similar) to download a lot of needed dependencies. Add these to your Eclipse project and see if it helps.
I wrote an Ant Task that generates an Eclipse .userlibraries file. You can import the generated file to create a user library in Eclipse. And then use this user library as part of your build path.
To use the task add this to your ant build file:
<target name="createEclipseUserLibraries"
description="Creates classpath and bootclasspatch that can be imported into Eclipse">
<taskdef name="createEclipseUserLibraries"
classname="com.forumsys.tools.CreateEclipseUserLibraries"
classpathref="yourclasspathref"/>
<createEclipseUserLibraries classpathref="classpathref" bootclasspathref="bootclasspathref"/>
</target>
Ant Task. It requires ant.jar to run and compile:
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.Task;
import org.apache.tools.ant.types.Path;
import org.apache.tools.ant.types.Reference;
/**
* A custom tag to create a file the eclipse can import to setup a user libraries.
*
* Created: Mar 29, 2014 9:44:09 AM
*
* @author <a href="mailto:jslopez@gmail.com">Javier S. López</a>
* @version 1.0
*/
public class CreateEclipseUserLibraries extends Task {
public static final String UTF8_ENCODING = "UTF-8";
public static final String DEFAULT_BOOT_CLASSPATH_LIBRARY_NAME = "SYSTEM_LIBRARY";
public static final String DEFAULT_CLASSPATH_LIBRARY_NAME = "LIBRARY";
public static final String DEFAULT_DESTINATION = "Eclipse.userlibraries";
private static final String INDENT = " ";
private Path _classpath;
private Path _bootClasspath;
private String _bootClasspathLibraryName = DEFAULT_BOOT_CLASSPATH_LIBRARY_NAME;
private String _classpathLibraryName = DEFAULT_CLASSPATH_LIBRARY_NAME;
private String _destination = DEFAULT_DESTINATION;
public void setClasspath(final Path classpath) {
if (_classpath == null) {
_classpath = classpath;
} else {
_classpath.append(classpath);
}
}
public void setClasspathRef(final Reference reference) {
if (_classpath == null) {
final Project antProject = getProject();
_classpath = new Path(antProject);
}
_classpath.setRefid(reference);
}
public void setBootClasspath(final Path bootClasspath) {
if (_bootClasspath == null) {
_bootClasspath = bootClasspath;
} else {
_bootClasspath.append(bootClasspath);
}
}
public void setBootClasspathRef(final Reference reference) {
if (_bootClasspath == null) {
final Project antProject = getProject();
_bootClasspath = new Path(antProject);
}
_bootClasspath.setRefid(reference);
}
public void setClasspathLibraryName(final String name) {
if (!isEmpty(name)) {
_classpathLibraryName = name;
}
}
public void setBootClasspathLibraryName(final String name) {
if (!isEmpty(name)) {
_bootClasspathLibraryName = name;
}
}
public void setDestination(final String argDestination) {
if (!isEmpty(argDestination)) {
_destination = argDestination;
}
}
@Override
public void execute() throws BuildException {
if (_classpath == null) {
throw new BuildException("classpath or classpathref attribute must be set");
}
if (_bootClasspath == null) {
throw new BuildException("bootclasspath or bootclasspathref attribute must be set");
}
try {
createUserLibrariesFile();
} catch (final IOException e) {
throw new BuildException(e.getMessage(), e);
}
}
/**
* @throws IOException
*
*/
private void createUserLibrariesFile() throws IOException {
final StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("<?final xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>");
stringBuilder.append("\n");
stringBuilder.append("<eclipse-userlibraries version=\"2\">").append("\n");
createBootClasspathLibrary(stringBuilder);
createClasspathLibrary(stringBuilder);
stringBuilder.append("</eclipse-userlibraries>");
final Project antProject = getProject();
final File baseDir = antProject.getBaseDir();
final File file = new File(baseDir, _destination);
if (file.exists()) {
file.delete();
}
final boolean append = false;
BufferedOutputStream bos = null;
try {
final FileOutputStream fos = new FileOutputStream(file, append);
bos = new BufferedOutputStream(fos);
bos.write(stringBuilder.toString().getBytes(UTF8_ENCODING));
bos.flush();
} finally {
if (bos != null) {
bos.close();
}
}
}
/**
* @param stringBuilder
*
*/
private void createBootClasspathLibrary(final StringBuilder stringBuilder) {
createLibrary(stringBuilder, _bootClasspathLibraryName, true, _bootClasspath);
}
/**
* @param stringBuilder
*/
private void createClasspathLibrary(final StringBuilder stringBuilder) {
createLibrary(stringBuilder, _classpathLibraryName, false, _classpath);
}
/**
* @param stringBuilder
* @param bootClasspathLibraryName
* @param b
* @param bootClasspath
*/
private void createLibrary(final StringBuilder stringBuilder, final String libraryName,
final boolean isSystemLibrary, final Path path) {
stringBuilder.append(INDENT).append("<library name=\"").append(libraryName);
stringBuilder.append("\" systemlibrary=\"").append(Boolean.toString(isSystemLibrary)).append("\">\n");
final String[] paths = path.list();
final Project antProject = getProject();
final File baseDir = antProject.getBaseDir();
final String baseDirName = baseDir.getName();
for (final String strPath : paths) {
final int index = strPath.indexOf(baseDirName);
//Only include the relative path
if (index != -1) {
stringBuilder.append(INDENT).append(INDENT);
stringBuilder.append("<archive path=\"").append(
strPath.substring(index - 1)).append("\"/>\n");
}
}
stringBuilder.append(INDENT).append("</library>\n");
}
public static final boolean isEmpty(final String str) {
return (str == null) || (str.length() == 0);
}
}
I've never found a really clean way to do it, but one "hackish" way to do it is to manipulate the .classpath file eclipse uses (this contains the build path).
So the .classpath is going to have stuff in it like this:
<classpathentry kind="lib" path="C:/jboss-4.2.3.GA/client/jboss-system-client.jar"/>
So you could, for example, write some sort of batch script, etc. which would read your ant file dependencies and put them into the eclipse .classpath file (in the proper format, of course).
But personally, I never fool with such things. What I do is just put all the jars my project needs in one folder, and then in my ant file I have a path set up like this:
<path id="all_libs">
<fileset dir="test_reflib">
<include name="**/*.jar"/>
</fileset>
</path>
test_reflib just needs to be defined to wherever this folder is that contains all the jars.
Then, on the eclipse side you can just do a "Add jars" and navigate to this same folder and just pick all the jars. What's even cooler is that any time you drop new jars into this folder, just click at the root level in the eclipse project and do "Refresh", and then edit the build path and click add jar again and it will only show you the jars that you haven't already added to the build path yet (i.e. the new jar you just dropped into the folder).
This obviously doesn't work too well if you are sharing jars in a central place, but it works pretty well for smaller projects where you can just copy all the jars over to a centralized folder for the project.
We have generated Eclipse .classpath and .project files from Ant for a large project with centrally located jars (100+) (not counting src jars and javadocs). Similar to the build.xml linked from here with the obvious addition of the src and javadoc attributes.