Compile files with certain pattern names in ANT - ant

I need to compile a set of files say they have a pattern "*_modules.F" (fortran files). Using ant, I have a PCC compiler set up on the machine to compile such files. How would I be able to do it via ant scripts, So far I have
<exec dir="ModuleDir" executable="PCC">
<arg line="1_module.F"/>
</exec>
The above would work for a single module, how can get it to work for all the module with the pattern "*_modules.F"? Any ideas?

This can be done using the apply ant task which takes a fileset as a parameter. Without the "parallel" attribute the executable would be invoked separately for each input file.
<apply executable="PCC" parallel="true">
<fileset dir="." includes="*_modules.F"/>
</apply>

Related

Ant failing with Content is not allowed in prolog

I am using subant and it is resulting into Content is not allowed in prolog problem.
<subant target="main" genericantfile="build.xml">
<fileset dir = "." />
</subant>
Error:
The following error occurred while executing this line:
pattern.py:1: Content is not allowed in prolog.
Please note I have different files in those folders for example, python files.
When I use explicit listing using the filelist, all works fine.
<subant target="main" genericantfile="build.xml">
<filelist dir="."
files = "A/build.xml,
B/build.xml"
/>
</subant>
With subant you either specify genericantfile along with a dirset (to run the same build file many times, each time with a different basedir) or you omit genericantfile but supply a fileset or other resource collection of build files to run. You are mixing the two styles, and it looks like when you provide a fileset ant is ignoring the genericantfile attribute and treating each element of that fileset as a build file, attempting to parse each of the files as XML, and failing for those that are not XML (i.e. the python files).
<subant target="main">
<fileset dir = "." includes="**/build.xml" />
</subant>
would include only the real build files in the fileset.

Using "antcall" in included ant files

I have a shared ant script b.ant which internally use antcall. It calculates a property that the client scripts use. I use include instead of import client scripts to avoid unintentional overwriting of targets, but this gives me a problem with the antcall.
When using include all targets in b are prefixes, and depends attributes in b are updated accordingly. This is however not true for antcall. Is there a there are way to handle this, i.e. make antcall always call the "local" ant target?
I can workaround this by using import, but then I'll get all the overwrite problems. It is not possible to use depends instead of antcall.
Example files
I have two files:
a.ant
<project>
<include file="b.ant" as="b" />
<target name="test-depends" depends="b.depend">
<echo>${calculated-property}</echo>
</target>
<target name="test-call" depends="b.call">
<echo>${calculated-property}</echo>
</target>
</project>
b.ant
<project>
<target name="depend" depends="some-target">
<property name="calculated-property" value="Hello World"/>
</target>
<target name="call">
<antcall target="some-target" inheritrefs="true"/>
<property name="calculated-property" value="Hello World"/>
</target>
<target name="some-target"/>
</project>
Example output
Calling test-depend works as expected but test-call fails with this output:
b.call:
BUILD FAILED
D:\ws\rambo2\ws-dobshl\ant-test\b.ant:6: The following error occurred while executing this line:
Target "some-target" does not exist in the project "null".
Total time: 258 milliseconds
Ant is a dependency matrix specification language. Usually a bunch of <antcall/>, <ant/>, <include/> and <import/> is a sign of a poorly written build script. It's a developer trying to force Ant to act like a programming language.
For developer, it makes sense to break up a program into smaller files. Even Python and Perl scripts can benefit from this. However, breaking up an Ant build script usually causes problems. We had a developer who went through every project and broke up all the build.xml files into six or seven separate build files in order to improve the process. It basically broke the whole Ant dependency mechanism. To fix it, he then tossed in a bunch of <ant/> calls and <include> tasks. In the end, it meant that each target was called between 12 to 20 times.
Not using <import/> and <antcall/> isn't a hard and fast rule. But, I've been using Ant for years and rarely ever used these mechanisms. When I do, it's usually for a shared build file that multiple projects will use (which sounds like what you have) but instead of defining targets in my shared build file, I define macros. This eliminates the target namespace issues that you are having, and the macros work better because they act more like Ant tasks. This is especially true with the introduction of <local/> in Ant 1.8.
See if you can restructure the shared build file into using <macrodef/> instead of targets. It will make it much easier to include your shared build file.
Give a name to the <project> in b.ant and then change the target of the <antcall>:
<project name="b"> <!-- Give the project a name -->
<target name="depend" depends="some-target">
<property name="calculated-property" value="In b.depend"/>
</target>
<target name="call">
<!-- Specify the name of the project containing the target -->
<antcall target="b.some-target" inheritrefs="true"/>
<property name="calculated-property" value="In b.call"/>
</target>
<target name="some-target"/>
</project>
The result of ant -f a.ant test-call:
b.call:
b.some-target:
test-call:
[echo] In b.call
BUILD SUCCESSFUL
With the changes to b.ant, the <include> in a.ant can be simplified by removing the as attribute:
<include file="b.ant" />

Using JDK 6 style classpath with javac ANT compile task

Does anybody have an example of using JDK 6 style - only defining the directory and not list of each and every jar in the directory - classpath with an ANT javac compile task?
We tried it like this
compile.classpath=c:....\WEB-INF\lib*;...websphere...\a.jar;...websphere...\b.jar; etc. and used this classpath in the javac task, but the libraries from WEB-INF\lib were not being recognised.
So, I am wondering if it is possible to use this type of construct with ANT. The ANT version is 1.8.4.
Typically we use path like structures .
<path id="project.classpath">
<fileset dir="${libdirectory}">
<include name="*.jar"/>
</fileset>
</path>
The the project.classpath is used in javac task. See more at ant examples
I do not yet know, why this works vs. why it doesn't work without these attributes, but I was able to get the wildcard part to work by using the fork="yes" and executable="path-to-my-executable" attributes in the javac task.

Is there a way to call the ant 'ant' target with '-lib' option

I'm developing an ant script which is calling another ant script using the <ant> task. This ant script is an installer a Java product and is to be used by our customers, who will have ant installed separately.
The script being called uses the antlr task <antlr:ant-antlr3>. To do this I must place the ant-antlr3.jar file in the ant lib directory, as well as adding antlr-3.2.jar to the classpath.
But I don't want to have this dependency of having ant-antl3.jar file in the client's own installed version of ant.
Is there a way of providing the equivalent to ant's command-line '-lib' option to specify other paths for jars to be added to antlib using the <ant> task itself?
I've taken a look at the online docs and there doesn't seem to be a way.
Thanks
I believe the accepted way to do this is to manually set up your classpath in the build file rather than implicitly including it via the global ant lib directory. i.e.
<path id="master-classpath">
<fileset dir="${lib}" />
<fileset file="${findbugs-base}/lib/annotations.jar" />
<pathelement location="${build-classes}" />
</path>
You can then use this path element in any task that can accept classpath args such as javac
<javac
destdir="${out}"
source="1.5"
target="1.5"
debug="true">
<src path="${src}" />
<classpath refid="master-classpath" />
</javac>
This way, the global ant set up isn't a dependency, and you can specify any files you might need for any build, as specifically as you need to (down to a given call or target).
Obviously, this is all to be carried out in the build file you're calling from the clients' build file. This way, when you call out to yours, the classpath will be set up exactly as you desire.
Another far less idiomatic possibility would be to literally shell out with the Exec Task and call ant that way. Obviously, with the provision of the Ant task, the developers of ant don't recommend you doing that. It is an option, nonetheless.
Tim's answer gives most of the story, but in order to run Ant and set JVM options, you'd need to invoke it via the java task.
There is an example of running this way in the Ant docs, here slightly modified to include -lib:
<java
classname="org.apache.tools.ant.launch.Launcher"
fork="true"
failonerror="true"
dir="${sub.builddir}"
timeout="4000000"
taskname="startAnt"
>
<classpath>
<pathelement location="${ant.home}/lib/ant-launcher.jar"/>
</classpath>
<arg value="-lib"/>
<arg value="${path.to.your.antlr.jar}"/>
<arg value="-buildfile"/>
<arg file="${sub.buildfile}"/>
<arg value="${sub.target}"/>
</java>

How to create directories specified by a mapper in Ant

Given a fileset
<fileset id="myFiles" dir=".">
<include name="**/*.file"/>
</fileset>
How do I create a sub-directory at each file in the set, named after the filename without the extension?
For example, given the files folderA/X.file and folderA/folderB/Y.file, I want to create the directories folderA/X and folderA/folderB/Y
The ant touch task supports creating files, parent dirs and filename mapping, so can be used to achieve this:
<target name="mkdirs">
<touch mkdirs="true">
<fileset dir="the_dir"/>
<mapper type="glob" from="*.file" to="the_dir/*/.tmp" />
</touch>
<delete>
<fileset dir="the_dir" includes="**/.tmp"/>
</delete>
</target>
This creates temporary files in target dirs (creating the dirs if the don't exist) then deletes the temporary files leaving the dirs you wanted.
You would be using for task to iterate on your file list. But I have not come across any substring type of utility in Ant which you can use to strip the extension and create the directory. Do search for this utility, if its not there then you need to implement an Ant task to do that.
Sorry to answer my own question. Unless someone knows otherwise, there appears to be no way for out-of-the-box ANT to create directories (e.g. using mkdir) relative to entries in a fileset.
Ant-Contrib contains useful for loop tasks, as Bhushan suggests, which could possibly perform this sort of task.
Had some better things to be getting on with, so in the end, I just wrote a batch file called by an ANT task (apply tasks can iterate over filesets).
<apply executable="cmd" failonerror="1">
<arg value="/c"/>
<arg line="build\tools\makeRelDir.bat"/>
<fileset dir=".">
<include name="**/*.file"/>
</fileset>
</apply>
where the batch file does this:
mkdir %~dp1%~n1
(Why is it so hard to do something some simple in ANT? Am I missing something?)

Resources