My current build file has the following repetitive tasks:
<jar jarfile="${build.lib}/${prefix}-foo.jar">
<fileset dir="${build.classes}">
<include name="com/a/c/foo/**"/>
</fileset>
</jar>
<jar jarfile="${build.lib}/${prefix}-bar.jar">
<fileset dir="${build.classes}">
<include name="com/a/c/bar/**"/>
</fileset>
</jar>
... etc. The issue is that the build.xml must be modified for each new package or for each new sub-project. This is a frequent occurrence where I work.
I would like to replace this with logic that will dynamically generate the JARs and their file names based off of a "root" package. So, for example, I could set the root package to be com/a/c, and all packages directly under that package would get their own JAR. Note that all packages under "foo" or "bar" would just be part of "foo.jar" or "bar.jar".
I looked up for loop logic tasks for ANT. I found one in each ant-contrib and JWare/AntXtras, but I could not get either to work as desired.
I don't know about looping over and finding all package names, but you could use a macro to avoid code duplication.
I haven't tried this, but it could work
<macrodef name="build_jar">
<attribute name="name"/>
<sequential>
<jar jarfile="${build.lib}/${prefix}-#{name}.jar">
<fileset dir="${build.classes}">
<include name="com/a/c/#{name}/**"/>
</fileset>
</jar>
</sequential
</macrodef>
<target name="build_foo">
<build_jar name="foo"/>
</target>
<target name="build_bar">
<build_jar name="bar"/>
</target>
How about this:
<project name="dynjar" default="jar" basedir=".">
<property name="build.classes" value="${basedir}/classes"/>
<property name="build.lib" value="${basedir}/lib"/>
<property name="prefix" value="prefix"/>
<property name="root" value="com/a/c"/>
<target name="jar">
<!-- ${ant.file} is the name of the current build file -->
<subant genericantfile="${ant.file}" target="do-jar">
<!-- Pass the needed properties to the subant call. You could also use
the inheritall attribute on the subant element above to pass all
properties. -->
<propertyset>
<propertyref name="build.classes"/>
<propertyref name="build.lib"/>
<propertyref name="prefix"/>
<propertyref name="root"/>
</propertyset>
<!-- subant will call the "do-jar" target for every directory in the
${build.classes}/${root} directory, making the subdirectory the
basedir. -->
<dirset dir="${build.classes}/${root}" includes="*"/>
</subant>
</target>
<target name="do-jar">
<!-- Get the basename of the basedir (foo, bar, etc.) -->
<basename file="${basedir}" property="suffix"/>
<jar jarfile="${build.lib}/${prefix}-${suffix}.jar">
<fileset dir="${build.classes}">
<include name="${root}/${suffix}/**"/>
</fileset>
</jar>
</target>
</project>
Related
Pretty new to ANT and building using it. I have a Java-Jersey rest project and i have included the Jersey libraries under WEB-INF/lib.
I have a build.xml for building/compiling the project.
<?xml version="1.0"?>
<project name="Ant-Test" default="Main" basedir=".">
<!-- Sets variables which can later be used. -->
<!-- The value of a property is accessed via ${} -->
<property name="src.dir" location="src" />
<property name="lib.dir" location="" />
<property name="build.dir" location="bin" />
<!--
Create a classpath container which can be later used in the ant task
-->
<path id="build.classpath">
<fileset dir="${lib.dir}">
<include name="**/*.jar" />
</fileset>
</path>
<!-- Deletes the existing build directory-->
<target name="clean">
<delete dir="${build.dir}" />
</target>
<!-- Creates the build directory-->
<target name="makedir">
<mkdir dir="${build.dir}" />
</target>
<!-- Compiles the java code -->
<target name="compile" depends="clean, makedir">
<javac srcdir="${src.dir}" destdir="${build.dir}" classpathref="build.classpath" />
<jar destfile="${build.dir}/CrunchifyRESTJerseyExample.jar" basedir="${build.dir}"/>
<war destfile="${build.dir}/CrunchifyRESTJerseyExample.war" webxml="WebContent/WEB-INF/web.xml">
<classes dir="${build.dir}"/>
</war>
</target>
<target name="Main" depends="compile">
<description>Main target</description>
</target>
</project>
With this, i am not getting the library files in the war file. What should i add to get it in the war?.
If you take a look on the Ant war task you can specify a <lib> element with the jars that are going to be put under WEB-INF/lib folder. So try this:
<war destfile="${build.dir}/CrunchifyRESTJerseyExample.war" webxml="WebContent/WEB-INF/web.xml">
<classes dir="${build.dir}"/>
<lib dir="${lib.dir}">
<exclude name="jdbc1.jar"/> <!-- Exclude here jars you don't want -->
</lib>
</war>
Note: You should set your property at the begining of your script for the above task to work properly:
<property name="lib.dir" location="lib" /> <!-- Or whatever you call your project folder with the jars-->
try including fileset element as child of war element
<fileset dir="${home.dir}/WEB-INF/libDirectory/*">
<include name="**/*"/>
</fileset>
I'm using build.xml to build my src. However it failed to generate class files without any error message. The full script is
<?xml version="1.0"?>
<project name="auxiliary" basedir="." default="dist">
<property name="src.dir" value="../auxiliary-src/com/nextbio/drugbank"/>
<property name="dist.dir" value="dist"/>
<property name="lib.dir" value="../jboss_config/common_app_jars"/>
<property name="temp.dir" value="temp"/>
<property name="foo_dist.dir" value="../foo/dist"/>
<path id="libs-classpath">
<fileset dir="${foo_dist.dir}">
<include name="foo.jar"/>
</fileset>
</path>
<target name="dist" depends="auxiliary-dist" />
<target name="auxiliary-cleanup">
<delete dir="${temp.dir}"/>
<delete dir="${dist.dir}"/>
<echo message="cleaned up. ${temp.dir}, and ${dist.dir} have been deleted."/>
</target>
<target name ="auxiliary-dist">
<delete dir="${temp.dir}"/>
<echo message="delete ${temp.dir}" />
<mkdir dir="${temp.dir}"/>
<javac destdir="${temp.dir}" source="1.6" target="1.6" debug="on" fork="true" memorymaximumsize="1024m">
<src path="${src.dir}"/>
<classpath>
<path refid="libs-classpath"/>
</classpath>
<include name="com/car/**"/> <!-- troubled line -->
</javac>
<!--<copy overwrite="true" todir="${temp.dir}">
<fileset dir="${src.dir}">
<exclude name="**/*.java"/>
<exclude name="**/*.sql"/>
<exclude name="**/*.txt"/>
</fileset>
</copy>
<delete dir="${dist.dir}"/>
<mkdir dir="${dist.dir}"/>
<jar destfile="${dist.dir}/auxiliary.jar" basedir="${temp.dir}"/> -->
</target>
There is no class file in ${temp.dir} after this step, and no error message. I double checked it, and found it is because of the "troubled line". I tried to add some files to the classpath. I don't know why it is wrong.
The source path should point to the root of the package tree. You make it point to a specific package inside the sources : ../auxiliary-src/com/nextbio/drugbank.
And in the javac task, you ask it to compile all the files matching the pattern com/car/**. That means that it will compile the Java source files in ../auxiliary-src/com/nextbio/drugbank/com/car or in a subdirectory. If that's the case, you have very unconventional package names.
I had the same problem.
My project complilated well but the classes there weren't in nowhere and It didn't have any error message.
My problem was the classpath. The eclipse wizard added EclipseLink 2.5.1 jars.
I removed it and the problem is gone.
I suggest make a simple HelloWord and remove all jars
reference from the classpath and try again.
I encountered this "ant, javac, compile" problem related with the classpath to.
No debug or verbose message shown.
This behavior appear because in classpath exists not compatible (superior) version jar packages and that cause no output classes.
I'm learning these days how to use ant to run automated test folowing this tutorial.
I have JUnit in the classpath of my project. All seem to work fine and I can include it in my classes:
import junit.framework.TestCase; //line20
public class SimpleLattice1DTest extends TestCase{
...
}
My build.xml is:
<?xml version="1.0"?>
<project name="Ant-Test" default="compile" basedir=".">
<!-- Sets variables which can later be used. -->
<!-- The value of a property is accessed via ${} -->
<property name="src.dir" location="." />
<property name="build.dir" location="build" />
<property name="dist.dir" location="dist" />
<property name="docs.dir" location="docs" />
<property name="test.dir" location="jlife/tests" />
<property name="test.report.dir" location="test/report" />
<!-- Deletes the existing build, docs and dist directory-->
<target name="clean">
<delete dir="${build.dir}" />
<delete dir="${docs.dir}" />
<delete dir="${dist.dir}" />
</target>
<!-- Creates the build, docs and dist directory-->
<target name="makedir">
<mkdir dir="${build.dir}" />
<mkdir dir="${docs.dir}" />
<mkdir dir="${dist.dir}" />
<mkdir dir="${test.report.dir}" />
</target>
<!-- Compiles the java code (including the usage of library for JUnit -->
<target name="compile" depends="clean, makedir">
<javac srcdir="${src.dir}" destdir="${build.dir}">
</javac>
</target>
<!-- Creates Javadoc -->
<target name="docs" depends="compile">
<javadoc packagenames="src" sourcepath="${src.dir}" destdir="${docs.dir}">
<!-- Define which files / directory should get included, we include all -->
<fileset dir="${src.dir}">
<include name="**" />
</fileset>
</javadoc>
</target>
<!--Creates the deployable jar file -->
<target name="jar" depends="compile">
<jar destfile="${dist.dir}\CoreTest.jar" basedir="${build.dir}">
<manifest>
<attribute name="Main-Test" value="test.CoreTest" />
</manifest>
</jar>
</target>
<!-- Run the JUnit Tests -->
<!-- Output is XML, could also be plain-->
<target name="junit" depends="compile">
<junit printsummary="on" fork="true" haltonfailure="yes">
<formatter type="xml" />
<batchtest todir="${test.report.dir}">
<fileset dir="${src.dir}">
<include name="**/*Test*.java" />
</fileset>
</batchtest>
</junit>
</target>
</project>
When i run it into eclipse I get the following error:
[javac] C:\Documents and
Settings\noname\Documenti\JLife_git\JLife_git\JLife\src\jlife\tests\SimpleLattice1DTest.java:20:
package junit.framework does not exist
[javac] import junit.framework.TestCase;
I suppose there's something wrong with it, but I have no idea. Could someone put me in the right direction?
Your javac target doesn't specify anything apart from the source and target directory - it doesn't add any classpath entries; you'll need to add an entry for the appropriate JUnit jar file. See the javac task documentation for more details. You may want to specify the path to JUnit as a classpath attribute, a nested element, or a reference to a path declared elsewhere.
The eclipse classpath is separate from your ant environment. In your build file, when you call javac you need to supply a classpath attribute.
You can define the classpath at the top of the file with the rest of your properties, like this:
<path id="classpath">
<fileset dir="[path to libraries]" includes="**/*.jar" />
</path>
and then use it in each call to javac by setting the classpathref attribute, like this:
<javac srcdir="${src.dir}" destdir="${build.dir}" classpathref="classpath" />
You need to specify the directory that contains your .class files and your external jars (like junit).
e.g.
<!-- Populates a class path containing our classes and jars -->
<path id="dist.classpath">
<fileset dir="${lib}"/>
<pathelement path="${build}"/>
</path>
<!-- Compile the java code place into ${build} -->
<target name="compile" depends="-dirty" description="Compile the source.">
<javac srcdir="${source}" destdir="${build}" includeantruntime="false">
<classpath refid="dist.classpath"/>
<exclude name="${test.relative}/**/*"/>
</javac>
</target>
Here's the complete file I took that excerpt from in case you need ideas for how to setup other common things (emma, javadoc, etc)
<project name="imp" default="dist" basedir="..">
<description>Buildscript for IMP</description>
<property name="source" location="src"/>
<property name="lib" location="lib"/>
<property name="history" location="test_history"/>
<property name="web-tests" location="/var/www/tests"/>
<property name="web-files" location="/var/www/files"/>
<property name="web-javadoc" location="/var/www/javadoc"/>
<property name="web-emma" location="/var/www/emma"/>
<property name="emma.dir" value="${lib}"/>
<property name="test" location="${source}/imp/unittest"/>
<property name="test.relative" value="imp/unittest"/>
<property name="javadoc-theme" value="tools/javadoc-theme"/>
<!-- directories for generated files -->
<property name="build" location="build"/>
<property name="build-debug" location="debug"/>
<property name="build-coverage" location="coverage"/>
<property name="dist" location="dist"/>
<property name="reports" location="reports"/>
<property name="coverage-emma" location="${reports}/coverage/emma"/>
<!-- Populates a class path containing our classes and jars -->
<path id="dist.classpath">
<fileset dir="${lib}"/>
<pathelement path="${build}"/>
</path>
<path id="debug.classpath">
<fileset dir="${lib}"/>
<pathelement path="${build-debug}"/>
</path>
<!-- import emma. This classpath limits the coverage to just our classes -->
<path id="debug.imp.classpath">
<pathelement path="${build-debug}"/>
</path>
<taskdef resource="emma_ant.properties" classpathref="debug.classpath"/>
<!--
Shouldn't ever need to use this from the command line. IRC saith that the "private"
internal use only sort of targets are prefixed with '-'.
dirty because it's the opposite of the 'clean' target.
-->
<target name="-dirty">
<tstamp/>
<mkdir dir="${build}"/>
<mkdir dir="${build-debug}"/>
<mkdir dir="${build-coverage}"/>
<mkdir dir="${dist}"/>
<mkdir dir="${reports}"/>
<mkdir dir="${coverage-emma}"/>
</target>
<!-- clean up all the generated files and direcories -->
<target name="clean" description="Deletes all files and directories created by this script.">
<delete dir="${build}"/>
<delete dir="${build-debug}"/>
<delete dir="${build-coverage}"/>
<delete dir="${dist}"/>
<delete dir="${reports}"/>
<delete dir="${coverage-emma}"/>
</target>
<!-- Compile the java code place into ${build} -->
<target name="compile" depends="-dirty" description="Compile the source.">
<javac srcdir="${source}" destdir="${build}" includeantruntime="false">
<classpath refid="dist.classpath"/>
<exclude name="${test.relative}/**/*"/>
</javac>
</target>
<!-- Compile the java code with debug info place into ${build} -->
<target name="compile-debug" depends="-dirty" description="Compile the source with debug information.">
<javac
srcdir="${source}"
destdir="${build-debug}"
includeantruntime="false"
debug="true"
debuglevel="lines,vars,source"
>
<classpath refid="debug.classpath"/>
</javac>
</target>
<!-- roll up everyting into a single jar file -->
<target name="dist" depends="clean, compile" description="Generate the distribution file for IMP.">
<!-- Copy the library .jars to the directory where the IMP distribution will be located -->
<copy todir="${dist}">
<fileset dir="${lib}"/>
</copy>
<!-- TODO: Generate the MANIFEST.MF file on the fly -->
<jar jarfile="${dist}/imp.jar" basedir="${build}" manifest="tools/MANIFEST.MF"/>
<!-- dump to web server -->
<copy todir="${web-files}">
<fileset dir="${dist}"/>
</copy>
</target>
<!-- build and run the tests then report the results in HTML -->
<target name="test" depends="compile-debug" description="Run all the JUnit tests and outputs the results as HTML.">
<!-- run the tests -->
<junit printsummary="true" haltonerror="false" haltonfailure="false">
<classpath refid="debug.classpath"/>
<formatter type="xml"/>
<batchtest fork="true" todir="${reports}">
<fileset dir="${source}">
<include name="${test.relative}/**/*Test*.java"/>
<exclude name="${test.relative}/**/AllTests.java"/>
</fileset>
</batchtest>
</junit>
<!-- report the results -->
<junitreport todir="${reports}">
<fileset dir="${reports}" includes="TEST-*.xml"/>
<report todir="${reports}"/>
</junitreport>
<!-- update the latest results file to be commited -->
<copy file="${reports}/TESTS-TestSuites.xml" tofile="${history}/test-results-latest.xml"/>
<!-- dump to webserver -->
<copy todir="${web-tests}">
<fileset dir="${reports}"/>
</copy>
</target>
<!-- run emma code coverage tool and publish results in HTML -->
<target name="emma" depends="compile-debug" description="Checks code coverage with Emma.">
<!-- put the magic emma juice into the classes -->
<emma>
<instr
instrpathref="debug.imp.classpath"
destdir="${coverage-emma}/instr"
metadatafile="${coverage-emma}/metadata.emma"
merge="true"
/>
</emma>
<!-- run the tests -->
<junit fork="true" printsummary="true" haltonerror="false" haltonfailure="false">
<classpath>
<pathelement location="${coverage-emma}/instr"/>
<path refid="debug.classpath"/>
</classpath>
<batchtest fork="true" todir="${reports}">
<fileset dir="${source}">
<include name="${test.relative}/**/*Test*.java"/>
<exclude name="${test.relative}/**/AllTests.java"/>
</fileset>
</batchtest>
<jvmarg value="-Demma.coverage.out.file=${coverage-emma}/coverage.emma"/>
<jvmarg value="-Demma.coverage.out.merge=true"/>
</junit>
<!-- publish the coverage report -->
<emma>
<report sourcepath="${source}" verbosity="verbose">
<fileset dir="${coverage-emma}">
<include name="*.emma"/>
</fileset>
<html outfile="${web-emma}/index.html"/>
</report>
</emma>
</target>
<!-- publish javadoc -->
<target name="javadoc" description="Creates javadoc for IMP.">
<delete dir="${web-javadoc}"/>
<javadoc
sourcepath="${source}"
defaultexcludes="no"
destdir="${web-javadoc}"
author="true"
version="true"
use="true"
windowtitle="IMP: Integrated Mechanisms Program"
overview="${source}/overview.html"
classpathref="debug.classpath"
stylesheetfile="${javadoc-theme}/stylesheet.css"
/>
<copy file="${javadoc-theme}/javadoc.jpg" tofile="${web-javadoc}/javadoc.jpg"/>
</target>
<target name="all" description="Runs test, emma, javadoc, and dist targets.">
<antcall target="test"/>
<antcall target="emma"/>
<antcall target="javadoc"/>
<antcall target="dist"/>
</target>
</project>
If you observe the error stack, you will find the following line, just above the error line you mentioned...
[javac] [search path for class files: C:\Program Files\Java\jre6\lib\resource...
This line shows all the jars available in the class path for this ant target execution.
You will definitely not find the desired jar over here i.e. junit-x.x.x.jar (junit-4.8.2.jar)
Now go to eclipse -> Window -> preferences -> Ant -> Runtime -> Global Entries -> Add Jars add junit-4.8.2jar (which you will find in your project lib directory)
If you play around the Ant -> Runtime -> classpath and the classpath related error line in the error stack, you will understand the issue.
Hope this solves your problem.
Given a zipfile with an unknown directory, how can I rename or move that directory to a normalized path?
<!-- Going to fetch some stuff -->
<target name="get.remote">
<!-- Get the zipfile -->
<get src="http://myhost.com/package.zip"
dest="package.zip"/>
<!-- Unzip the file -->
<unzip src="package.zip"
dest="./"/>
<!-- Now there is a package-3d28djh3 directory. The part after package- is
a hash and cannot be known ahead of time -->
<!-- Remove the zipfile -->
<delete file="package.zip"/>
<!-- Now we need to rename "package-3d28djh3" to "package". My best attempt
is below, but it just moves package-3d28djh3 into package instead of
renaming the directory. -->
<!-- Make a new home for the contents. -->
<mkdir dir="package" />
<!-- Move the contents -->
<move todir="package/">
<fileset dir=".">
<include name="package-*/*"/>
</fileset>
</move>
</target>
I'm not much of an ant user, any insight would be helpful.
Thanks much, -Matt
This will only work as long as the dirset only returns 1 item.
<project name="Test rename" basedir=".">
<target name="rename">
<path id="package_name">
<dirset dir=".">
<include name="package-*"/>
</dirset>
</path>
<property name="pkg-name" refid="package_name" />
<echo message="renaming ${pkg-name} to package" />
<move file="${pkg-name}" tofile="package" />
</target>
</project>
If there are no subdirectories inside the package-3d28djh3 directory (or whatever it is called once you extracted it) you can use
<move todir="package" flatten="true" />
<fileset dir=".">
<include name="package-*/*"/>
</fileset>
</move>
Otherwise, use the regexp mapper for the move task and get rid of the package-xxx directory:
<move todir="package">
<fileset dir=".">
<include name="package-*/*"/>
</fileset>
<mapper type="regexp" from="^package-.*/(.*)" to="\1"/>
</move>
I am doing some thing obvious wrong. I have a simple applet which needs to upload files to server. I have written an ant script to build the jar file. However, the manifest.mf has class-path split into multiple lines.
Manifest-Version: 1.0
Ant-Version: Apache Ant 1.7.0
Class-Path: lib/commons-codec-1.3.jar lib/commons-httpclien
t-3.1.jar lib/commons-logging-1.0.4.jar lib/plu
gin.jar
Created-By: 14.3-b01-101 (Apple Inc.)
My build.xml is :
<project name="ScreenShot" default="dist" basedir=".">
<description>
simple example build file
</description>
<!-- set global properties for this build -->
<property name="src" location="src" />
<property name="build" location="build" />
<property name="dist" location="dist" />
<target name="init">
<!-- Create the time stamp -->
<tstamp />
<!-- Create the build directory structure used by compile -->
<mkdir dir="${build}" />
</target>
<target name="compile" depends="init" description="compile the source ">
<!-- Compile the java code from ${src} into ${build} -->
<javac srcdir="${src}" destdir="${build}">
<classpath>
<pathelement path="${classpath}" />
<pathelement path="lib/commons-codec-1.3.jar:lib/commons-httpclient-3.1.jar:lib/plugin.jar" />
</classpath>
</javac>
</target>
<target name="dist" depends="compile" description="generate the distribution">
<!-- Create the distribution directory -->
<mkdir dir="${dist}" />
<copy todir="${build}/lib">
<fileset dir="lib/" />
</copy>
<path id="libs.project">
<!-- lib.home contains all jar files, in several subdirectories -->
<fileset dir="lib">
<include name="**/*.jar" />
</fileset>
</path>
<manifestclasspath property="jar.classpath" maxParentLevels="1" jarfile="build/ScreenShot.jar">
<classpath refid="libs.project" />
</manifestclasspath>
<!-- Put everything in ${build} into the MyProject-${DSTAMP}.jar file -->
<jar jarfile="/Users/firemonk/red5/webapps/whiteboard/ScreenShot.jar" basedir="${build}">
<manifest>
<attribute name="Class-Path" value="${jar.classpath}" />
</manifest>
</jar>
</target>
<target name="clean" description="clean up">
<!-- Delete the ${build} and ${dist} directory trees -->
<delete dir="${build}" />
<delete dir="${dist}" />
</target>
</project>
Check the value of ${jar.classpath}. It seems its value itself is in multiple lines.
Does it not work? It's a bit odd that there are big spaces between each classpath entry but it looks valid.
The manifest specification states that lines must be no longer than 72 bytes and that longer lines should be split and continued on the next line with a leading space.