Ant: javac with proc:only from Ant? - ant

Is there any way to enforce javac task to invoke only annotation processing, without compilation. -proc:only javac option is supposed to enforce such behaviour, according to javac documentation.
But the following snippet of ant buildfile:
<target name="apt">
<javac srcdir="src" destdir="bin" includeantruntime="false">
<compilerarg value="-proc:only"/>
</javac>
</target>
Compiles project anyway. I experimented with other <compilerarg> tag versions (e.g. line instead of value) but nothing helped.

Avoid specifying the "destdir" attribute of the task, or use an empty directory as a destination for class files. The Ant "javac" task will then look for the class files either in the base directory (if you leave "destdir" unset) or in the empty directory. Because it will not find the classs files there, it will not exclude the potentially up-to-date sources from the compilation and execute "javac" on the sources from the directory specified in the "srcdir" attribute.
Your code would therefore look like this:
<target name="apt">
<javac srcdir="src" includeantruntime="false">
<compilerarg value="-proc:only" />
</javac>
</target>
or, if you use the empty directory approach, like this:
<target name="apt">
<mkdir dir="empty" />
<javac srcdir="src" destdir="empty" includeantruntime="false">
<compilerarg value="-proc:only" />
</javac>
</target>
The second approach is slightly more complex but a bit more clean. Usually your project will have an output directory where you put compiled classes and packaged jars, so adding an extra empty directory there would not hurt. As of Ant version 1.9.4, I did not find any other way to do annotation processing from Ant independently of compilation, even though a simple "force" attribute in the "javac" task could solve this problem.

Related

I wonder if there is something wrong with my ant junit task

I'm writing my build.xml. However, it seems there is something go wrong with my junit task. when I run my junit task. I can build success, but the junit report only show that run 1 test with error. But I have more than 10 tests. So I wonder if there is something run with my junit task. Here is my code.
<property name="src.dir" value="src"/>
<property name="bin.dir" value="bin"/>
<property name="dest.dir" value="dest"/>
<property name="test.dir" value="test/>
<property name="lib.dir" value="lib"/>
<path id="classpath">
<pathelement location="${lib.dir}/junit-4.11.jar"/>
<pathelement location="${lib.dir}/ant-junit4.jar"/>
</path>
<target name="test" depends="compile">
<junit printsummary="yes" haltonfailure="no">
<classpath>
<pathelement location="${bin.dir}"/>
<path refid="classpath"/>
</classpath>
<formatter type="plain" usefile="false"/>
<batchtest fork="yes">
<fileset dir="${test.dir}" includes="*Test*.java"/>
</batchtest>
</junit>
</target>
I cannot figure out what is wrong so could somebody help me out?
And what is happening? Do you get any error messages?
You usually need to do the following:
Compile your normal code. The resulting *.class files should be placed inside a directory such as target/classes or build/classes. Use the destdir parameter of the <javac> task to do this.
Compile your JUnit tests.
In your classpath, you need all of the jars you needed to compile your normal classes
You need a reference to the destdir where your normal classes were compiled to.
You need the JUnit jar.
These should be compiled to a different directory from your normal jars. Normally, this is target/test-classes or build/test-classes.
Once you've compiled the JUnit tests, you may run them. You can use the <junit> task like you did.
You need to make sure that the includeantruntime parameter is set to true
You should also set fork to true.
You need the same classpath (with all three elements you had) when you compiled the test classes. More jars might be needed, but usually not.
You run the tests on the compiled JUnit test classfiles (the ones you saved to target/test-classes or build/test-classes. In your example, you're trying to run them against the source.
I use the Maven standards for my directory layout. That means my Java source is under src/main/java while my JUnit Java files are under src/test/java. Any XML or properties or other none source files needed are stored in src/main/resources. The regular source is compiled to target/classes while the Junit sources are compiled to target/test-classes.
This makes it easy to compile your code and test code separately without worrying about **/test/**, **/Test/**, **/JUnit/** exceptions in directory compiling since everything is separate.
Hope this helps.

Ant javadoc generation of tests code cannot find symbol from src code

In my project, I have a src folder with code source of the application and test folder with code source of the application tests.
In my Ant build, I would like to separate javadoc generation of these source codes. For the src code javadoc generation, there is no problem but for the tests code javadoc generation, I've got a problem because test code uses src code.
My Ant task to generate javadoc is like that :
<path id="classpath-test">
<pathelement path="." />
<pathelement path="${testclasses.home}" />
<pathelement path="${classes.home}" />
<fileset dir="${lib.home}" includes="*.jar" />
<fileset dir="${libtest.home}" includes="*.jar" />
</path>
<target name="compile" ... > // compiles src code of the project in ${classes.home}
<target name="compile-tests" depends="compile">
<javac srcdir="${test.home}"
destdir="${testclasses.home}"
target="1.5"
source="1.5"
debug="true"
>
<classpath refid="classpath-test" />
</javac>
<copy todir="${testclasses.home}">
<fileset dir="${test.home}">
<exclude name="**/*.java"/>
</fileset>
</copy>
</target>
<target name="generate-javadoc-tests" depends="compile-tests" >
<javadoc sourcepath="${test.home}" packagenames="*"
destdir="${test-javadoc.home}" verbose="false"
linksource="true" encoding="${encoding}">
<classpath refid="classpath-test" />
</javadoc>
</target>
The ${test.home} variable is test folder. In the classpath-test, I put jar from junit to avoid error about annotation specifics to junit during javadoc generation. This jar is contained in ${libtest.home}.
When I generate javadoc, I have several warnings about code from test folder that using code from src folder which is normal. The errors are like that :
[javadoc] E:\workspace\app\test\com\app\MyClass.java:9: package com.app.SrcClass does not exist
[javadoc] symbol : class MyClass
[javadoc] location: class com.app.MyClass
So, someone knows a way to includes src classes in classpath to avoid these warnings but without having source code javadoc included in test code javadoc.
Or may be a way to disable these warnings because the verbose option of javadoc task to false doesn't disable these warnings.
So, someone knows a way to includes src classes in classpath to avoid
these warnings but without having source code javadoc included in test
code javadoc.
Make sure the classes on which your tests depend are on the classpath. You might want to make your javadoc generation target dependent on the target which compiles code from src and builds a jar file. Then make sure that the classpath, referenced by refid classpath-test includes that jar.

Creating an ear-File with ant

I am new to ant i referred many sites , i need to build.xml for my project which consists
of two modules i have application.xml file which represents corresponding war file
so my question is it sufficient to add the application.xml file
<ear destfile="${dist.dir}/${ant.project.name}.ear" appxml="${conf.dir}/application.xml">
<metainf dir="${build.dir}/META-INF"/>
<fileset dir="${dist.dir}" includes="*.jar,*.war"/>
</ear>
whether this will refer the corresponding war files or i need to compile the whole scenario please let me know. how solve this.
I'm not 100% sure what you're asking.
In order to use the <ear> task, you already need to have compiled the required jars and wars.
If those jars and wars have already been built, you simply refer to them in your <ear> task as you did in your example. The application.xml must already exist before you build your ear. The application.xml doesn't build the jars and wars, you have to do that.
If you haven't already built the wars and jars, you need to do that first. A general outline of a build.xml looks something like this:
<project name="foo" basedir="." default="package">
<!-- Some standard properties you've defined -->
<property name="target.dir" value="${basedir}/target"/>
<property name="xxx" value="yyy"/>
<property name="xxx" value="yyy"/>
<property name="xxx" value="yyy"/>
<!-- Compile properties that allow overrides -->
<property name="javac.nowarn" value="false"/>
<property name="javac.listfiles" value="false"/>
<property name="javac.srcdir" value="source"/>
<property name="javac.distdir" value="${target.dir}/classes"/>
<target name="clean"
description="cleans everything nice and shiny">
<delete dir="${target.dir}"/>
</target>
<target name="compile"
description="Compiles everything">
<mkdir dir="${javac.distdir}"/>
<javac srcdir="${javac.srcdir}"
destdir="${javac.destdir}"
[...]
[...]/>
</target>
<target name="package.jar"
depends="compile"
description="Package jarfile">
<jar destfile="${target.dir}/jarname.jar"
[...]
[...]/>
</target>
<target name="package.jar2"
depends="compile"
description="Package jarfile">
<jar destfile="${target.dir}/jarname2.jar"
[...]
[...]/>
</target>
<target name="package.war"
depends="compile"
description="Package jarfile">
<war destfile="${target.dir}/jarname.jar"
[...]
[...]/>
</target>
<target name="package"
depends="package.jar"
description="Make the ear">
<ear destfile="${target.dir}/earfile.ear"
[...]/>
</target>
</project>
Basically, it consists of a bunch of targets and each target does one task. You can have targets depend upon other targets. For example, this particular build.xml will automatically run the package task. The package task depends upon the package.jar task which depends upon the compile task. Thus, the build.xml file will first call compile, then package.jar, then package.
The important thing to remember is that you don't specify the order of the events. You let Ant figure that out, and you let Ant figure out what you need to do. Let's say you've modified a java source file. Ant knows that it has to recompile only that one file. It also knows that it might have to rebuild the jarfile that contains that classfile. And, it then knows it has to rebuild the ear. Most tasks can figure it out on their own, and you don't do a clean for each build. (You notice that the clean target isn't called by package or compile. You have to call it manually).
The only other thing I recommend is that you try to keep your work area clean. Any files you create should be put into the ${target.dir} directory. That way, when you do a clean, you only have to delete that one directory.
I hope this answer your question.

Is there a way to call the ant 'ant' target with '-lib' option

I'm developing an ant script which is calling another ant script using the <ant> task. This ant script is an installer a Java product and is to be used by our customers, who will have ant installed separately.
The script being called uses the antlr task <antlr:ant-antlr3>. To do this I must place the ant-antlr3.jar file in the ant lib directory, as well as adding antlr-3.2.jar to the classpath.
But I don't want to have this dependency of having ant-antl3.jar file in the client's own installed version of ant.
Is there a way of providing the equivalent to ant's command-line '-lib' option to specify other paths for jars to be added to antlib using the <ant> task itself?
I've taken a look at the online docs and there doesn't seem to be a way.
Thanks
I believe the accepted way to do this is to manually set up your classpath in the build file rather than implicitly including it via the global ant lib directory. i.e.
<path id="master-classpath">
<fileset dir="${lib}" />
<fileset file="${findbugs-base}/lib/annotations.jar" />
<pathelement location="${build-classes}" />
</path>
You can then use this path element in any task that can accept classpath args such as javac
<javac
destdir="${out}"
source="1.5"
target="1.5"
debug="true">
<src path="${src}" />
<classpath refid="master-classpath" />
</javac>
This way, the global ant set up isn't a dependency, and you can specify any files you might need for any build, as specifically as you need to (down to a given call or target).
Obviously, this is all to be carried out in the build file you're calling from the clients' build file. This way, when you call out to yours, the classpath will be set up exactly as you desire.
Another far less idiomatic possibility would be to literally shell out with the Exec Task and call ant that way. Obviously, with the provision of the Ant task, the developers of ant don't recommend you doing that. It is an option, nonetheless.
Tim's answer gives most of the story, but in order to run Ant and set JVM options, you'd need to invoke it via the java task.
There is an example of running this way in the Ant docs, here slightly modified to include -lib:
<java
classname="org.apache.tools.ant.launch.Launcher"
fork="true"
failonerror="true"
dir="${sub.builddir}"
timeout="4000000"
taskname="startAnt"
>
<classpath>
<pathelement location="${ant.home}/lib/ant-launcher.jar"/>
</classpath>
<arg value="-lib"/>
<arg value="${path.to.your.antlr.jar}"/>
<arg value="-buildfile"/>
<arg file="${sub.buildfile}"/>
<arg value="${sub.target}"/>
</java>

How do I pass an argument to an Ant task?

I'm not very good with Ant, but we're using it as a build tool. Right now, we can run "ant test" and it'll run through all the unit tests.
However, I'd love to be able to do something like ant test some_module and have it accept some_module as a parameter, and only test that.
I haven't been able to find how to pass command line args to Ant - any ideas?
One solution might be as follows. (I have a project that does this.)
Have a separate target similar to test with a fileset that restricts the test to one class only. Then pass the name of that class using -D at the ant command line:
ant -Dtest.module=MyClassUnderTest single_test
In the build.xml (highly reduced):
<target name="single_test" depends="compile" description="Run one unit test">
<junit>
<batchtest>
<fileset dir="${test.dir}" includes="**/${test.module}.class" />
</batchtest>
</junit>
</target>
You can also define a property with an optional default value that can be replaced via command line, e.g.
<target name="test">
<property name="moduleName" value="default-module" />
<echo message="Testing Module: ${moduleName}"/>
....
</target>
and run it as:
ant test -DmoduleName=ModuleX
What about using some conditional in your test target and the specifying -Dcondition=true?
<target name="test" depends="_test, _test_if_true>
...
</target>
<target name="_test_if_true" if="condition">
...
</target>
<target name="_test" unless="condition">
...
</target>
Adapted a bit from the ant faq.
You can define a property on commandline when invoking ant:
ant -Dtest.module=mymodulename
Then you can use it as any other ant property:
...
<fileset dir="${test.dir}" includes="**/${test.module}.class" />
...
Have a look at Ant's manual.
I tried the solutions posted here for the very same original question. Yes just use ant -D<arg_name>. THe -D is a "keyword" I guess. I'm no ant expert and have not read the manuals in detail. Then inside the ant XML files can be accessed like: ${arg_name}
For instance you can have an argument name like: arg.myarg, so in XML ${arg.myarg}.
Ant really doesn't have parameters_ for the build file. I can think of a few ways to do this:
Use a special target to specify the tests. You can use the <for/> task from AntContrib to allow you to specify multiple tests. You'll need to download the Ant-Contrib jar file. I recommend placing it inside your project under the `${basedir}/antlib/antcontrib" directory. That way, when others checkout your project, they get the needed Ant-Contrib jar file.
<property name="antlib.dir" value="${basedir}/antlib"/>
<property name="antcontrib.dir" value="${antlib}/antcontrib"/>
<!-- Set up the ant contrib tasks for your use -->
<taskdef resource="net/sf/antcontrib/antlib.xml">
<classpath>
<fileset dir="${antcontrib.dir}"/>
</classpath>
</taskdef>
<target name="select-test"
description="Select the tests to run"
depends="test-compile"
if="junit-tests">
<for parameter="module"
list="${junit-tests}"
delimiter=" ">
<sequential>
<junit
fork="true"
...>
<batchtest todir="$target/unit-tests">
<fileset dir="${test.destdir}">
<include name="**/#{module}.class"/>
</fileset>
</junit>
</sequential>
</for>
</target>
You cab now run multiple tests like this:
$ ant -D"test-one test-two test-three" select-test
You could try this to access one target at a time. Add these lines to your build.xml file :
<project name="whatever" default="default">
<input message="Please select module:" addproperty="mod" />
<target name="default" depends="${mod}/>
...
</project>
This allows you to enter the module you want to execute and execute that itself instead of running the whole build.xml
You might need to make a few more changes to your build.xml for this to work perfectly.
For the arguments , there is Facility called property. You need to set the property. As in ANT plain arguments is taken as target name.
Lest say you have two modules in your project ModuleX and ModuleY where ModuleX has 2 testcases to run and ModuleY with 10 testcases.
You could do something like this :
ant runTestsOnModule -Dtestmodule="ModuleX"
OR to test all modules by calling
ant tests
<target name="runTestsOnModule">
<antCall target="testcase${testmodule}"/>
</target>'
<! -- run single module -->
<target name="runTestsOnModule">
<antCall target="testcase${testmodule}"/>
</target>
<!--run all tests-->
<target name="tests">
<antcall target="testcaseModuleX">
<antcall target="testCaseModuleY">
</target>
<target name="testcaseModuleX">
..run junit task to call 2 testcase
</target>
<target name="testcaseModuleY">
....run junit task to call 10 testcase
</target>

Resources