I'm using this because the enhancer plugin couldn't handle long CLASSPATHs on Winodws so using the plugin isn't a valid option.
My module.xml file is pretty much the default file but I only removed the enhance target dependency on compile and copy.metadata. I'm not compiling my .java classes because:
I have many libraries to include and it's a headache if I upgrade any set of libraries.
I don't need to because eclipse actually does that
And I removed the part that archives the whole project folder because I'm just building a JAR.
-->
<echo message="==================================================================="/>
<echo message="Enhancing the MODULE files"/>
<echo message="==================================================================="/>
<!-- the classpath to enhance -->
<path id="module.enhancer.classpath">
<pathelement location="${module.classes.dir}"/>
<path refid="module.lib.classpath"/>
</path>
<!-- define the task enhancer -->
<taskdef name="nucleusenhancer"
classpathref="module.enhancer.classpath"
classname="org.datanucleus.enhancer.tools.EnhancerTask" />
<!-- enhance -->
<nucleusenhancer classpathref="module.enhancer.classpath"/>
</target>
<!--
===================================================================
TARGET : modulearchive
===================================================================
-->
<target name="modulearchive" depends="enhance">
<mkdir dir="${module.archive.dist.dir}"/>
<delete file="${module.archive.dist.dir}/${module.archive.dist.file}"/>
<zip zipfile="${module.archive.dist.dir}/${module.archive.dist.file}">
<zipfileset dir="${module.classes.dir}" prefix="" includes="**/*"/>
</zip>
</target>
Also I'm having this warning that wouldn't go away no matter what I do!
<taskdef name="nucleusenhancer"
classpathref="module.enhancer.classpath"
classname="org.datanucleus.enhancer.tools.EnhancerTask" />
>>>E:\Projects\Core - Module\${module.lib.dir} does not exist.
My module.properties file isn't changed much. I commented properties for WAR building and uncommented properties for JAR building:
#######################################
# SAMPLE FOR JAR MODULE (commented out)
#######################################
module.dir=./
module.lib.dir=${module.dir}/lib/dn
module.lib2.dir=${module.dir}/lib/deps
module.classes.dir=${module.dir}/target/classes
module.src.java.dir=./src/main/java
module.build.debug=on
module.archive.dist.dir=dist
module.archive.dist.file=${name}.jar
module.archive.files=**/*
The folder lib beneath my project's folder holds 2 folders, datanucleus main jars for RDBMS while the other folder holds datanucleus dependencies. My compiled classes are beneath target.
The output is simply the following:
Buildfile: E:\Projects\Core - Module\build.xml
default:
[echo] ===================================================================
[echo] Welcome to the build.
[echo] ===================================================================
enhance:
[echo] ===================================================================
[echo] Enhancing the MODULE files
[echo] ===================================================================
[nucleusenhancer] log4j:WARN No appenders could be found for logger (DataNucleus.Enhancer).
[nucleusenhancer] log4j:WARN Please initialize the log4j system properly.
[nucleusenhancer] DataNucleus Enhancer (version 3.1.0.release) : Enhancement of classes
[nucleusenhancer] DataNucleus Enhancer completed and no classes were enhanced. Consult the log for full details
modulearchive:
[zip] Building zip: E:\Projects\Core - Module\dist\my-module-name.jar
distribution:
[echo] ===================================================================
[echo] Module file ready at: dist/my-module-name.jar
[echo] ===================================================================
BUILD SUCCESSFUL
Total time: 2 seconds
The enhancement is an actual modification to the compiled classes. If you are not compiling the classes first, there will be nothing for it to enhance.
Related
I need to build my multi module application using ant build tool, I am unable find suitable documents. I have few doubts.
Actually our application consists of 7 modules out of which 1 is EAR module(Currently we are building through eclipse without using any build tool).
So my doubt is
can i write a single build.xml i.e in EAR module(EAR project) for building project or do i need to write build.xml for every modules?
and also our project has cyclic dependencies, so is it possible to build using Ant without solving those cyclic dependencies....?
Thanks in advance
you should have separate build.xmls for all of your modules. build.xml of your ear module should call all other module's build files and finally export the ear with ear task which may look like;
<property name="build.dir" value="/path/to/your/build-directory/" />
<property name="src.dir" value="/path/to/ear-module/" />
<target name="generate-module-jars">
<!-- this should build module and export module jar to ${build.dir} -->
<ant antfile="module1/build.xml" target="jar" />
<!-- this should build module and export module jar to ${build.dir} -->
<ant antfile="module2/build.xml" target="jar" />
<!-- this should build module and export module jar to ${build.dir} -->
<ant antfile="module3/build.xml" target="jar" />
</target>
<target name="export-ear" depends="generate-module-jars">
<ear destfile="${build.dir}/myapp.ear" appxml="${src.dir}/metadata/application.xml">
<fileset dir="${build.dir}" includes="*.jar,*.war"/>
</ear>
</target>
You should reorganize your modules removing cyclic dependencies. But still you can use ivy. Or you can self implement an ant task directly calling eclipse's compiler that can handle cyclic dependencies. (if you are using eclipse)
how can I tell ant to find Ivy's jar in my own lib? ant just kept looking at it's home folder even when I've explicitly told it to find the jar somewhere else.
I would recommend removing the ivy jar from the ANT home directory. (For some very odd reason it's not normally packaged with ANT).
Instead I recommend including a special task to ensure ivy is installed.
<available classname="org.apache.ivy.Main" property="ivy.installed"/>
<target name="install-ivy" description="Install ivy" unless="ivy.installed">
<mkdir dir="${user.home}/.ant/lib"/>
<get dest="${user.home}/.ant/lib/ivy.jar" src="http://search.maven.org/remotecontent?filepath=org/apache/ivy/ivy/2.4.0/ivy-2.4.0.jar"/>
<fail message="Ivy has been installed. Run the build again"/>
</target>
Analysis
The ANT manual outlines the order in which jars a loaded by ANT at startup.
-lib jars in the order specified by the -lib elements on the command line
jars from ${user.home}/.ant/lib (unless -nouserlib is set)
jars from ANT_HOME/lib
This will always happen and unfortunately it won't matter what you do inside your build file.....
Jars in the ANT_HOME/lib
In my opinion, putting jars in the ANT_HOME effectively creates a bespoke installation of ANT. It makes your projects less portable across machines, and the customizations are frequently forgotten and undocumented.
So if you have control over the build server I would recommend removing any ANT tasks your find here.
Jars in the ${user.home}/.ant/lib
Placing jars here is less objectionable for the following reasons
Directory owned by the user running the build
Can be ignored at run-time by by using the commandline option -nouserlib
The only jar I put here is ivy... All other jars exist in the ivy cache (including ANT tasks)
You can place Ivy binaries in some folder inside you project folder. For example, in my case, it's etc/build/. I put where ivy.jar and jsch.jar.
After that provide the correct namespace in project defenfition and load Ivy.
<project name="somename" basedir="." xmlns:ivy="antlib:org.apache.ivy.ant">
<target name="ivy-load">
<path id="ivy.lib.path">
<pathelement location="${basedir}/etc/build/ivy.jar"/>
<pathelement location="${basedir}/etc/build/jsch.jar"/>
</path>
<taskdef resource="org/apache/ivy/ant/antlib.xml" uri="antlib:org.apache.ivy.ant" classpathref="ivy.lib.path"/>
</target>
<target name="ivy-init" depends="ivy-load">
<ivy:settings file="${basedir}/etc/ivysettings/ivysettings.xml"/>
<ivy:resolve conf="${ivy.conf}"/>
</target>
...
</project>
I have a Java application that I am packaging into a JAR. I created an Ant script to do that as I need to also add resources to the JAR (icons etc).
Now, I have libraries that I use in my project (Apache HttpClient and a JSON library). I also copy their contents into the JAR, as it is the simplest way.
My build file:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<project default="create_run_jar"
name="Create Runnable Jar">
<target name="create_run_jar">
<jar destfile="C:/Users/Pietu1998/Documents/Java/Whatever.jar"
filesetmanifest="mergewithoutmain">
<manifest>
<attribute name="Main-Class"
value="net.pietu1998.whatever" />
<attribute name="Class-Path" value="." />
</manifest>
<fileset dir="C:/Users/Pietu1998/Documents/Java/Whatever/bin"
includes="*.class" />
<fileset dir="C:/Users/Pietu1998/Documents/Java/Whatever/res" />
<zipfileset excludes="META-INF/**"
src="C:/Users/Pietu1998/Documents/Java/Whatever/lib/commons-codec-1.6.jar" />
<zipfileset excludes="META-INF/**"
src="C:/Users/Pietu1998/Documents/Java/Whatever/lib/commons-logging-1.1.3.jar" />
<!-- More (like 5) JARs -->
</jar>
</target>
</project>
However, the libraries (JARs) have their own META-INF folders, and they have a lot of stuff in them; files like LICENSE, CONDITIONS and also a folder for Maven called maven.
The project is for personal use, so I just want to get rid of the unnecessary stuff. I have tried some ways to exclude all of the META-INF stuff, but something is always left behind.
excludes="META-INF" leaves everything.
excludes="META-INF/**" leaves the maven folder.
**/excludes="META-INF/**", see above.
I believe I could use a lot of include-excludes or patternsets, but it would lead to a lot of repeating.
Is there a way (not for this specific case) to exclude a folder (META-INF here) and all its contents including subdirectories, and preferably with not too much repeating (for a lot of libraries)?
Using excludes="META-INF/**"" works for me (Ant 1.9.3, Windows 7, JDK 1.7.0_51)
Some test after downloading original commons-logging-1.1.3.jar from here :
<project>
<zipfileset excludes="META-INF/**" src="c:/area51/commons-logging-1.1.3.jar" id="foobar"/>
<!-- for output line by line -->
<pathconvert property="foo" refid="foobar">
<map from="c:/area51/commons-logging-1.1.3.jar:" to="${line.separator}"/>
</pathconvert>
<echo>${foo}</echo>
</project>
output contains only classfiles under org/apache/commons/logging/.. :
[echo] commons-logging-1.1.3.jar
[echo] org/apache/commons/logging/Log.class;
[echo] org/apache/commons/logging/LogConfigurationException.class;
[echo] org/apache/commons/logging/LogFactory$1.class;
[echo] org/apache/commons/logging/LogFactory$2.class;
[echo] org/apache/commons/logging/LogFactory$3.class;
[echo] org/apache/commons/logging/LogFactory$4.class;
[echo] org/apache/commons/logging/LogFactory$5.class;
[echo] org/apache/commons/logging/LogFactory$6.class;
[echo] org/apache/commons/logging/LogFactory.class;
[echo] org/apache/commons/logging/LogSource.class;
[echo] org/apache/commons/logging/impl/AvalonLogger.class;
[echo] org/apache/commons/logging/impl/Jdk13LumberjackLogger.class;
[echo] org/apache/commons/logging/impl/Jdk14Logger.class;
[echo] org/apache/commons/logging/impl/Log4JLogger.class;
[echo] org/apache/commons/logging/impl/LogFactoryImpl$1.class;
[echo] org/apache/commons/logging/impl/LogFactoryImpl$2.class;
[echo] org/apache/commons/logging/impl/LogFactoryImpl$3.class;
[echo] org/apache/commons/logging/impl/LogFactoryImpl.class;
[echo] org/apache/commons/logging/impl/LogKitLogger.class;
[echo] org/apache/commons/logging/impl/NoOpLog.class;
[echo] org/apache/commons/logging/impl/ServletContextCleaner.class;
[echo] org/apache/commons/logging/impl/SimpleLog$1.class;
[echo] org/apache/commons/logging/impl/SimpleLog.class;
[echo] org/apache/commons/logging/impl/WeakHashtable$1.class;
[echo] org/apache/commons/logging/impl/WeakHashtable$Entry.class;
[echo] org/apache/commons/logging/impl/WeakHashtable$Referenced.class;
[echo] org/apache/commons/logging/impl/WeakHashtable$WeakKey.class;
[echo] org/apache/commons/logging/impl/WeakHashtable.class
Maybe you forgot to set the update attribute from your jar task to true :
<jar destfile=".." update="true" ..>
to overwrite some already existing jarfile with the same name !?
I found a way to do it with the stars.
<zipfileset excludes="META-INF/**/*" src="C:\library.jar" />
This excludes the META-INF folder and all its contents.
* means it excludes all files inside a folder, and
foo/**/bar means it excludes bar in any level inside foo.
So, foo/**/* excludes every file on every level inside foo.
I am trying to write my first build.xml file for an established java project that has just been moved from Netbeans.
A. The objectives that I'm trying to meet are pretty simplistic:
Using the "dest" target below, copy all the source files (4 in all from 1 package) to src/test that I am trying to create. The source files were copied to the "src/test" directory but then a "test" directory was also getting created in the "src/test" directory, why I'm not sure.
Using the "jar" target below, create a jar that has all the class files under the package name directory - DID NOT WORK AT ALL!
Using the "compile" target to ensure that all the code is compiled successfully but I got a lot of errors. The code does CLEAN and BUILD successfully in Eclipse so I'm not sure what I did wrong in the ANT script and one thing I noticed was that it was trying to compile "8" files when there are only "4". Not sure where the other 4 are coming from though it indicates a duplication. The errors show with regard to a missing symbol seem to refer to import statements regarding required projects that are included in the build path so I'm not sure how to address the issues ANT raises in its compile.
B. Here is my first attempt at creating my first build.xml file but I"m experiencing the problems shown below:
<project name="ThalesDataGenerator" basedir="." default="clean-build">
<property name="src.dir" value="src"/>
<property name="dest.dir" value="${src.dir}/test"/>
<property name="dist.dir" value="dist"/>
<property name="build.dir" value="build"/>
<property name="classes.dir" value="${build.dir}/classes"/>
<property name="jar.dir" value="${build.dir}/${ant.project.name}"/>
<property name="main-class" value="thalesdatagenerator.ThalesDataGenerator"/>
<target name="clean">
<delete dir="${build.dir}"/>
<delete dir="${dest.dir}"/>
</target>
<target name="compile">
<mkdir dir="${classes.dir}"/>
<javac srcdir="${src.dir}" destdir="${classes.dir}"/>
</target>
<target name="dest">
<mkdir dir="${dest.dir}"/>
<copy todir="${dest.dir}">
<fileset dir="${src.dir}" includes="**"/>
</copy>
</target>
<target name="jar" depends="compile">
<mkdir dir="${jar.dir}"/>
<jar destfile="${jar.dir}/ThalesDataGenerator.jar" basedir="${build.dir}">
<manifest>
<attribute name="Main-Class" value="${main-class}"/>
</manifest>
</jar>
</target>
<target name="run" depends="jar">
<java jar="${jar.dir}/${ant.project.name}.jar" fork="true"/>
</target>
<target name="clean-build" depends="clean,dest,jar,run"/>
</project>
Here are the errors I got:
> Buildfile: C:\ATMSwitch\ThalesDataGenerator\build.xml clean:
> [delete] Deleting directory C:\ATMSwitch\ThalesDataGenerator\build
> dest:
> [mkdir] Created dir: C:\ATMSwitch\ThalesDataGenerator\src\test
> [copy] Copying 4 files to C:\ATMSwitch\ThalesDataGenerator\src\test
> [copy] Copied 2 empty directories to 1 empty directory under C:\ATMSwitch\ThalesDataGenerator\src\test
> compile:
> [mkdir] Created dir: C:\ATMSwitch\ThalesDataGenerator\build\classes
> [javac] C:\ATMSwitch\ThalesDataGenerator\build.xml:22: warning: 'includeantruntime' was not set, defaulting to
build.sysclasspath=last; set to false for repeatable builds
> [javac] Compiling 8 source files to C:\ATMSwitch\ThalesDataGenerator\build\classes
> [javac] C:\ATMSwitch\ThalesDataGenerator\src\thalesdatagenerator\ISOUtil.java:36:
duplicate class: thalesdatagenerator.ISOUtil
> [javac] C:\ATMSwitch\ThalesDataGenerator\src\test\thalesdatagenerator\ThalesDataGenerator.java:13:
package common.database does not exist
> [javac] import common.database.Database;
> [javac] ^
> [javac] C:\ATMSwitch\ThalesDataGenerator\src\test\thalesdatagenerator\ThalesSystem.java:13:
package com.sharpbancsystems.atmterminals.thales does not exist
> [javac] Note: C:\ATMSwitch\ThalesDataGenerator\src\test\thalesdatagenerator\ThalesDataGenerator.java
uses unchecked or unsafe operations.
> [javac] Note: Recompile with -Xlint:unchecked for details.
[javac] 18 errors
BUILD FAILED
C:\ATMSwitch\ThalesDataGenerator\build.xml:22: Compile failed; see the compiler error output for details.
Total time: 874 milliseconds
Any help/direction would be greatly appreciated. Regards.
Let's take this one at a time:
A few hints:
Use ${basedir} when defining properties. For example, <property name="src.dir" value="${basedir}/src"/> instead of simply value="src"/>
Don't force a clean as part of your default target. The standard default target should build the jar and that's it. Doing a clean makes you duplicate work that may not be needed. You can use a target named all to clean, build, and execute.
As mentioned above, use the default target names clean to clean up your build, and all to run all targets in your build. Neither of these should be the default target.
Now back to your issue. Your <javac> target looks like this:
<target name="compile">
<mkdir dir="${classes.dir}"/>
<javac srcdir="${src.dir}" destdir="${classes.dir}"/>
</target>
Are you saying that there are no third party jars that your source depends upon? You need to create a compile classpath that includes all of the third party jars your source depends upon. In Eclipse, there's a built in classpath you're using. In Ant, you have to specify this.
Let's assume that all jars you need for your source to compile are stored in ${basedir}/lib. Your compile target needs to look like this:
<target name="compile">
<mkdir dir="${classes.dir}"/>
<path id="compile.classpath">
<fileset dir="${basedir}/lib">
<include name="**/*.jar"/>
</fileset>
</path>
<javac srcdir="${src.dir}"
classpathref="compile.classpath"
destdir="${classes.dir}"/>
</target>
There are many ways of doing this, but this is the easiest syntactically. I use <path> to define a compile.claasspath that contains all of the jars I need. Since they all live in the lib directory, it was pretty easy.
Next, I use the classpathref parameter to specify this classpath when I compile my Java code.
This will get the classes compiled (which isn't happening now). Since compile target fails, the Ant build ends there before the <jar> task is called. Getting the compile to work should allow the rest of your build to work.
happened to me. was because i hadn't copied selenium-server-standalone-3.4.0.jar to my C:\jars dir (ws.jars)
I am using Ant 1.8
I have multiple modules in intelliJ IDEA. Each module has a build.xml and currently i need to browse till build.xml of that file and run ant for every module.
e.g. module B's build success depends on whether module A's build was successful.
Now, i want to update this process. It will be great if an option exists wherein i can write a single build process which will first build distribution for module A and then while building distribution for B, it will be checked if build for module A is successful.
Is there any way using current Ant mechanism. i could see something similar in ivy but i cant use it in my project.
Please suggest an approach using basic Ant features.
The subant task in ANT is the most flexible way to invoke a multi-module build, for example:
<project name="parent" default="build">
<target name="build">
<subant>
<filelist dir=".">
<file name="moduleA/build.xml"/>
<file name="moduleB/build.xml"/>
</filelist>
<target name="clean"/>
<target name="build"/>
</subant>
</target>
</project>
Project structure
|-- build.xml
|-- moduleA
| `-- build.xml
`-- moduleB
`-- build.xml
Note:
In my opinion the most powerful way to use this task is to combine it with the buildlist task from Apache ivy. Let the ivy inter-module dependency declarations automatically determine the module build order.
Thanks Mark!!
Your answer helped me a lot.
In addition to above answer I would like to add details, if properties are being loaded from properties file.
Project Structure:
|-- build.xml
|-- ProjectOne
-- build.xml
-- antbuilds.properties
|-- ProjectTwo
-- build.xml
-- antbuilds.properties
Common ANT build file:
<project name="Parent" default="all">
<target name="ProjectOne">
<subant>
<property file="ProjectOne/antbuilds.properties"/>
<filelist dir=".">
<file name="ProjectOne/build.xml"/>
</filelist>
<target name="deploy"/>
</subant>
</target>
<target name="ProjectTwo">
<subant>
<property file="ProjectTwo/antbuilds.properties"/>
<filelist dir=".">
<file name="ProjectTwo/build.xml"/>
</filelist>
<target name="deploy"/>
</subant>
</target>
<target name="all" depends="ProjectOne, ProjectTwo">
</target>