In ant, I have defined some properties that define some paths ( absolute ) needed in my build system.
Most of ant tasks need filesets, so to build a fileset from a property I would have to do:
<fileset dir="" includes="${myprop}"/>
The problem is that myprop
is absolute and I should omit the dir attribute ( which is not possible ), so is there a way to define (absolute) properties and efficiently use them to create filesets, dirsets, etc.. or in ant is this a bad practice (only relative paths should be used) ?
Thanks.
There's no particular rules about absolute versus relative with Ant. You should avoid hard-coding absolute paths if possible - to make your build more portable. If you have to use absolute paths for some part of the build, try to construct them - say from the ${basedir}
of the project - so that changes are easier to make.
Two things that may be useful for converting absolute paths to relative paths for use in filesets and the like:
property
task supports an attribute relative=
that can be used to convert from an absolute path to relative. pathconvert
task can be used to do the same, when there are several absolute paths in one property. Examples:
<!-- Absolute paths -->
<property name="myprop" value="${basedir}/x" />
<property name="myprop2" value="${basedir}/x:${basedir}/y" />
<!-- Convert single path to relative to basedir -->
<property name="myprop_rel" location="${myprop}" relative="yes"/>
<!-- Go via path/pathconvert for the property with multiple paths -->
<path id="mypath2" path="${myprop2}" />
<pathconvert property="myprop2_rel" refid="mypath2" pathsep=",">
<map from="${basedir}/" to="" />
</pathconvert>
<fileset id="my_fileset" dir="." includes="${myprop2_rel}" />
In response to a comment: I'm not aware of a simple way to get the longest common prefix directory of a fileset in Ant, but here's a macro wrapping a script task that does what you might call 'shrink wrapping'. You call it with a reference to the 'input' fileset, and the name of the property to set.
<macrodef name="common-prefix-dir">
<attribute name="refid" />
<attribute name="outputproperty" />
<sequential>
<script language="javascript"><![CDATA[
srcFiles = project.getReference( "@{refid}" )
.getDirectoryScanner( project )
.getIncludedFiles( );
if ( srcFiles.length > 0 ) {
prefix = "" + srcFiles[0];
for ( i = 0; i < srcFiles.length; i++ ) {
while ( prefix.length && srcFiles[i].substr( 0, prefix.length ) != prefix ) {
prefix = prefix.substr( 0, prefix.length - 1);
}
if ( !prefix.length ) {
break;
}
}
}
else {
prefix = "";
}
prefix = prefix.substring( 0, prefix.lastIndexOf( '/' ) );
project.setProperty( "@{outputproperty}", prefix );
]]></script>
</sequential>
</macrodef>
(This was derived from a php implementation .)
You can try it out with something like:
<property name="my.dir" location="...your dir here..." />
<fileset id="my.fs" dir="${my.dir}">
<!-- define fileset here -->
</fileset>
<echo message="Input fileset is: '${toString:my.fs}'" />
<common-prefix-dir refid="my.fs" outputproperty="prefix" />
<echo message="Longest common prefix is: '${prefix}'" />
The pathconvert
task can now be used to create a shrink-wrapped fileset:
<pathconvert property="shrink" refid="my.fs" pathsep=",">
<map from="${my.dir}/${prefix}/" to="" />
</pathconvert>
<fileset id="my.fs.out" dir="${my.dir}/${prefix}" includes="${shrink}" />
<echo message="Shrink-wrapped fileset is: '${toString:my.fs.out}'" />
I would suggest you to use a different property for the dir
target, if you are doing an absolute reference to ${myprop}, I guess it's a file name. Try it separating it into ${parent.dir} and ${target.filename}.
<fileset dir="${parent.dir}" includes="${target.filename}"/>
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.