Relative path problem in ANT junit task - ant

I have setup an ant script as eclipse builder to automatically run all my tests, like below:
<project name="auto-test" default="test">
<property name="tst-dir" location="C:\STAF\services\custom\TopCoder\bin" />
<path id="classpath.base" />
<path id="classpath.test">
<pathelement location="D:\eclipse\eclipse\plugins\org.junit4_4.3.1\junit.jar" />
<pathelement location="${tst-dir}" />
<path refid="classpath.base" />
</path>
<target name="test" description="Run the tests">
<junit>
<classpath refid="classpath.test" />
<formatter type="brief" usefile="false" />
<test name="testDataGenerator.test.AllTests" />
</junit>
</target>
</project>
It was all good before I changed a test fixture file from absolute path to relative path:
SAXReader reader = new SAXReader();
Document document = reader.read(new File(".").getCanonicalPath()+"\\conf\\TestData.xml");
The ant task now try to open D:\eclipse\eclipse\conf\TestData.xml, instead of C:\STAF\services\custom\TopCoder\conf\TestData.xml, I've also try to run AllTests manually from Eclipse and it's all good.
Has anyone met similar problem before?
Thanks in advance.
PS. ANT_HOME=D:\eclipse\eclipse\plugins\org.apache.ant_1.7.0.v200706080842
Follow up:
I tried to run the ant script from command line, and find below:
C:\STAF\services\custom\TopCoder>ant -f c:\STAF\services\custom\TopCoder\task\build.xml, the ant script works correctly.
C:>ant -f c:\STAF\services\custom\TopCoder\task\build.xml, the script will claim: [junit] C:\conf\TestData.xml (The system cannot find the path specified)
I've also checked eclipse builder setting, there seems nothing to change the path to D:\eclipse\eclipse.

Java resolves relative paths against the current user directory, which is typically the directory from where the java program was invoked.
One way to overcome this issue is to define an environmental variable for your base path. Then, you could easily use "relative paths" (meaning, create absolute paths by concatenating the base path and the relative path).

Here is the solution I find:
Just as kgiannakakis mentioned, Ant also start executing its task from the location it was invoked, so we just need to change the working directory setting of our custom eclipse builder.
In the JRE tab, choose "Execution Environment".
Change the Working directory to your current workspace.

Looks like I've missed the karma but anyway...
We do this:-
Build.xml
<project name="whatever">
<property file="build.${env.COMPUTERNAME}.properties"/>
<property file="build.properties"/>
build.properties
project.root=..
build.file.dir=${project.root}/buildfiles
deploy.dir=${project.root}/deploy
which of course you can override by creating your OWN build.computername.properties to allow for developer path differences etc

Related

Ignore full path for specific files when running 'tar' task in ant

I have my proj structure like this
myproj
-bin/myproj-run
-bin/myproj-cli
-lib/x.jar
-target/myproj.jar
I want to create a tar.gz that looks like
myproj
-bin/myproj-run
-bin/myproj-cli
-lib/x.jar
-myproj.jar
How do I do it using ant tar task ?
This one should work (I've tested this on my computer and it works):
<project name="tar.test" default="tartest">
<dirname property="basedir" file="${ant.file.tar.test}" />
<target name="tartest">
<tar destfile="${basedir}/files.tar">
<tarfileset dir="${basedir}/myproj">
<exclude name="target/**" />
</tarfileset>
<tarfileset dir="${basedir}/myproj/target"/>
</tar>
</target>
</project>
BTW, you should read tar manual on apache page, you will find there few examples which shoud help you.
I would first <copy> the files to some other directory (e.g., one called 'package') with the folder structure that you want. Then, run <tar> and <gzip>:
<tar destfile="myTar.tar" basedir="package" />
<gzip src="myTar.tar" destfile="myTar.tar.gz"/>

Change baseDir attribute while using import tag

Let me first provide the background of the problem I'm facing.
I have a directory structure as below.
c:\myDirectory
c:\myDirectory\Project1
c:\myDirectory\Scripts
Under the c:\myDirectory\Scripts there is a script that download the source code (from svn) and creates the c:\myDirectory\Project1 directory.
I have another ant scripts ( c:\myDirectory\Scripts**compile-source.xml ) that compiles the Project1
from an ant script build.xml that is downloaded to c:\myDirectory\Project1
Snippet for c:\myDirectory\Scripts\compile-source.xml
<project name="compile" default="buildAll" basedir=".">
<property file=".\build.properties">
</property>
.......
<import file="${project.home.path}/${project.name}/build.xml"/>
<target name="buildAll">
<antcall target="jar-pack"/>
</target>
</project>
Snippet for c:\myDirectory\Project1\build.xml.
<project name="CommonFeatures" default="jar-pack" basedir=".">
<description>
A build file for the Common Features project
</description>
....
</project>
Note that the basedir for the project is set as "." for both the above ant scripts.
When I execute the script c:\myDirectory\Scripts\compile-source.xml from the c:\myDirectory\Scripts directory the target "jar-pack" present in the c:\myDirectory\Project1\build.xml gets executed.
However, the problem is that basedir attribude in build.xml ( basedir="." ) is the current working directory and in this case its c:\myDirectory\Scripts. Hence the script build.xml errors out since the basedir for build.xml is expected to be c:\myDirectory\Project1. The build.xml script would have worked, if basedir="." were set to "c:\myDirectory\Project1", but unfortunately build.xml file comes from the source code that is downloaded and I'm unable to edit.
So here's my question, Is it possible to do any of the following.
Override the value of the attribude basedir="." in build.xml when the is done in c:\myDirectory\Scripts\compile-source.xml ?
Is it possible to change the basedir in build.xml by any other mechanism so that the script c:\myDirectory\Project1\build.xml is executed under directory c:\myDirectory\Project1 ?
Any other way to resolve this issue?
Any help from Ant experts to overcome this issue is highly appreciated.
You can update basedir using subant task. Check this answer
Create the following build.xml file (assuming it is in Z:/any/folder):
<?xml version="1.0" encoding="UTF-8"?>
<project name="project">
<target name="mytarget">
<subant target="debug">
<property name="basedir" value="X:/any/dir/with/project"/>
<fileset dir="Y:/any/folder/with" includes="build.xml"/>
</subant>
</target>
</project>
The you can execute ant mytarget from Z:/any/folder
You can specifically reference the location of your build file, which is described in this stack overflow thread. This would allow you to get and use the directory your build file resides in as a reference point.
For your case the usage of the subant or ant tasks may be better suited, but nevertheless...
You can (but you should know/consider the side-effects!) extend ant with the common ant-contrib task definitions and use the var task which is able to override properties. Make sure to use the latest version (> 1.0b3).
<!-- adjust to your path and include it somewhere at the beginning of your project file -->
<taskdef resource="net/sf/antcontrib/antlib.xml" classpath="lib/ant-contrib-1.0b3.jar" />
<!-- works e.g. for basedir = /foo/bar to update it to /foo/bar/.. ~ /foo -->
<var name="basedir" value="${basedir}/.." />
update: but one has to be careful, because this does not change . (current working directory) (so <property name="x" location="tmp" /> would be relative to . and not to basedir anymore ; update: setting basedir outside of ant or via <project basedir= also sets . to basedir!). Here is some test target proving the effect on both:
<target name="tst.dummy.basedir-override">
<!-- example output:
tst.dummy.basedir-override:
[echo] basedir before: basedir=D:\tst, '.'=D:\tst\.
[echo] updating it via 'var' to '..'
[echo] basedir now: basedir=D:\tst/.., '.'=D:\tst\.
-->
<property name="cur" location="." /> <!-- makes the relative path absolute -->
<echo message="basedir before: basedir=${basedir}, '.'=${cur}" />
<echo message="updating it via 'var' to '..'" />
<var name="basedir" value="${basedir}/.." />
<property name="cur2" location="." /> <!-- makes the relative path absolute -->
<echo message="basedir now: basedir=${basedir}, '.'=${cur2}" />
</target>

Get immediate subdirectory of a root directory containing a subdirectory

I have a following directory structure
root_dir
fixed_dir
random_dir
subdir1
subdir2
subdir2.1
subdir3
subdir3.1
subdir3.2
In the ANT build file I know the root_dir, fixed_dir, and one directory that is either random_dir or a subdirectory below random_dir (subdirX). I need to determine the path of random_dir given some subdirX. Is it possible to find this directory in ANT and if so, how?
Here is a tested solution for finding the immediate subdirectory of a root directory that contains some subdirectory subdirX at any level of nesting given the file structure provided in the question.
<property name="root.dir" location="${basedir}/root_dir" />
<property name="subdirX" value="subdir2.1" />
<target name="find-immediate-subdir-of-root-containing-subdirX">
<dirset dir="${root.dir}" includes="**/${subdirX}" id="mydirset" />
<pathconvert property="random_dir" pathsep="${line.separator}" refid="mydirset">
<mapper type="regexp"
from="^(${root.dir}${file.separator}[^${file.separator}]+).*"
to="\1"/>
</pathconvert>
<echo message="${random_dir}" />
</target>
Output
find-immediate-subdir-of-root-containing-subdirX:
[echo] /ant/project/basedir/root_dir/random_dir
BUILD SUCCESSFUL
Total time: 1 second
With Ant addon Flaka you'll get the parent as property of a file object (see Flaka Manual, section 3.7.2, i.e.
<project xmlns:fl="antlib:it.haefelinger.flaka">
<!-- let standard ant tasks, i.e. echo
understand EL expresssions -->
<fl:install-property-handler />
<echo>#{file('${basedir}').parent}</echo>
<!-- or without fl:install-property-handler use fl:echo-->
<fl:echo>#{file('${basedir}').parent}</fl:echo>
</project>
so you would use :
#{file('${yoursubdir}').parent

Running PigUnit in a subdirectory with Ant

My problem is with running PigUnit via ant from a parent directory.
I am using the PigUnit example straight off of the PigUnit site.
The ant script I am using is here:
<junit printsummary="on" fork="true" haltonfailure="yes">
<jvmarg value="-Duser.dir=${basedir}"/>
<classpath refid="junit.class.path" />
<formatter type="xml" />
<batchtest todir="${test.report.dir}">
<fileset dir="${test.dir}">
<include name="**/*Test*.java" />
</fileset>
</batchtest>
</junit>
</target>
This script works perfectly fine if I run ant in the working directory of the project. However, when I remotely call the script with this line of code in an ant build script in the Pig project's parent directory
<ant dir="${pig.dir}" target="main" inheritall="false" antfile="build.xml"/>
I get a FileNotFoundException:
java.io.FileNotFoundException">java.io.FileNotFoundException: top_queries.pig (No such file or directory)
at java.io.FileInputStream.open(Native Method)
at java.io.FileInputStream.<init>(FileInputStream.java:138)
at org.apache.pig.pigunit.PigTest.readFile(PigTest.java:273)
at org.apache.pig.pigunit.PigTest.readFile(PigTest.java:269)
at org.apache.pig.pigunit.PigTest.<init>(PigTest.java:92)
at TopQueriesTest.testTop2Queries(Unknown Source)
This same FNF exception also happens if I run ant from the command line in the parent directory:
ant -f PigJavaTest/build.xml junit
My workaround to helping PigUnit find top_queries.pig file to specifiy the top_queries.pig file's location relative to the Pig project's parent directory, e.g.
PigTest test = new PigTest("PigTestJava/top_queries.pig", args);
but this is not optimal because it breaks when running ant from a directory different from the parent one.
Other JUnit tests will run normally from the parent directory, but PigUnit always throws the same FNF exception. I also tried doing a simple test with PigServer (loading/dumping a file) and the PigServer test behaved just like PigUnit had.
Why does this FileNotFoundException get thrown when calling ant from the parent directory, and how can I fix it?
You have a relative path to your pig file. So if you call the ant script from the working directory of the project it should work. When you call the ant script from the parent project, the relative path now is relative to the parent directory.
http://ant.apache.org/manual/Tasks/ant.html
when you call the ant task here, you are correctly setting the dir property, but that only changes the value of ${basedir} property for the follow in script, not the actual working directory when the junit task runs.
I suggest you use the dir attribute in your junit task to hard set the working directory (i guess that's what you're trying to do with the jvmarg option):
<junit printsummary="on" fork="true" haltonfailure="yes" dir="${basedir}">
<jvmarg value="-Duser.dir=${basedir}"/>
<classpath refid="junit.class.path" />
<formatter type="xml" />
<batchtest todir="${test.report.dir}">
<fileset dir="${test.dir}">
<include name="**/*Test*.java" />
</fileset>
</batchtest>
</junit>
See http://ant.apache.org/manual/Tasks/junit.html for more details

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>

Resources