Index

Table of contents

Apache Ant

Ant file locations

linux location for ant dependencies (all users)
/usr/share/ant/lib/
location for ant dependencies (current user)
[HOME]/.ant/lib/

Command line

invoke default target on build.xml
ant
verbose mode
ant -v
invoke specified target on build.xml
ant [target]
invoke a target on a sepecified build file
ant [target] -f [build_file]
set the [name] property to [value]
ant [target] -D[name]=[value]
supply an ant dependency (e.g. ant-junit.jar)
ant -lib [ant]

hello world

<project default="hello">
    <target name="hello">
        <echo>hello</echo>
    </target>
</project>
increase logging verbosity
<script language="javascript">
	var logger = project.getBuildListeners( ).firstElement( );
	logger.setMessageOutputLevel( 9 );
</script>

Paths

printing a path
<pathconvert  property="[property]" refid="[id]"/>
<echo>${[property]}</echo>
passing a path to another ant target (for example, to reuse the compile target)
<ant antfile="${[file]}" target="[target]">
	<property name="compile.path" value="${toString:test.compile.path}" />
</ant>

Properties

detect windows
<condition property="os.windows">
	<os family="windows" />
</condition>
configuring a target with all properties in a file
<ant antfile="${[file]}" target="[target]">
	<property file="${file}" />
</ant>
macro for regex replace in property
<macrodef name="regexreplace">
	<attribute name="property" />
	<attribute name="in" />
	<attribute name="replace" />
	<attribute name="with" />
	<sequential>
		<loadresource property="@{property}">
			<propertyresource name="@{in}" />
			<filterchain>
				<replaceregex pattern="@{replace}" replace="@{with}" flags="g" />
			</filterchain>
		</loadresource>
	</sequential>
</macrodef>

input output

downloading a file (wget)
<get src="${url}" dest="${destination}" />
downloading a file only if missing
<get src="${url}" dest="${destination}" skipexisting="true" />

javadoc

javadoc simple
<javadoc sourcepath="${src}" destdir="${api}" defaultexcludes="yes" version="true" use="true" />

Checks

checking that a directory exists
<available file="${dir}" type="dir" property="myproperty"/>
checking that a particular port is taken / available
<condition property="webserver.online">
	<socket server="localhost" port="${webserver.port}"/>
</condition>
<fail if="webserver.online" message="port ${webserver.port} already taken! Is the webserver already running?" />

packing

create zip file (overwrites any existing zip)
<zip destfile="file.zip" basedir="sources" />
create or update zip file
<zip destfile="file.zip" basedir="sources" update="true" />
merging zip files
<zip destfile="merged.zip">
    <zipgroupfileset dir="zips" includes="*.zip"/>
</zip>
merge libs into a jar we are creating
<jar destfile="${jar}">
	<fileset dir="${build.main.classes.dir}" />
	<zipgroupfileset dir="${project.lib.compile.dir}" includes="*.jar"/>
</jar>

SQL

running a select query on a database
<project default="mysql">
    <property name="db.jar" value="mysql-connector-java-8.0.22.jar" />
    <property name="db.driver" value="com.mysql.cj.jdbc.Driver" />
    <property name="db.host" value="localhost" />
    <property name="db.database" value="mysql" />
    <property name="db.user" value="root" />
    <property name="db.password" value="secret" />
    <property name="db.url" value="jdbc:mysql://${db.host}/${db.database}" />
    <target name="mysql">
        <sql driver="${db.driver}" url="${db.url}" userid="${db.user}" password="${db.password}" print="true">
                <classpath>
                        <pathelement location="${db.jar}"/>
                </classpath>
                show tables;
        </sql>
    </target>
</project>

ant macros

macro with attribute
<macrodef name="hello-world">
	<attribute name="message"/>
	<sequential>
		<echo message="@{message}" />
	</sequential>
</macrodef>
invoking the above macro
<hello-world message="Foo! Bar!" />
attribute with default
<macrodef name="hello-world">
	<attribute name="message" default="I have nothing to say"/>
	<sequential>
		<echo message="@{message}" />
	</sequential>
</macrodef>
invoking the above macro
<hello-world />
macro with element
<macrodef name="identity">
	<element name="body"/>
	<sequential>
		<body/>
	</sequential>
</macrodef>
invoking the above macro
<identity>
	<body>
		<echo>Foo! Bar!</echo>
	</body>
</identity>
macro for asserting file exists
<macrodef name="require">
	<attribute name="file"/>
	<attribute name="message" default="Error! file does not exist: @{file}"/>
	<sequential>
		<fail message="@{message}">
		    <condition>
			<not>
			    <available file="@{file}" />
			</not>
		    </condition>
		</fail>
	</sequential>
</macrodef>
use like this
<require file="${file}"/>
<require file="${file}" message="optional custom message"/>

Further reading

https://ant.apache.org/manual/Tasks/macrodef.html

ant scripting

hello world
<script language="javascript">
	java.lang.System.out.println("hello javascript!");
</script>
escape angular brackets
<script language="javascript">
	<![CDATA[
		java.lang.System.out.println("<hello>");
	]]>
</script>
invoke a task
<script language="javascript">
	var echo = project.createTask("echo");
	echo.setMessage("hello from echo task");
	echo.perform();
</script>
read a property
<property name="property.key" value="hello xml property"/>
<script language="javascript">
	java.lang.System.out.println(project.getProperty('property.key'));
</script>
set a property
<script language="javascript">
	project.setProperty('property.key', 'hello javascript property');
</script>
<echo>${property.key}</echo>
iterate the elements of a directory
<property name="property.containing.dir" value="/tmp"/>
<script language="javascript">
	<![CDATA[
		var path = project.getProperty('property.containing.dir');
		var dir = new java.io.File(path);
		var children = dir.listFiles();
		for(i=0; i<children.length; i++) {
			var child = children[i];
			if(child.isDirectory()) {
				java.lang.System.out.println(child);
			}
		}
	]]>
</script>

documentation

https://ant.apache.org/manual