Ant - difference between task and target - java

I am new to Ant, and having difficulty in understanding some of its basic things like task and target.
Online documentation and books say that target is a stage of the entire build process, while task is the smallest unti of work. However, I find it very difficult to understand what exactly is meant by this,
Can someone explain in depth with examples what are targets and tasks in Ant?

Targets contain one or more tasks.
A target has a user-defined name, and usually does something high-level like "compile the code", or "build a deployable jar file". It is just a convenient container for tasks (and also allows you to specify dependencies upon other targets).
A task is provided and named by Ant (or plug-ins) and is generally something lower-level like "copy a file", "create a directory". You can create new tasks (see the Ant manual) if the built-in ones don't do what you need.
An example from the Ant tutorial:
<target name="compile">
<mkdir dir="build/classes"/>
<javac srcdir="src" destdir="build/classes"/>
</target>
The target is called "compile" (because it is intended to compile some code. However, the name is arbitrary - I could just as well call it "doUsefulStuff"). To complete this target, we specify that we want to execute two tasks:
Make a directory (using the mkdir task)
Compile some code, and put the compiled classes into the directory from step 1, using the javac task
(Disclaimer - it might be possible to create targets with zero tasks - I haven't checked - but they wouldn't be much use).

Another fundamental difference is that when you run ant you indicate a target (not a task) to be executed. So, when you call ant via command line, you specify ant [options] [target]. If you don't specify the target, the one indicated as default in your build file (build.xml) is executed.
If you open an ant build file on the ant view in Eclipse, the executable options are the targets, not the tasks.
For practical purposes, targets are further divided into private (aka, internal) and public. The difference is that the <target> declaration of a public target contains the description attribute. I mention this because you may want to decompose/refactor a target in sub-steps in your build.xml. The sub-steps can be internal targets.

Related

Can we write a custom target in ant?

However we can create our own tasks using taskdef (as explained here http://www.tutorialspoint.com/ant/ant_extending_ant.htm).
I want to have a custom target like <customtarget name="customtarget"> where we can execute the target from command line as we usually do for <target>.
For Ex: <target name="sometarget">, we do ant sometarget in the same way i should be able to do ant customtarget.
Like custom tasks can we have custom targets ??

custom ant task with additional libraries

i was writing a custom task for ant in java and my idea was that i can give someone the .jar which contains the java files like the classes and the libraries and the build.xml for ant and he can use it.
If i export my java project the .jar (antTask.jar) contains :
a folder for the compiled classes, one for the libraries, meta-inf folder and .classpath .project files
The ant build.xml looks like this:
<?xml version="1.0" ?>
<project name="repair" basedir="." default="repairTask">
<taskdef name="antTask" classpath="antTask.jar" classname="def.RepairTask"/>
<target....
i don't really understand all this classpath stuff, so can someone tell me what i have to add in my build file so it will work only with this .jar file without the java code sources?
right now i am getting an error that ant can't find one of the libraries i use in the java code with this error (but the antTask.jar contains this lib as another .jar):
taskdef A class needed by class def.RepairTask cannot be found: org/apache/commons/...
using the classloader AntClassLoader[C:...\AntTask\antTask.jar]
i am trying for hours but i just can't figure out how i have to edit my build.xml so i just have to point to this single .jar file and it works..
Thank you guys
All a taskdef does is associate a task name to a classfile that contains the code to execute that task. However, in order to find that classfile, you need to tell <taskdef/> where to find the jar that contains it. That's all classpath does is.
You don't have to define a classpath with the <taskdef/> task. Ant by default looks for all jars that contain code for the <taskdef/> tasks in $ANT_HOME/lib. If you copy your jar to that folder, you could simply define that task this way:
<taskdef name="antTask" classname="def.RepairTask"/>
No need for the classpath. However, I actually don't recommend doing that. Instead, I recommend putting that jar file into your project, so other developers can use your project without having to install that task jar into their $ANT_HOME/lib folder:
<taskdef name='antTask' classname="def.RepairTask">
<classpath>
<fileset dir="${basedir}/antlib/antjar"/>
</classpath>
</taskdef>
Now, when a developer checks out the project that requires the optional task jar, that task jar comes with the project, so they can simply do their build.
There are two ways to define tasks. One is to give a task a name, and then tell <taskdef/> what classfile is associated with that jar as you did above. However, you can also define a resource that also will associate task names with their classes. Here's a common way to include the Ant-Contrib ant tasks:
<taskdef resource="net/sf/antcontrib/antcontrib.properties">
<classpath>
<fileset dir="${basedir}/antlib/antcontrib"/>
</classpath>
</taskdef>
If I expand the antcontrib jar, I'll see it contains a net/sf/antcontrib/antcontrib.properties1 file inside the jar. That file looks something like this:
...
# Logic tasks
if=net.sf.antcontrib.logic.IfTask
foreach=net.sf.antcontrib.logic.ForEach
throw=net.sf.antcontrib.logic.Throw
trycatch=net.sf.antcontrib.logic.TryCatchTask
switch=net.sf.antcontrib.logic.Switch
outofdate=net.sf.antcontrib.logic.OutOfDate
runtarget=net.sf.antcontrib.logic.RunTargetTask
timestampselector=net.sf.antcontrib.logic.TimestampSelector
antcallback=net.sf.antcontrib.logic.AntCallBack
antfetch=net.sf.antcontrib.logic.AntFetch
assert=net.sf.antcontrib.logic.Assert
relentless=net.sf.antcontrib.logic.Relentless
# Math Tasks
math=net.sf.antcontrib.math.MathTask
...
All it does is define each task with a classfile for that task. I would recommend you do something similar with your custom ant task. This way, if you decide to include other tasks, you can simply modify this one file, and developers won't have to change their <taskdef/> definition in their jars, or add in multiple ones.
By the way, you should make good and sure that your class doesn't clash with another class that someone else may use. You might want to give your classname a full path that includes a unique prefix:
<taskdef name='antTask' classname="com.vegicorp.anttasks.RepairTask">
Assuming you work for VegiCorp...
1 Ant contrib tasks contain two such files. One is XML format and the other is in properties format. I always use the XML format, and that's what your suppose to use when you define Ant Task resources. I used the properties file because it's a simpler format and easier to see what's going on.

creating javadoc with ant for only the dependent classes of a given class (java file)

I want to create javadoc with ant from a java source file and just from the dependent classes of this file. These are in a java project, but i don't need javadoc from all the java files.
Is there a way to create javadoc like javac
javac includes="package/Java_source.java" destdir="dir/classes"
that compiles the source files and just the dependent classes? If there isn't, then is there another way?
Thanks, Tamas
Well you can add a fileset and / or a packageset parameter:
Example with a fileset:
<javadoc
destdir="docs/api"
author="true"
version="true"
use="true"
windowtitle="Test API">
<fileset dir="src">
<include name="foo/bar/BaseClass.java"/>
<include name="foo/bar/baz/DependentClassA.java"/>
<include name="foo/bar/phleem/DependentClassB.java"/>
</filset>
</javadoc>
But you will have to figure out the dependent classes yourself, I'm afraid.
Reference:
Ant javadoc Task
There is no way to find out what the "dependent classes" are without starting the job. The only thing I can think of is a brutal hack:
On the compiled classes, use a byte code analysis tool like ASM and check all classes in the code base for their usage of your given class (source code analyis is not enough because of possible wildcard imports and same-package usage). From the List of used classes, build a list of source files, and pass that to the Javadoc task (probably best to create an Ant task that does all this). But this is heavy stuff.

Does Ant Support File-based Dependencies?

I would like to make an ant dependency where the target file depends on a source file. How do you describe this in ant?
For example, convert this Make target to ant
data.txt: header1.txt body.txt footer.txt
cat header1.txt body.txt footer.txt > data.txt
You might be able to do something like this, but it's starting to sound like scripting. Ant isn't a scripting language. If you have a lot of "if/then/else" logic in mind you're probably doing it wrong.
Please describe "other data". Are we talking about copying files? Is this a devl/test/prod environment issue? In that case, you can certainly pass in a parameter specifying environment name and using conditional tests to decide which set to copy. Read this to see how.
If you're just wanting to bring files in one directory up-to-date with respect to your source tree,
you might use the sync task. Here's a basic example from the docs:
<sync todir="site">
<fileset dir="generated-site"/>
</sync>
overwrites all files in site with
newer files from generated-site,
deletes files from site that are not
present in generated-site.
If you need to determine which resources need update,
in order to carry out a more complex operation than a sync,
you might use the ant-contrib outofdate task. For example
<outofdate property="compile.needed" outputsourcespath="sources.for.recompile">
<sourcefiles>
<fileset dir="${src}" includes="*.c"/>
</sourcefiles>
<mapper type="glob" dir="${src}" from="*.c" to="${obj}/*.o"/>
</outofdate>
will set compile.needed to true if any object files are out-of-date compared to source,
and also set the path sources.for.recompile with a list of just the sources that need recompile -
you can then compile for just those sources.
(The assumption here is that a single file in the build output area is directly related to one source.)
My simple solution right now is to manually add a test for the source/dest file age in my shell script called from exec task in ant.

Java code for compiling and executing Java programs

I want to compile and execute a set of java programs one after the other.
Please help me out by giving me some example program on how to carry out the task.
Please advise...
Try using Ant
The documentation should answer your questions.
The HelloWorld app can be found here
Can't you call the main() method of the other programs inside your main method?
Example:
ClassB {
public static void main(String[] args) {
System.out.println("ClassB main() Called");
}
}
ClassA {
public static void main(String[] args) {
System.out.println("ClassA main() Called");
ClassB.main(args);
}
}
The output will be
ClassA main() Called
ClassB main() Called
You can also use the java compiler API programmatically. http://download-llnw.oracle.com/javase/6/docs/api/javax/tools/package-summary.html
The necessary tools jars are hidden away in the JDK directory.
When I had to do this I create a perl script that I ran. Within the script I used system calls to execute the java programs (one after the other). I was also able to change directory between the programs.
Use something like apache ant (http://ant.apache.org) or maven (http://maven.apache.org)
Runtime.getRuntime().exec("javac.exe");
Pass the .java filename(s) to compile.
Runtime.getRuntime().exec("java.exe");
Pass the class name to execute.
Why not using NetBeans or Eclipse? But once you got familiar with those tools, try compiling the sourcecode with 'javac' and executing the classes with 'java' from command line
See e.g. http://java.sun.com/developer/onlineTraining/tools/netbeans_part1/
or http://download.oracle.com/javase/tutorial/getStarted/cupojava/netbeans.html
You could use ant
For instance, if you have two java files in the directory src
src/Hello.java
src/Hola.java
Using this build file will compile and run them:
<project default="compile">
<!-- compile everything inside the "src" directory -->
<target name="compile">
<javac srcdir="src" destdir="classes" />
</target>
<!-- run the program named "Hello" followed by the program "Hola" -->
<target name="run" depends="compile">
<java classname="Hello" classpath="classes" />
<java classname="Hello" classpath="classes" />
</target>
</project>
Save the content in a build.xml and then type ant or ant run
$ ant run
Buildfile: build.xml
compile:
[javac] Compiling 2 source files to /Users/oscarryz/Oscar/code/languages/Java/useAnt/classes
run:
[java] Hello
[java] Hello
BUILD SUCCESSFUL
Total time: 0 seconds
To install ant in your system installing ant or this
So basically what you need is a build system, similar to the make and MAKEFILE combination for generic programming. A build system is a usually a program that parses the file which describes what actions the build system needs to make to produce executable. But as usual there can be significantly more things happening (you can execute the compiled files, generate documentation etc.).
So in the example above by OscarRyz, the ant project file defines the source directory where the files are and after compilation runs the files in that directory. The javac tag and java tag.
Good thing about ant is that it's also written in java so you really don't need to do anything else. And the documentation for ant has been pretty good, with examples, worth definitely reading.
I don't think it would be worthwhile, especially if you are beginner to start using weird Runtime constructs or tinkering with javac directly (unless you have significant amount of time available, which we usually don't :)).

Categories

Resources