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

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>

Related

How do you make a file to read only in an ant build?

I have an existing ant build file that zips up some files, but I want to make some files read only in the zip on osx and windows. Is this possible?
I've found you can change the read only attribute on windows with <attrib>, but "Right now it has effect only under Windows". Any cross platform solutions?
chmod is the Unix-only way, but there is no cross-platform task.
But when you say you want to make the files read-only inside the ZIP then you don't need to modify the files on disk (in fact it wouldn't have any effect on the permissions stored inside the archive if you use Ant's zip task). In order to set permissions of archive entries, use a zipfileset and the filemode attribute. Something along the lines of
<zip ...>
<fileset dir="...">
<exclude name="files that should be read-only"/>
</fileset>
<zipfileset dir="..." filemode="444">
<include name="files that should be read-only"/>
</zipfileset>
</zip>

Ant copy files to dir while renaming original files

I have a task that needs to copy over files to a certain location. If the files already exist in the destination, these destination files need to be renamed (appended with .bak). If the destination file doesn't exist, the file should just be put into place.
Currently I have this:
<target name="install-jsps">
<copy todir="target">
<fileset dir="source"/>
<globmapper from="*.jsp" to="*.jsp.bak"/>
</copy>
</target>
This however renames the source files while I want to rename the target files before copying over the source files. I cannot do a rename of the whole target folder because some target files are not in the source fileset.
Preferably I don't want to use an external library like ant-contrib.
You can do it in two copy tasks: one to make the backups, one to copy in the new files from the source. The extra bit you need is the present selector in the fileset used to make the backup. The selector allows you to only back up the files that are about to be superceded, i.e. the ones that are present in the source directory.
<copy todir="dest">
<fileset dir="dest" includes="*.jsp">
<present targetdir="source" />
</fileset>
<globmapper from="*" to="*.bak" />
</copy>
<copy todir="dest">
<fileset dir="source" includes="*.jsp" />
</copy>

adding the specified folders in the jar created using ant

I have a folder structures
build/classes/com/vaannila/domain/.class files
build/classes/com/vaannila/service/.class files
build/classes/com/vaannila/web/.class files
My requirement is to create a jar file using ant, how can I include the specified folders in the jar,say I want include only domain and service (or) domain and web in the jar, like the way I create the jar using Eclipse(Export-->archive file).
Can anyone help me with this please?
You can use include and exclude tags in the fileset element, and choose specific files...
<jar destfile="${jar.dir}/${jar.file.name}" index="true"
manifest="${manif.dir}/${manif.file.name}">
<fileset dir="${build.classes.dir}" >
<include/>
<exclude/>
</fileset>
</jar>
<fileset dir="${build.classes.dir}">
<exclude name="**/property/*"/>
<include name="**/abcd/*"/>
</fileset>
This way you can remove/include respective directories.

Copy content of subfolders with Ant

How can I copy content of all subfolders of given folder using Ant?
i.e. I have such folder structure
folder/
folder/sub1/1.txt
folder/sub1/f1/1.txt
folder/sub2/2.txt
...
I don't know exact names of subfolders. And I need to copy content from all of them into one folder (keeping the structure of content, i.e. copying all files into one dir using flatten isn't a solution). I need to get
newfolder/1.txt
newfolder/1/1.txt
newfolder/2.txt
...
Does fileset allows to group subfolders in such a way?
** stands for zero or more directories, and usage of * as directory name is disallowed, i.e. <fileset dir="${dir}/*/" /> isn't acceptable.
Thanks in advance, Yury
<copy toDir="newfolder">
<fileset dir="folder">
<include name="*/**"/>
<exclude name="*"/>
</fileset>
<regexpmapper from="^[^/]*/(.*)$$" to="\1" handledirsep="true"/>
</copy>
You only need to specify handledirsep if you ever intend to run this script in Windows.

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.

Resources