Ant failing with Content is not allowed in prolog - ant

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.

Related

Can I use an Ant fileset as input to construct another fileset?

I am automating a build process using Jenkins and Ant build steps. I have the build operation and post-build source control tagging working fine.
After a number of QT projects have been built, I want to be able to preserve the useful artifacts from the build.
As a vehicle for discussion/consideration, lets say I have the following set of files in a build directory:
MyApp.exe
MyApp.pdb
MyApp_Tests.exe
MyApp_Tests.pdb
SomeLib.lib
SomeLib.pdb
3rdParty.lib
3rdParty.pdb
Utils.dll
Utils.pdb
(In reality there are many more exe's, dll's lib's and their associated pdb files and the files produced by the build change frequently as the project evolves.)
I want to collect the "deliverable" files (non-test exe's and dll's) and their pdb files without the test exe's, lib files and their pdb files.
I believe I can get a fileset of the deliverable files to use in a copy task:
<copy todir="${artifactDestination}" failonerror="true">
<fileset dir="./build">
<include name="*.exe" />
<include name="*.dll" />
<exclude name="*_Tests*" />
</fileset>
</copy>
What I am struggling with is how to get a fileset of the pdb files that relate to the exe and dll files, i.e. all the pdb files except MyApp_Tests.pdb, SomeLib.pdb and 3rdParty.pdb.
What I would like to do is use the initial fileset of exe and dll files and create a second fileset from that which has those filenames with a .pdb extension instead of .dll or .exe.
I've been reading up on selectors and such but have not managed to spot a solution to achieve my desired result.
Any suggestions?
You should be able to achieve what you want with two subsequent copy tasks. The first one is the one you've already figured out. In order to copy the .pdb files that match the files you've copied in the first step you can use a present selector.
<copy todir="${artifactDestination}" failonerror="true">
<fileset dir="build">
<or>
<present targetdir="${artifactDestination}">
<globmapper from="*.pdb" to="*.exe"/>
</present>
<present targetdir="${artifactDestination}">
<globmapper from="*.pdb" to="*.dll"/>
</present>
</or>
</fileset>
</copy>

Compile files with certain pattern names in 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>

can you do this seemingly simple Ant copy task without using ant-contrib's foreach?

I have a source directory with a bunch of plugins. Each plugin has its own lib directory. I want the contents of each of those lib directories to be merged into a single lib directory within my build. In theory you'd do something like this:
<copy todir="build/web/lib">
<fileset dir="web/plugins/*/lib/" includes="**/*" />
</copy>
However, Ant chokes when the dir attribute includes a wildcard. Is ant-contrib the only alternative, or can you make this work with vanilla ant?
Choke message is build.xml:28: [...]/web/plugins/*/lib does not exist.
The dir= attribute of a fileset doesn't take a wildcard - hence the error you see. You need to specify a single directory, in this case web/plugins, and use a slightly different wildcard for the includes:
<copy todir="build/web/lib">
<fileset dir="web/plugins" includes="*/lib/**/*" />
</copy>
If you need to alter the paths as you copy, you can use a mapper, for example the flattenmapper will give you file names with all leading directory information stripped off.

How do I convert an Ant Path into a FileSet?

I'm writing an Ant script to package a project into a WAR file. The software consists of several projects with their own source directories, libraries, etc.
The WAR task has a nested element lib which I'm currently working on. I currently have a reference of the required libs as a Path (containing several FileSets, which I use in a classpath reference. The lib, however, wants the input to be a FileSet, and it refuses a Path.
I tried converting my Path into a FileSet, but then I didn't get it to work as a classpath elsewhere.
Is there a way to convert a Path into a FileSet? I would hate to copy-paste the directories.
<path id="compile.libs">
<fileset dir="${common.path}/lib" includes="*.jar"/>
<fileset dir="${data.path}/lib" includes="*.jar"/>
<fileset dir="${gui.path}/lib" includes="*.jar"/>
<fileset dir="${gui.path}/WebContent/WEB-INF/lib" includes="*.jar"/>
</path>
...when used with <war ..><../> <lib refid="compile.libs"/> </war> leads to:
BUILD FAILED
build.xml:173: compile.libs doesn't denote a zipfileset or a fileset
Assuming the paths are absolute, you can first convert the Path to a comma-delimited list using <pathconvert>, and then convert the list back into a Fileset:
<!-- create path -->
<path id="foo.path">
<pathelement location="/foo/bar/baz.txt"/>
<pathelement location="/qux/quux/quuux.txt"/>
</path>
<!-- convert foo.path to foo.list -->
<pathconvert
refid="foo.path"
property="foo.list"
pathsep=","
dirsep="/"
>
<!--
<fileset> will want relative paths, so we need to strip
the leading /. result: "foo/bar/baz.txt,qux/quux/quuux.txt"
-->
<map from="/" to=""/>
</pathconvert>
<!-- convert foo.list to fileset -->
<fileset id="foo.fileset" dir="/" includes="${foo.list}"/>
(Note the above assumes Unix; you may need to fiddle a bit with separators and whatnot if you're on Windows or you want to make it platform-independent.)
You may have several choices.
You may provide more than one
<lib> nested element to <war>
task. Maybe this would be enough.
You may preassemble all of your
lib files in one temporary
directory and then just reference that
directory as a fileset.
There is an ant-contrib
PathToFileSet task, but it
requires a central root directory,
and this may not be a case with your
compile.libs layout.
Since Ant 1.8.0 you can use a mappedresources. Source: Ant script: Prevent duplication of JAR in javac-classpath war-lib
I think I would try option 1.
I solved this by staging the libs like this :
<copy todir="stage/libs" flatten="true">
<path refid="classpath" />
</copy>
and then using a in the WAR task.simple.
The jars in the classpath used to compile are not the same that needs to be packaged inside the war. For example: I'm sure you need servlet-api.jar to compile your project but you don't need it inside the war because the container provides it. And some jars aren't needed at compile time but at runtime.
I know I'm not answering your question, just want you to think what you are doing.

ANT: Force error on missing resource?

I've inherited an Ant build system that contains many resource
set definitions like this:
<files id="app1.lib.jars">
<include name="${java}/jre/lib/jsse.jar"/>
<include name="${work.lib}/jtidy.jar"/>
...
</files>
<files id="app2.lib.jars">
<include name="${work.lib}/itext.jar"/>
<include name="${work.lib}/commons-httpclient.jar"/>
...
</files>
<files id="app3.lib.jars">
<include name="${work.lib}/jdom.jar"/>
<include name="${ant.lib}/ant.jar"/>
...
</files>
There are perhaps a dozen of these, and each can contain anywhere from
5 to 50 files. The problem is that I'm reworking this system to use
Ivy for dependency management, and in the process some of the
references now point to non-existent files. Unfortunately, Ant does
not provide any help finding these bad pointers. When these resource
collections are used to define a classpath any <include...> tags
pointing to missing files are silently ignored.
I thought I could force an error by using the collections as the
source of a <copy...>, but even with failonerror="true" it just
ignored the bad references.
The command-line -v (verbose) and -d (debug) option didn't help
either. The output acknowledged that some were missing but didn't
actually show them
[echo] app1.lib.jars
[copy] C:\dev\src\tomcat6\work\java\jre\lib\jsse.jar omitted as C:\dev\src\tomcat6\work\verify\jsse.jar is up to date.
[copy] C:\dev\src\tomcat6\work\lib\axis-ant.jar omitted as C:\dev\src\tomcat6\work\verify\axis-ant.jar is up to date.
...
[copy] No sources found.
[echo] app2.lib.jars
...
For a one-time solution I extracted all the filenames from the
resource sets in the Ant file and compared that to a directory listing
of the result of copying all the files (in Ant) into a temporary
directory, after appropriate sorting.
Question: Is there a way to get Ant to tell me when a resource points
to a missing file, preferably at the time the resource is defined?
Here's an illustration of one method. Key points
Convert your files to filelists - these can contain names of files that don't exist in the file system, unlike filesets and files, that ignore entries that don't exist
Use a restrict to check for existence
Use a fail to error when something is missing
You'll need to add the "antlib:org.apache.tools.ant.types.resources.selectors" namespace to the project to use the resource selectors shown below. You'll hit snags with Ant versions older than 1.7.0.
<project name="so" default="checkfiles" basedir="."
xmlns:rsel="antlib:org.apache.tools.ant.types.resources.selectors">
<filelist id="app1.lib.jars">
<file name="${java}/jre/lib/jsse.jar"/>
<file name="${work.lib}/jtidy.jar"/>
...
</filelist>
<restrict id="missing.app1.lib.jars">
<filelist refid="app1.lib.jars"/>
<rsel:not>
<rsel:exists/>
</rsel:not>
</restrict>
<property name="missing.files" refid="missing.app1.lib.jars" />
<fail message="These files are missing: ${missing.files}">
<condition>
<length string="${missing.files}" when="greater" length="0" />
</condition>
</fail>
<pathconvert property="found.files" refid="app1.lib.jars" />
<echo message="Found files ${found.files}" />
Alternatively, you could use the 'copy' task, as you suggest, but with filelists instead of files.
The copy should fail when it tries to process the first resource that doesn't exist.

Resources