Passing a variable into ant - ant

If I pass a variable to ant by doing
ant -Dsomething=blah
How can I refer to it in my build.xml? I tried #something# and ${something} but neither seem to work.
Ultimately what I am trying to do is set some properties (versions) at compile time.
update: the problem of course turned out to be somewhere else - accepting the most complete looking answer with examples

Don't you hate it when you over think these things:
<project name="test">
<echo message="The value of foo is ${foo}"/>
</project>
Now, I'll run my program. Notice that I never defined a value for property foo in my build.xml. Instead, I'll get it from the command line:
$ ant -Dfoo=BAR_BAR_FOO
test:
[echo] The value of foo is BAR_BAR_FOO
BUILD SUCCESSFUL
time: 0 seconds
See. Nothing special at all. You treat properties set on the command line just like normal properties.
Here's where the fun comes in. Notice that I've defined the property foo in my build.xml this time around:
<project name="test">
<property name="foo" value="barfu"/>
<echo message="The value of foo is ${foo}"/>
</project>
Now watch the fun:
$ ant
test:
[echo] The value of foo is barfu
BUILD SUCCESSFUL
time: 0 seconds
Now, we'll set the property foo on the command line:
$ ant -Dfoo=BAR_BAR_FOO
test:
[echo] The value of foo is BAR_BAR_FOO
BUILD SUCCESSFUL
time: 0 seconds
See the command line overrides the value I set in the build.xml file itself. This way, you can have defaults that can be overwritten by the command line parameters.

It sounds like you want to do something like the following:
<mkdir dir="build/src"/>
<copy todir="build/src" overwrite="true">
<fileset dir="src" includes="**/*.java"/>
<filterset>
<filter token="VERSION" value="${version}"/>
</filterset>
</copy>
...which will cause your source to get copied, replacing #VERSION#:
public class a { public static final String VERSION = "#VERSION#"; }
...and then include build/src in your javac src.
That said, I don't recommend this approach since the source copy step is expensive, and it will undoubtedly cause confusion. In the past, I've stored a version.properties file in my package with version=x.y. In my Java code, I used Class.getResourceAsStream("version.properties") and java.util.Properties. In my build.xml, I used <property file="my/pkg/version.properties"/> so that I could create an output-${version}.jar.

${argsOne} works for me and is easily referenced if the invoking command is
ant -DargsOne=cmd_line_argument
Ant documentation also says so. This should work, try running with ant -debug and paste the output.

Related

Ant inline exec arguments

I have tasks running in Ant, which I'm quite new to, as part of a CI chain of build events. I used a tutorial to create the file for testing/linting/etc a PHP application.
The first important directives in the build.xml are:
<property name="phpmd" value="phpmd"/>
<property name="phpunit" value="phpunit"/>
This works fine as is, assuming that phpmd/phpunit are on the path, and using phpunit as a further example, is run under the following target:
<target name="phpunit" unless="phpunit.done" depends="prepare" description="Run unit tests with PHPUnit">
<exec executable="${phpunit}" resultproperty="result.phpunit" taskname="phpunit">
<arg value="--configuration"/>
<arg path="${basedir}/phpunit.xml"/>
</exec>
<property name="phpunit.done" value="true"/>
</target>
All this works well as is- but I want to use docker from now on, which I had hoped would simply mean changing <property name="phpunit" value="phpunit"/> to <property name="phpunit" value="docker-compose run php phpunit"/>, but this instead gives me the following error:
Execute failed: java.io.IOException: Cannot run program "docker-compose run -w /var/www/src php phpunit" (in directory "/var/lib/jenkins/jobs/Blah blah blah/workspace/src"): error=2, No such file or directory
I know that you would usually add additional <arg/> nodes to targets- but is it not possible at all to provide the full command with inline arguments on the initial <property>?
Ant is obviously complaining because, along with those inline arguments, that executable doesn't exist. Will I have to use arg nodes and update every single target?
Using docker-compose alone works fine, but I need the args for the correct container and working directory to be used- preferably inline, otherwise I have to insert many arg nodes.
In the end I just created a property for phpunit arguments and then added it by using the <args line="${phpunitArgs}">.
Definitely not ideal, but at least it does what it is supposed to. I certainly prefer using Gulp! XML feels like a bad choice for a build system.

Ant conditional target not running

I have the following ant file:
<project name="admin" default="dirCheck" basedir=".">
<property name="directory" location="node_modules" />
<target name="run.npm.install" depends="dirCheck" unless="${dirExists}">
<echo>${directory} does not exist. Running 'npm install'</echo>
<exec executable="npm">
<arg value="install" />
</exec>
</target>
<target name="run.npm.update" depends="dirCheck" if="${dirExists}">
<echo>${directory} exists. Running 'npm update'</echo>
<exec executable="npm">
<arg value="update" />
</exec>
</target>
<target name="node_modules.check">
<condition property="dirExists">
<available file="${directory}" type="dir"/>
</condition>
</target>
<target name="dirCheck" depends="node_modules.check">
<echo>Checking for ${directory}. Exists? ${dirExists}</echo>
</target>
</project>
For some reason, neither runNPMInstall nor runNPMUpdate are ever run, regardless of whether the node_modules directory exists or not. Anyone have any idea what might be causing this? From all examples online at least one of the dependent tasks should be run.
EDIT: Changed:
<condition property="dirExists" value="true" else="false">
To:
<condition property="dirExists">
With the same result. Additional information is that I am using Ant 1.8.2. Thanks for anyone's help!
EDIT 2: Updated code to reflect my latest tests. Output from the build for new code above is:
Buildfile: /ws_html/app/client/build.xml
node_modules.check:
dirCheck:
[echo] Checking for /ws_html/app/client/node_modules. Exists? true
BUILD SUCCESSFUL
Total time: 0 seconds
Edit 3: Output when running ant -debug -f build.xml:
jjung-m2:client-dir jjung$ ant -debug -f build.xml
Apache Ant(TM) version 1.8.2 compiled on June 16 2012
Buildfile: /ws_html/client-dir/app/client-dir/build.xml
Adding reference: ant.PropertyHelper
Detected Java version: 1.7 in: /Library/Java/JavaVirtualMachines/jdk1.7.0_17.jdk/Contents/Home/jre
Detected OS: Mac OS X
Adding reference: ant.ComponentHelper
Setting ro project property: ant.file -> /ws_html/client-dir/app/client-dir/build.xml
Setting ro project property: ant.file.type -> file
Adding reference: ant.projectHelper
Adding reference: ant.parsing.context
Adding reference: ant.targets
parsing buildfile /ws_html/client-dir/app/client-dir/build.xml with URI = file:/ws_html/client-dir/app/client-dir/build.xml
Setting ro project property: ant.project.name -> ClientApp
Adding reference: ClientApp
Setting ro project property: ant.project.default-target -> dirCheck
Setting ro project property: ant.file.ClientApp -> /ws_html/client-dir/app/client-dir/build.xml
Setting ro project property: ant.file.type.ClientApp -> file
Project base dir set to: /ws_html/client-dir/app/client-dir
+Target:
+Target: run.npm.install
+Target: run.npm.update
+Target: node_modules.check
+Target: dirCheck
Adding reference: ant.LocalProperties
parsing buildfile jar:file:/usr/share/ant/lib/ant.jar!/org/apache/tools/ant/antlib.xml with URI = jar:file:/usr/share/ant/lib/ant.jar!/org/apache/tools/ant/antlib.xml from a zip file
Setting project property: directory -> /ws_html/client-dir/app/client-dir/node_modules
Setting ro project property: ant.project.invoked-targets -> dirCheck
Attempting to create object of type org.apache.tools.ant.helper.DefaultExecutor
Adding reference: ant.executor
Build sequence for target(s) `dirCheck' is [node_modules.check, dirCheck]
Complete build sequence is [node_modules.check, dirCheck, run.npm.update, run.npm.install, ]
node_modules.check:
[available] Found directory: node_modules
Condition true; setting dirExists to true
Setting project property: dirExists -> true
dirCheck:
[echo] Checking for /ws_html/client-dir/app/client-dir/node_modules. Exists? true
BUILD SUCCESSFUL
Total time: 0 seconds
Your runNPMInstall target will never run, because the dirExists property will always be set either true or false, because you used condition task with attribute else="false".
When using the old syntax (Ant Version < 1.8.0) , means just the plain propertyname if="propertyname" the target is only activated if the property is defined - independent of its actual value. On the contrary unless="propertyname" means the target is only activated if the property is not defined, but your property will always be set from condition task => true or false.
Since ant 1.8.0 you may use the new syntax if="${propertyname} means the target is only activated if the property holds true | yes | on, respectively unless="${propertyname}" means the target will only be activated if the property hold false | no | off, see ant manual if / unless
When using if / unless with ${propertyname} it should work as expected with Ant >= 1.8.0Alternatively use the condition task without the else attribute to make it work with the old syntax :
The value to set the property to if the condition evaluates to false. By default the property will remain unset.
Also value="true" is not needed, as :
The value to set the property to. Defaults to "true".
So that should be sufficient to make it work 'old style' :
<condition property="dirExists">
<available file="${directory}" type="dir"/>
</condition>
-- EDIT after comment --
When starting your ant file it will run the default target dir.check and nothing else happens. Use :<project name="admin" default="main" basedir=".">
and create a new target :<target name="main" depends="dir.check,runNPMInstall,runNPMUpdate"/>

How to create temporary directory in ant?

I'd like to create a temporary directory in ant (version 1.6.5) and assign it to a property.
The command "mktemp -d" would be ideal for this, but I cannot find similar functionality from inside ant
I can't find any official function in the docs apart from the tempfile task which apparently only creates files, not directories.
I'm considering using exec to call tempfile and get the result, however this will make my build.xml dependent on UNIX/linux, which I'd like to avoid.
Background: I'm trying to speed up an existing build process which builds inside networked filesystem. The build already copies all the source to a temporary directory, however this is on the same filesystem. I've tested changing this to /tmp/foo and it gives a worthwhile speed increase: 3mins vs 4mins.
You could combine the tempfile task with the java.io.tmpdir system property to get a file path to use to create a temporary dir:
<project default="test">
<target name="test">
<echo>${java.io.tmpdir}</echo>
<tempfile property="temp.file" destDir="${java.io.tmpdir}" prefix="build"/>
<echo>${temp.file}</echo>
</target>
</project>
Note that the tempfile task does not create the file (unless you ask it to). It just sets a property which you can use to create a file or dir.
This task sets a property to the name of a temporary file. Unlike
java.io.File.createTempFile, this task does not actually create the
temporary file, but it does guarantee that the file did not exist when
the task was executed.
Output in my environment:
test:
[echo] C:\Users\sudocode\AppData\Local\Temp\
[echo] C:\Users\sudocode\AppData\Local\Temp\build1749402932
The answer above only hints at how to create a temporary directory. The point is that merely returns a string. A more complete answer is
<target name="temptest" description="test making tempdir">
<tempfile property="mytempdir" destdir="${java.io.tmpdir}"/>
<tempfile property="mytempfile" destdir="${mytempdir}"/>
<tstamp>
<format property="now" pattern="MMMM dd yyyy"/>
</tstamp>
<copy tofile="${mytempfile}">
<string value="today=${now}"/>
</copy>
<property file="${mytempfile}"/>
<echo message="It it now ${today}"/>
</target>

checking latest version in version control

i am currently writing an ANT script which will include some intelligence to check for things. I am using SnapshotCM from True Blue Software as my version control and using CruiseControl as a framework for my nightly build.
Basically, I will need to always check for the latest version found in my version control and execute commands. In this case here is an example:
<project name="nightly_build" default="main" basedir="checkout">
<target name="init">
<property file="initial.properties"/>
</target>
<target name="main" depends="init">
<!-- need some code to set variable -->
<!-- need some code to increment variable -->
<!-- need some code here to check for the latest version -->
<exec executable="C:/Program Files/True Blue Software/SnapshotCM/wco.exe">
<arg line='-f -R "C:/Work/7.10.000_Tip/7.10.000_Tip_GUI_TEST/"'/>
</exec>
</target>
</project>
In the code above, I will load the "initial.properties" file.
The algorithm should be as follow:
load the initial properties file
get the build_number
increment build_number by 1 (let this new variable be X)
if X is found, increament X by 1 (if not found jump to 6.)
if X is found, repeat 4 (until X cannot be found)
else use the build number inside the <arg line ='-f -R "C:/..../7.10.100.X..../"'/>
The initial.properties file is as follow:
Major_Version=7
Minor_Version=10
Project_Number=100
Build_Number=036
Product_Version=${Major_Version}.${Minor_Version}.${Project_Number}.${Build_Number}
can anyone guide me on that?
Ant is not a programming language. It's a dependency matrix language.
That means you don't specify execution order in Ant. Ant will calculate the order it needs to run the targets. It also means Ant doesn't have the ability to do loops, or even change the value of a property once it is set.
There are a few packages that build upon Ant. The old standby is the Antcontrib. Antcontrib has the concept of variables which are like mutable properties. It also has various looping structures. However, I'm not sure if the <foreach> or <for> tasks will do what you want...
Searching sequentially for the next build number is something you can do in a shell script. In fact, I highly recommend this.
I use Ant for builds only and keep my CM functions outside of my build.xml file. Instead, I rely on my build system to do everything that's not related to the build itself. This includes checking out the code, saving the artifacts, and compiling unit tests. This way, if I change the way I use my continuous build system or my version control system, I don't have to modify my build.xml files.

Which Ant property contains the CWD when the ant script is run?

I don't want to get the basedir -- that appears to contain the build.xml script -- I want the CWD of the call to ant itself.
Basically, I want to do this:
$ cd /home/chrisr/projects/some_project
$ ant -f ../../tools/ant-build-rules/library.xml build-library
At this point, I need two things:
The path to ant-build-rules in absolute form; this is currently found in the basedir property, so I'm set there.
The path of some_project, in absolute form. This is what I don't know how to get.
Which property contains this information?
The java property user.dir contains the current directory
<project name="demo" default="printCWD">
<target name="printCWD">
<echo message="${user.dir}"/>
</target>
</project>
There is no such property, but you can run a script to get it.
${bsh:WorkDirPath.getPath()}
See urbancode.com.

Resources