Ant exec refactoring - ant

I've this code in my build.xml:
<exec executable="cmd" osfamily="winnt">
<arg value="/c"/>
<arg value="xsltproc\bin\xsltproc.exe"/>
<arg value="--xinclude"/>
<arg value="-o"/>
<arg value="dist/html/main.html"/>
<arg value="xsl/html/docbook.xsl"/>
<arg value="xml/main.xml"/>
</exec>
<exec executable="xsltproc" osfamily="unix">
<arg value="--xinclude"/>
<arg value="-o"/>
<arg value="dist/html/main.html"/>
<arg value="xsl/html/docbook.xsl"/>
<arg value="xml/main.xml"/>
</exec>
the sequence is the same... I'm wondering about how refactoring this small fragment in order to keep it DRY.

maybe try using a property for the common bits with arg-line? something like this:
<property name="xslt.common" value="--xinclude -o dist/html/main.html xsl/html/docbook.xsl xml/main.xml"/>
<exec executable="cmd" osfamily="winnt">
<arg value="/c"/>
<arg value="xsltproc\bin\xsltproc.exe"/>
<arg line="${xslt.common}"/>
</exec>
<exec executable="xsltproc" osfamily="unix">
<arg line="${xslt.common}"/>
</exec>

Define a macro.
You can glob the shared portions in an element, and conditionally execute the specific parts.

I think the Unix version will work under NT if you have the xsltproc.exe available in via the PATH environment variable. You could try removing the osfamily and see.

Related

Open a new window with <exec> in Apache Ant

I have a build.xml for my ant in which I use
<exec executable="cmd">
<arg line = "start"/>
<arg value ="/c test3.bat"/>
</exec>
to start the given bat-file.
This works fine, but what I really want is that it opens the test3.bat in a new cmd-window. Is it possible to achieve this?
Works like that =
<exec executable="cmd">
<arg value="/c"/>
<arg value = "start"/>
<arg value ="test3.bat"/>
</exec>
In case oft doubt, use multiple <arg value=.../> for the parameters instead of <arg line=.../>,
works better.

No output running yui-compressor from Ant

I'm going to minify my js files by yuicomressor via ant, I wrote this:
<property name="concat-js-file-name" value="main.concat.js"/>
<property name="concat-js-file-path" value="${temp-folder}/js/${concat-js-file-name}"/>
<property name="yui-jar-path" value="lib/yuicompressor-2.4.7.jar"/>
<target name="minification" depends="concatation">
<echo>---Minification is started</echo>
<java jar="${yui-jar-path}" fork="true">
<arg value="${concat-js-file-path}"/>
<arg value="-o minified.js"/>
</java>
<echo>---Minification is finished successfully...</echo>
</target>
The problem is the output file is not generated!
Any idea?
You should set <java ... failonerror="true"/> and increase the noiselevel to see what's going on, means start your ant build with ant -f yourbuild.xml -debug
Actually, after some tries I found a solution:
I used <arg line="-o outputfile inputfile"/> instead, and it worked.
I suggest using <arg value="..."> instead of <arg line="...">. <arg value="..."> ensures that each command line argument has quotes around it, if necessary.
In the case of yui-compressor, the "-o" and "<file>" arguments should each go in their own <arg value="..."> elements:
<java jar="${yui-jar-path}" fork="true">
<arg value="-o"/>
<arg value="minified.js"/>
<arg value="${concat-js-file-path}"/>
</java>

build.xml ignoring <echo> tags and if options

I have a sencha Ext.js project and I am trying to get user input and take action based on that user input in my build.xml file.
Here's my build.xml:
<?xml version="1.0" encoding="utf-8"?>
<project xmlns:if="ant:if" xmlns:unless="ant:unless" name="PSOGN" default=".help">
<import file="${basedir}/.sencha/app/build-impl.xml"/>
<target name="-after-build">
<echo>57 ...</echo>
<property name="realperl" value="/usr/bin/perl"/>
<echo>59 ...</echo>
<exec executable="/bin/hostname" outputproperty="myhost">
<arg value="-s"/>
</exec>
<echo>64 ...</echo>
<exec executable="${realperl}" outputproperty="env">
<arg value="../bin/getCf.pl"/>
<arg value="--config"/>
<arg value="../etc/config/currentCf"/>
<arg value="ENV"/>
</exec>
<echo>70 ...</echo>
<input message="Install ${env} version on ${myhost}?" addproperty="install" validargs="y,n" />
<echo>72 ...</echo>
<condition property="doinstall">
<equals arg1="${install}" arg2="y" />
</condition>
<echo>Hello ...</echo>
<exec executable="${realperl}" outputproperty="htdocspath">
<arg value="../bin/getCf.pl"/>
<arg value="--config"/>
<arg value="../etc/config/currentCf"/>
<arg value="HTDOCSPATH"/>
</exec>
<echo>do install is ${doinstall}</echo>
<echo if:true="${doinstall}">Please wait. Executing rsync to ${htdocspath}. Output logged to /tmp/rsync.log.</echo>
<echo if:false="${doinstall}">Skipping rsync to ${htdocspath}.</echo>
<exec executable="/usr/local/bin/rsync" if:true="${doinstall}">
<arg value="--exclude='*.log'" />
<arg value="--chmod=ugo=rwX" />
<arg value="-rltDq" />
<arg value="../info"/>
<arg value="../sbin"/>
<arg value="../bin"/>
<arg value="../cec"/>
<arg value="../cec.list.html"/>
<arg value="../cgi"/>
<arg value="../common"/>
<arg value="../dblib"/>
<arg value="../etc"/>
<arg value="../ext-2.3.0"/>
<arg value="../framework"/>
<arg value="../help"/>
<arg value="../icon-loading-animated.gif"/>
<arg value="../images"/>
<arg value="../img"/>
<arg value="../include"/>
<arg value="../index.shtml"/>
<arg value="../kicker"/>
<arg value="../lib"/>
<arg value="../msgs"/>
<arg value="../src"/>
<arg value="../thingold"/>
<arg value="../thing"/>
<arg value="${htdocspath}"/>
<redirector output="/tmp/rsync.log" alwayslog="true"/>
</exec>
</target>
</project>
When I run sencha app build which invokes ant I only get this output from by build.xml:
Install Dev version on tools-dev1? (y, n)
There is no output from my <echo... tags and if I answer 'n' I can that the rsync command executes. What am I doing wrong here?
I simplified your build.xml
<project xmlns:if="ant:if" xmlns:unless="ant:unless" name="PSOGN" >
<input message="Install ?" addproperty="install" validargs="y,n" />
<condition property="doinstall">
<equals arg1="${install}" arg2="y" />
</condition>
<echo>do install is ${doinstall}</echo>
<echo if:true="${doinstall}">Please wait. Executing rsync</echo>
<echo unless:true="${doinstall}">Skipping rsync </echo>
<exec executable="echo" if:true="${doinstall}">
<arg value="ECHO IS EXECUTED" />
<redirector output="./rsync.log" alwayslog="true"/>
</exec>
</project>
and I replaced if:false with unless:true
<echo unless:true="${doinstall}">Skipping rsync </echo>
Everything works fine:
oleg#oleg-ThinkPad-X201:~/temp/aa$ ant
Buildfile: /home/oleg/temp/aa/build.xml
[input] Install ? (y, n)
y
[echo] do install is true
[echo] Please wait. Executing rsync
[exec] ECHO IS EXECUTED
BUILD SUCCESSFUL
Total time: 2 seconds
oleg#oleg-ThinkPad-X201:~/temp/aa$ ant
Buildfile: /home/oleg/temp/aa/build.xml
[input] Install ? (y, n)
n
[echo] do install is ${doinstall}
[echo] Skipping rsync
BUILD SUCCESSFUL
Total time: 2 seconds

Variable number of parameters using <macrodef> and exec

I am using exec to invoke a command line program multiple times from an ant build.xml. This command line program takes variable number of arguments for different cases.
At the moment I am calling this external program multiple time using exec and code looks cluttered. For example:
<exec dir="./deploy_abc/bin" executable="python" failonerror="true" >
<arg line="tests.py"/>
<arg line="-h aaa"/>
<arg line="-u bbb"/>
<arg line="-p ccc"/>
</exec>
<exec dir="./deploy_abc/bin" executable="python" failonerror="true" >
<arg line="tests.py"/>
<arg line="-h ddd"/>
<arg line="-u eee"/>
<arg line="-p fff"/>
<arg value="this is second test"/>
</exec>
<exec dir="./deploy_abc/bin" executable="python" failonerror="true" >
<arg line="tests.py"/>
<arg line="-u bbb"/>
<arg line="-p ccc"/>
<arg value="this is another test"/>
</exec>
So I am planning to refactor this build.xml file using macrodef.
My question is how to pass variable number of parameters to macrodef. As it is shown above I need to pass different arguments to the exec-ed program based on the scenario.
You can use a macrodef element to support this:
This is used to specify nested elements of the new task. The contents
of the nested elements of the task instance are placed in the
templated task at the tag name.
For example, you might define your macro like this:
<macrodef name="call-exec">
<attribute name="dir"/>
<attribute name="executable"/>
<attribute name="failonerror"/>
<element name="arg-elements"/>
<sequential>
<exec dir="#{dir}" executable="#{executable}"
failonerror="#{failonerrer}" >
<arg-elements />
</exec>
</sequential>
</macrodef>
And call it like this:
<call-exec dir="./deploy_abc/bin" executable="python" failonerror="true" >
<arg-elements>
<arg line="tests.py"/>
<arg line="-u bbb"/>
<arg line="-p ccc"/>
<arg value="this is another test"/>
</arg-elements>
</call-exec>

How to pass a list of files to <exec>?

This is a part of my ant script:
<target>
<exec executable="find" outputproperty="found">
<arg value="src/main/java"/>
<arg line="-name '*.java'"/>
</exec>
<exec executable="xgettext">
<arg value="-k_"/>
<arg line="-o gettext.pot"/>
<arg line="${found}"/>
</exec>
</target>
Doesn't work because xgettext receives a quoted list of files and treats this list as a single file name. How to solve it?
You'd need to separate out each file to a separate arg for that to work.
You can supply a list-of-files file to process to 'xgettext' using the --files-from option.
How about something like this: write the 'find' output to a file, then reload into 'xgettext':
<target>
<exec executable="find" outputproperty="found">
<arg value="src/main/java"/>
<arg line="-name '*.java'"/>
</exec>
<echo file="xgettext.files" message="${found}" />
<exec executable="xgettext">
<arg value="-k_"/>
<arg value="-o" />
<arg value="gettext.pot"/>
<arg value="--files-from=xgettext.files"/>
</exec>
</target>
Alternatively, here's a variation that assumes you have the Bourne Shell sh - if you have something else you can probably adapt. This pipes the 'find' output directly to 'xgettext':
<exec executable="sh">
<arg value="-c"/>
<arg value="find src/main/java -name '*.java' | xgettext -k_ -o gettext.pot -f -"/>
</exec>

Resources