modify ant classpath on the fly - ant

I want to use resolvers (ssh) which are dependant on ant classpath.
Something like
<resolvers>
...
<ssh ...
...
</resolvers>
To use it I need jsch in ant classpath. Ant script should depends only on common lib (which also includes resolved jsch dependencies) - to use it on any client PC. Scenario is:
task to download lib.
Extract libs (jsch and etc.)
ivy:configure
But ivy:configure does not have any classpathref param, so it is unclear for me how to load jars I extracted.
Is it possible?
Or, probably, somehow run ant again internally with extended classpath?

Ok,
so my comment to question looked good for me but at the end it did not work.
The only way I found (working way I mean) is to to run ant script with
Download common-lib (with ) which includes all jar-libs required for optional ivy processing
Construct new classpath and run exec on same build file with required target:
<target name="call.task" if="wrapped.task.name">
<path id="ant.class.path">
<fileset dir="${tools.lib.dir}" >
<include name="*.jar" />
</fileset>
<pathelement location="${java.class.path}" />
</path>
<condition property="append.dest.dir" value="-Ddest.dir=${dest.dir}" else="">
<isset property="dest.dir"/>
</condition>
<exec executable="ant" failonerror="true">
<arg line="-f ivy-build.xml" />
<arg line='-lib "${toString:ant.class.path}"' />
<arg value="${wrapped.task.name}" />
<arg value="${append.dest.dir}" />
</exec>
</target>

Related

How to conditionally execute batch scripts for different platforms using Ant?

I am attempting to use an Ant build script to build a project that already has nmake (Visual Studio) build scripts. Rather than redo the entire build script, I would like to have Ant reuse the existing scripts.
So, I have something like this which works for Windows Mobile 6 ARMV4I builds:
<project ...>
<target name="-BUILD.XML-COMPILE" depends="-init, -pre-compile">
<exec executable="cmd">
<arg value="/c"/>
<arg line='"${g.path.project}\build-wm6-armv4i.bat"'/>
</exec>
<antcall target="-post-compile" inheritall="true" inheritrefs="true" />
</target>
</project>
But I would also like it to work for other platforms like Win32 x86 and Windows CE6 x86.
How can I have the Ant script discriminate which batch file it should execute to perform the build?
The <os> condition may be used to set properties based on the operating system and the hardware architecture. Targets may be conditionally executed using the if and unless attributes.
<?xml version="1.0" encoding="UTF-8"?>
<project name="build" basedir="." default="BUILD.XML-COMPILE">
<condition property="Win32-x86">
<and>
<os family="windows" />
<or>
<os arch="i386" />
<os arch="x86" />
</or>
</and>
</condition>
<condition property="Win-ARMv4">
<os family="windows" arch="armv4" />
</condition>
<target name="-BUILD.XML-COMPILE_Win-ARMv4" if="Win-ARMv4"
depends="-init, -pre-compile">
<exec executable="cmd">
<arg value="/c"/>
<arg line='"${g.path.project}\build-wm6-armv4i.bat"'/>
</exec>
<antcall target="-post-compile" inheritall="true" inheritrefs="true" />
</target>
<target name="-BUILD.XML-COMPILE_Win32-x86" if="Win32-x86"
depends="-init, -pre-compile">
<exec executable="cmd">
<arg value="/c"/>
<arg line='"${g.path.project}\build-win32-x86.bat"'/>
</exec>
<antcall target="-post-compile" inheritall="true" inheritrefs="true" />
</target>
<!-- Execute the correct target automatically based on current platform. -->
<target name="BUILD.XML-COMPILE"
depends="-BUILD.XML-COMPILE_Win-ARMv4,
-BUILD.XML-COMPILE_Win32-x86" />
</project>
The paths to the batch files are both single and double quoted so that file paths with spaces will not break the script. I have not tested this script on Windows Mobile 6 ARMV4I, so you will want to use the Ant target below to verify the name.
<target name="echo-os-name-arch-version">
<echo message="OS Name is: ${os.name}" />
<echo message="OS Architecture is: ${os.arch}" />
<echo message="OS Version is: ${os.version}" />
</target>
Related stack overflow questions:
how to detect the windows OS in ANT
Using ant to detect os and set property

Ant: Apply with fileset, but only exec once on one file?

I'm working on something similar to the question here: ANT script to compile all (css) LESS files in a dir and subdirs with RHINO
However, I'm having a hard time customizing this to one particular requirement:
If any .less files in dir.less change: Run LESS on just one file (as it imports the other less files, making a single, combined output).
This is the state of my current build.xml:
<target name="less" description="Compile LESS files">
<echo message="Checking for LESS file changes..."/>
<apply dir="${dir.less}" executable="${tool.less}" parallel="false" failonerror="true">
<fileset dir="${dir.less}" includes="*.less" />
<srcfile/>
<mapper type="glob" from="*.less" to="${dir.css}/*.css"/>
<targetfile/>
<arg value="-compress" />
</apply>
</target>
This currently builds all of the .LESS files and outputs them toe the appropriate location (Which is livable). If I replace the mapper glob with:
<mapper type="glob" from="MainFileThatImportsOthers.less" to="${dir.css}/MainFileThatImportsOthers.css"/>
The fileset directive is effectively reduced to that one file, and changing the other .LESS files in that directory don't cause output from the task.
Can someone point me in the right direction so I can avoid setting this up wrong and recusing through each .LESS file every time?
I worked out a solution that works correctly, I used an upToDate task to set a property to conditionally trigger Exec for the compiler:
<target name="scanLess" description="Scan for LESS file changes">
<echo message="Checking for LESS file changes..."/>
<uptodate property="tool.less.changed" targetfile="${dir.css}/MyFile.css" >
<srcfiles dir="${dir.less}" includes="*.less" />
</uptodate>
</target>
<target name="less" depends="scanLess" unless="tool.less.changed" description="Compile LESS files" >
<echo message="LESS files changed, running lessc" />
<exec executable="${tool.less}" failonerror="true">
<arg value="${dir.less}/MyFile.less" />
<arg value="${dir.css}/MyFile.css" />
<arg value="-compress" />
</exec>
</target>
Investigate how selectors work in ANT

Running a BAT file from ANT

I have gone through number of posts on the very forum but couldn't sort it out. I am trying to run a BAT file from ANT script. The folder hierarchy is like this
- Project
| - build.xml
| - build-C
| | - test.bat
The ANT file that i wrote so for is
<project name="MyProject" basedir=".">
<property name="buildC" value="${basedire}\build-C" />
<exec dir="${buildC}" executable="cmd" os="Windows XP">
<arg line="/c test.bat"/>
</exec>
</project>
The bat file content is
echo In Build-C Test.bat
It says that build failed .. :s i dun know what wrong am i doing ?
<property name="buildC" value="${basedire}\build-C" />
This should be ${basedir} I guess? Use
<echo>${buildC}</echo>
to make sure the dir is correct.
And shouldn't
<exec dir="${buildC}" executable="test.bat" os="Windows XP" />
do the job?
Hopefully this will help expand on the already given/accepted answers:
I suggest executing cmd with the batch script as a parameter:
<exec failonerror="true" executable="cmd" dir="${buildC}">
<arg line="/c "${buildC}/test.bat""/>
</exec>
Not sure if it is necessary to use the absolute path "${buildC}/test.bat" since dir is specified, but I put it just in case. It might be enough to use /c test.bat.
My project executes a batch script on Windows operating systems & a shell script on all others. Here is an example:
<target name="foo">
<!-- properties for Windows OSes -->
<condition property="script.exec" value="cmd">
<os family="windows"/>
</condition>
<condition property="script.param" value="/c "${basedir}/foo.bat"">
<os family="windows"/>
</condition>
<!-- properties for non-Windows OSes -->
<property name="script.exec" value="sh"/>
<property name="script.param" value=""${basedir}/foo.sh""/>
<echo message="Executing command: ${script.exec} ${script.param}"/>
<exec failonerror="true" executable="${script.exec}" dir="${basedir}">
<arg line="${script.param}"/>
</exec>
</target>

How to quickly deploy assets to Amazon S3 with an Ant target?

What is the quickest way to deploy content to a CDN with an Ant target? My Ant target is running on a continuous integration server (Hudson). My current solution uses curl and is a bit slow. Should I use wput or something else and how would I do that in ant?
<target name="Deploy">
<for param="file">
<path>
<fileset dir="${basedir}/output" includes="**/*"/>
</path>
<sequential>
<echo> Deploy #{file} </echo>
<exec executable="curl">
<arg value="-F name=value"/> <!-- params for secure access -->
<arg value= "-F file=#{file}"/>
<arg value="http://cdn.com/project"/>
</exec>
</sequential>
</for>
</target>
Several ideas have come up to speed up the transfer of content to the cdn
1) max out the pipe bandwidth by using the parallel ant task to simultaneously transfer several mutually exclusive filesets. For example, if there are three sub-folders in the output folder, each can be given to a different parallel task, and each would iterate through the files, calling curl on each file to transfer it to the cdn. http://ant.apache.org/manual/Tasks/parallel.html
2) write a custom ant task (bash script?) that would have local knowledge about the build so that any files that were changed by the last build get marked and only those files would be transfered. This would prevent sending a file that is already on the cdn.
3) read the remote directory from the cdn and use timestamps to determine which files to send. This may not be possible depending on the cdn and whether it allows such queries. I was hoping wput could do this but I don't see an option for that. http://wput.sourceforge.net/wput.1.html
RESOLVED
I found a blog titled "Deploying assets to Amazon S3 with Ant" which was extremely helpful. It uses a python script 's3cmd sync' which only transfers files that don’t exist at the destination.
I ended up with this ant target:
<target name="s3Upload">
<property name="http.expires" value="Fri, 31 Dec 2011 12:00:00 GMT" />
<exec executable="${PYTHON_DIR}\python.exe" failonerror="true">
<arg value="${PYTHON_DIR}\Scripts\s3cmd" />
<arg value="--guess-mime-type" />
<arg value="--add-header=Cache-Control:public, max-age=630657344" />
<arg value="--add-header=Expires:${http.expires}" />
<arg value="--encoding=UTF-8" />
<arg value="--skip-existing" />
<arg value="--recursive" />
<arg value="--exclude=*.log" />
<arg value="--acl-public" />
<arg value="sync" />
<arg value="${CDN_DIR}/" />
<arg value="s3://my-project-cdn/" />
</exec>
</target>

Inconsistent NoClassDefFoundError in subant java task

My ant build script starts with a java task that uses fork=true
<java fork="true"
classname="org.apache.tools.ant.launch.Launcher"
jvm="${java.home}/bin/java"
classpathref="class.path">
<arg value="-f" />
<arg value="${ant.file}" />
<arg value="generate" />
</java>
The <arg value="generate" /> points to another task in the same ant build file.
This task starts another target with a subant task that points to another file.
<subant verbose="true" target="replace">
<fileset dir="${basedir}" includes="refactor.xml" />
</subant>
This file refactor.xml starts a java task again with fork=true.
<java classpathref="class.path"
classname="namespace.Tool"
fork="true"/>
The strange behaviour is: everything works fine, except once in a while I get the NoClassDefFoundError error for the namespace.Tool java source file.
After e.g. closing, reopening the file the error may disappear, however there is no reproducible behaviour.
I tried avoiding the subant construction (used to unclutter) but this doesn't help.
Finally the class.path that is referenced is like this:
<path id="class.path">
<pathelement location="../common/bin" />
<pathelement location="./bin" />
<fileset dir="${build.dir}">
<include name="...jar" />
</fileset>
</path>
Any ideas?
Cause was <pathelement location="./bin" />.
This bin folder was recompiled by Eclipse as soon as in other steps in the sequence of Ant tasks e.g. a folder was deleted. The default setting in Eclipse is to recompile all code at such a moment.
As a result the Ant process may or may not find a specific class in this bin folder resulting in the inconsistent NoClassDefFoundError.

Resources