Is it possible to execute an apply on a file set and have ant print the command it is executing?
For example:
<target name="test">
<apply executable="ls" failonerror="true" verbose="true" ignoremissing="false">
<fileset dir=".">
<include name="*.xml" />
</fileset>
<arg line="-la" />
</apply>
</target>
I would like the output to be something close to the following, with the key line being:
[apply] ls -la ./build.xml"
E.g.
Buildfile: /home/abarker/NetBeansProjects/TestProject/build.xml
test:
[apply] ls -la ./build.xml
[apply] -rw-r--r-- 1 abarker abarker 29231 Feb 13 11:29 /home/abarker/NetBeansProjects/TestProject/build.xml
[apply] Applied ls to 1 file and 0 directories.
There are several ideas I have:
You can use the outputproperty parameter. This will give you the output of the command in the <apply> task.
You can use fileset reference instead of an actual fileset.
Like this:
<property name="apply.files.prop" refid='apply.files'/>
<echo>The files you're operating on are "${apply.files.prop}"</echo>
<apply executable="ls" failonerror="true" verbose="true" ignoremissing="false">
<fileset refid="apply.files"/>
<arg line="-la" />
</apply>
You can then look at the fileset reference apply.files to see what files the <apply> task is operating on.
You can always add the -debug and -verbose flag when you run ant. This will print exactly what you want and then some -- then some a whole lot. I wish there was a way to turn verbose mode on and off on a particular task, but I don't know how to do that -- at least an easy way to do that.
For debug purposes - Just replace your own executable with echo. Here is an example of how I do it on Windows machines:
<target name="test">
<apply executable="cmd" failonerror="true" verbose="true" ignoremissing="false">
<fileset dir=".">
<include name="*.xml" />
</fileset>
<arg line="/c" />
<arg line="echo" />
<arg line="ls" />
<arg line="-la" />
</apply>
</target>
Normally when you run ant with -v/-verbose flag, it will print each execution of the command (this also includes exec and apply).
Related
So I have the below build file:
<target name="test">
<echo message="test"></echo>
<exec executable="C:\Users\Abc\Desktop\cmd.bat" >
<arg value="exit"/>
<arg value="mkdir C:\Users\Abc\Desktop\ant\test"/>
</exec>
</target>
I thought it would create a test folder there but its not. It pops out another command prompt window, I thought the exit would close that but it doesn't. I'm not sure what I am doing wrong.
The content of bath script test1.bat:
#echo off
echo %1
And ant's build.xml:
<target name="test">
<echo message="test"></echo>
<exec executable="C:\Users\AAA\Desktop\ant\test1.cmd">
<arg value="hello"/>
</exec>
</target>
As per the official documentation:
Note that .bat files cannot in general by executed directly. One
normally needs to execute the command shell executable cmd using the
/c switch
Follow this format instead:
<target name="help">
<exec executable="cmd">
<arg value="/c"/>
<arg value="ant.bat"/>
<arg value="-p"/>
</exec>
</target>
Source: https://ant.apache.org/manual/Tasks/exec.html
I'm trying to figure out a way to have Ant run a .jar executable that accepts a file and spits out several generated files from the single input file. Specifically, I'm trying to generate compiled .js files and at the same time generate .map files.
Normally, the command would look something like this:
java -jar compiler-latest --js a.js --js_output_file a.min.js --create_source_map a.js.map
Where:
compiler-latest is the closure-compiler jar
a.js is the JavaScript file to compile
a.min.js is the compiled JavaScript
a.js.map is the source map
My Ant script looks like this:
<project name="BuildTest" default="Build" basedir=".">
<description>
HTML Build Test with Ant
</description>
<property name="src" location="../js"/>
<property name="dst" location="../build"/>
<property name="compiler" location="../compiler.jar"/>
<!--Make Dest Directory-->
<target name="-destination">
<mkdir dir="${dst}"/>
</target>
<!--Compile JS-->
<target name="Build" depends="-destination">
<!--Filesets and Mappers-->
<fileset id="sourceFiles" dir="${src}" includes="*.js"/>
<mapper id="compiledJs" type="glob" from="*.js" to="*.compiled.js"/>
<mapper id="mapJs" type="glob" from="*.js" to="*.js.map"/>
<!--Apply Everything-->
<apply executable="java" parallel="false" dest="${dst}">
<!--Closure Compiler-->
<arg value="-jar"/>
<arg path="${compiler}"/>
<arg value="--compilation_level=SIMPLE_OPTIMIZATIONS"/>
<!--Source Files-->
<arg value="--js"/>
<srcfile/>
<fileset refid="sourceFiles"/>
<!--Output Files-->
<arg value="--js_output_file"/>
<targetfile/>
<mapper refid="compiledJs"/>
<!--Source Maps-->
<arg value="--source_map_format=V3"/>
<arg value="--create_source_map"/>
<arg value="--js_output_file"/>
<targetfile/>
<mapper refid="mapJs"/>
</apply>
</target>
<!--Clean Project-->
<target name="Clean" description="Cleans the project">
<delete dir="${dst}"/>
</target>
</project>
However, I get an error saying I can't have multiple <targetfile/> elements
apply doesn't support multiple targetfile elements.
This is a workaround, not nice, but effective.
You can use an Ant <compositemapper> to construct the command line for your application.
Below is an illustration. You need to set relative="yes" on the task in order that filenames relative to the build directory are used in preference to absolute filenames, otherwise mapping is harder. To build the command line provide a list of mappers inside the <compositemapper>. Use a <mergemapper> for fixed parts (args like --output_file), and use a suitable other mapper, maybe a glob, when you need to generate filenames.
A series of mappers is needed to separate the arguments passed to the java by <apply>, otherwise they will be passed as one long arg with embedded spaces.
<apply executable="java" parallel="false" relative="yes">
<arg line="-jar compiler-latest --js"/>
<srcfile />
<targetfile />
<compositemapper>
<mergemapper to="--js_output_file" />
<globmapper from="*.js" to="*.compiled.js" />
<mergemapper to="--source_map_format=V3" />
<mergemapper to="--create_source_map" />
<globmapper from="*" to="*.map" />
</compositemapper>
<fileset dir="." includes="*.js" />
</apply>
For a simple test that leads to a command line like:
java -jar compiler-latest --js 1.js --js_output_file 1.compiled.js --source_map_format=V3 --create_source_map 1.js.map
Here is my ant apply task:
<apply executable="${7z.exec}" failonerror="true">
<arg value="x"/>
<fileset dir="${distdir}">
<include name="**/*.zip"/>
</fileset>
</apply>
7z.exec is an absolute path to the 7z.exe executable. How can I tell 7zip to deposit the unzipped files into the same folder as the .zip?
You need to use the 7z -o switch for the eXtract command and an Ant mapper to get just the path to the zip. The Ant apply task has a targetfile element that allows you extra flexibility in composing the command line for the task. Leads to something like:
<apply executable="${7z.exec}" failonerror="true">
<arg value="x"/>
<srcfile />
<targetfile prefix="-o" />
<mapper type="regexp" from="^(.*)/(.*\.zip)" to="\1" />
<fileset dir="${distdir}">
<include name="**/*.zip"/>
</fileset>
</apply>
I'm trying to provide all *.cpp files in a folder to the c++ compiler through ant. But I get no further than ant giving gpp a giant string containing all the files. I tried to prove it by using a small test application:
int main( int argc, char**args ){
for( --argc; argc != 0; --argc ) printf("arg[%d]: %s\n",argc,args[argc]);
}
With the ant script like this:
<target name="cmdline">
<fileset id="fileset" dir=".">
<include name="*"/>
</fileset>
<pathconvert refid="fileset" property="converted"/>
<exec executable="a.exe">
<arg value="${converted}"/>
</exec>
</target>
My a.exe's output is this:
[exec] arg[1]: .a.cpp.swp .build.xml.swp a.cpp a.exe build.xml
Now here's the question: how do I provide all files in the fileset individually as an argument to the executable?
This is what the apply task in ANT was designed to support.
For example:
<target name="cmdline">
<apply executable="a.exe" parallel="true">
<srcfile/>
<fileset dir="." includes="*.cpp"/>
</apply>
</target>
The parallel argument runs the program once using all the files as arguments.
Found it: the difference seems to lie in arg value vs. arg line.
<arg line="${converted}"/>
resulted in the expected output:
[exec] arg[5]: C:\cygwin\home\xtofl_2\antes\build.xml
[exec] arg[4]: C:\cygwin\home\xtofl_2\antes\a.exe
[exec] arg[3]: C:\cygwin\home\xtofl_2\antes\a.cpp
[exec] arg[2]: C:\cygwin\home\xtofl_2\antes\.build.xml.swp
[exec] arg[1]: C:\cygwin\home\xtofl_2\antes\.a.cpp.swp
Based on this article, here is the complete code illustrating the use of the pathconvert task:
<target name="atask">
<fileset dir="dir" id="myTxts">
<include name="*.txt" />
</fileset>
<pathconvert property="cmdTxts" refid="myTxts" pathsep=" " />
<apply executable="${cmd}" parallel="false" verbose="true">
<arg value="-in" />
<srcfile />
<arg line="${cmdTxts}" />
<fileset dir="${list.dir}" includes="*.list" />
</apply>
</target>
Above code assumes there are no spaces in the paths.
To support spaces in paths, change above pathconvert line to:
<pathconvert property="cmdTxts" refid="myTxts" pathsep="' '" />
and arg line to:
<arg line="'${cmdTxts}'"/>
Source: Converting an Ant fileset to multiple apply args.
Have you looked at the ant cpptasks? This would allow you to integrate C++ compilation into your Ant build in a more Ant-centric fashion. For example, specifying files to be compiled using a fileset.
Here is the example (compatible with Ant 1.6 or later)::
<project name="hello" default="compile" xmlns:cpptasks="antlib:net.sf.antcontrib.cpptasks">
<target name="compile">
<mkdir dir="target/main/obj"/>
<cpptasks:cc outtype="executable" subsystem="console" outfile="target/hello" objdir="target/main/obj">
<fileset dir="src/main/c" includes="*.c"/>
</cpptasks:cc>
</target>
</project>
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>