I don't want to use propertyregex in the AntContrib task, but I need to modify a property. I am using the cabarc command (I can't get the <cab> task to work), and I need to strip out the drive name.
${basedir} = "D:\some\directory\blah\blah"
${cwd} = some\directory\blah\blah"
I need this in order to strip out the path in cabarc (but still using directories). I've ended up doing the following:
<!-- Create a property set with just basedir -->
<!-- Needed for loadproperties to work -->
<propertyset id="cwd">
<propertyref name="basedir"/>
</propertyset>
<loadproperties>
<propertyset refid="cwd"/>
<filterchain>
<tokenfilter>
<replaceregex pattern=".:\\"
replace="cwd="/>
</tokenfilter>
</filterchain>
</loadproperties>
That works, but it's a little complex and will be hard to maintain.
Is there an easier way to do this?
get into the groove ;-)
<groovy>
properties.'cwd' = properties.'basedir'[3..-1]
</groovy>
or with Ant Plugin Flaka :
<project xmlns:fl="antlib:it.haefelinger.flaka" name="World">
<!-- simple echo -->
<fl:echo>#{replace('${basedir}', '$1' , '.:\\\\(.+)' )}</fl:echo>
<!-- set property -->
<fl:let>cwd := replace('${basedir}', '$1' , '.:\\\\(.+)' )</fl:let>
</project>
Disclosure = i'm participating as committer in the Flaka project
Related
I am trying to achieve following with Ant.
I have a property file where we have list of tokens and their values.
This file is passed to Ant and it works great and does all the normal string replacement.
<copy todir="${target_direcotry}" overwrite="true">
<fileset dir="config">
<include name="*.change_me"/>
</fileset>
<filterset begintoken="<" endtoken=">">
<filtersfile file="${property_file}"/>
</filterset>
<mapper type="glob" from="*.change_me" to="*"/>
</copy>
Now If i have one of the token-value pair as follows :
TOKEN_VALUE1=`./run_me.ksh` in property file.
Target file test.xml.change_me has content :
You have <TOKEN_VALUE1> entries present !!!
With above code in build.xml and this new token in property file i am getting content of test.xml after running ant is :
You have `./run_me.ksh` entries present !!!
Output of script run_me.ksh will decide the value this token and give me output as follows :
Scenario 1 :
Run_me.ksh output: 10
Required content of file test.xml after execution :
"You have 10 entries present !!!"
Scenario 1 :
Run_me.ksh output: 20
Required content of file test.xml after execution :
"You have 20 entries present !!!"
Can i achieve this with Ant function/commands to run such shell script during replacements and how ?
It is technically possible to achieve this with Ant using FilterChain and FilterReader (specifically this one: ScriptFilter). However this is not so trivial and may have some portability issues. You may consider either writing your own task (or a specific FilterReader), or simply define a target that executes your shell script and store its result in a property and the use that property as value for token replacement.
Hereafter a snippet of how to launch a script in your token replacement task :
<copy todir="${target.dir}" overwrite="true">
<fileset dir="${config.dir}">
<include name="*.change_me" />
</fileset>
<filterchain>
<!-- replace token with value in the property file (i.e. `run_me.sh`) -->
<filterreader classname="org.apache.tools.ant.filters.ReplaceTokens">
<param type="propertiesfile" value="${token.properties}" />
</filterreader>
<tokenfilter>
<!-- split result along a specific pattern ('`' character for instance). -->
<stringtokenizer delims="`" delimsaretokens="false" />
<!-- apply a script filter to execute shell if token is script name -->
<scriptfilter language="javascript">
<![CDATA[
if( self.getToken().indexOf(".sh") != -1 ){
<!-- rely on ant Exec task to run script -->
exectask = project.createTask("exec");
exectask.setExecutable("sh");
exectask.createArg().setValue(self.getToken());
<!-- store output in an ant property : -->
exectask.setOutputproperty("result");
exectask.perform();
<!-- retrieve the ant property and use it to replace current token -->
self.setToken(project.getProperty("result"));
}
]]>
</scriptfilter>
</tokenfilter>
</filterchain>
<mapper type="glob" from="*.change_me" to="*" />
</copy>
I'm rewriting build.xml file from Ant to Phing and everything goes fine with one exception.
I need to add new line at the end of each appended file but I can't find any alternative for fixlastline="true".
In Ant it was
<concat destfile="${libraryFilePrefix}.js" fixlastline="yes">
<!-- many filesets -->
</concat>
In Phing it's like
<append destfile="${libraryFilePrefix}.js">
<!-- many filesets -->
</append>
Is there any attribute that works like fixlastline or maybe I need to find another way to achieve this?
I believe, one of the approaches (and possibly the only one) is applying replaceregexp filter on each fileset. You only need to apply filterchain at the beginning and it will do the job for each fileset, like this:
<append destfile="${libraryFilePrefix}.js">
<filterchain>
<replaceregexp>
<regexp pattern="([^\n])$" replace="$1${line.separator}" ignoreCase="true"/>
</replaceregexp>
</filterchain>
<!-- many filesets -->
</append>
As of Phing 3.x the AppendTask is aware of the fixlastline attribute. Your Ant script provided is now working as expected
<project name="concat-supports-fixlastline" default="concat-fixed-lastline" basedir=".">
<target name="concat-fixed-lastline">
<concat destfile="${libraryFilePrefix}.js" fixlastline="yes">
<!-- many filesets -->
</concat>
</target>
</project>
I have an ant property ${src.dirs} that contains a list of dirs separated by a semi colon.
Now i need to specify fileset (for replaceregexp) and that fileset has to contain all java files from all dirs listed in ${src.dirs}.
How can i do it (I don't use any ant-contrib funcky stuff, I use plain vanilla ant).
The src.dirs have this form: /usr/work/dir1/src;/usr/work/java/dir2/src;/usr/libabc/src
There's is an example on how to use propertyregex, but when I try to use it I get this error:
build.xml:98: Problem: failed to create task or type propertyregex
Edit:
Here's what was my final solution:
<loadresource property="source.dir.javafiles">
<propertyresource name="source.dir"/>
<filterchain>
<tokenfilter>
<replaceregex pattern="\s*([;,]\s*)*$" replace="/**/*.java"/>
<replaceregex pattern="\s*([;,]\s*)+" replace="/**/*.java," flags="g"/>
</tokenfilter>
</filterchain>
</loadresource>
<fileset dir="" includes="${source.dir.javafiles}"/>
These regexes ensure that trailing commas or semicolons don't produce wrong fileselectors.
You might be able to do this without using ant-contrib. Here's a possibility:
<property
name="dirlist"
value="/usr/work/dir1/src;/usr/work/java/dir2/src;/usr/libabc/src" />
<property name="file.wildcard" value="*.java" />
<loadresource property="dirs.include">
<propertyresource name="dirlist"/>
<filterchain>
<tokenfilter>
<replaceregex pattern="^/" replace="" />
<replaceregex pattern=";/" replace="/**/${file.wildcard}," flags="g"/>
<replaceregex pattern="$" replace="/**/${file.wildcard}" />
</tokenfilter>
</filterchain>
</loadresource>
<fileset id="files" dir="/" includes="${dirs.include}" />
The work is split into two: first string processing to convert the semicolon-separated list into patterns suitable for use in a fileset includes attribute; second make a fileset from the pattern.
The loadresource task here is simply being used as a wrapper around a sequence of simple regular expression replacements. The three replacements deal with the leading root directory \, expanding the intra-string semicolons into Ant patterns and commas (which are used in includes attributes to separate entries), and adding a pattern at the end of the string.
In your case you might consider tuning this to not use the root directory in the dir attribute of the fileset.
propertyregex is from ant-contrib, which is why the example is not working for you.
Here is one way to achieve what you want.
<pathconvert property="src.dirs.includes" pathsep="/**/*.java,">
<path path="${src.dirs}" />
</pathconvert>
<replaceregexp match="\s+" replace=" " flags="g" byline="true">
<files id="files" includes="${src.dirs.includes}/**/*.java" />
</replaceregexp>
However spaces in any of the filenames (including their path) will stuff you up.
Do you simply have to go through these directories and do your compile, or must these directories be compiled together because of dependencies?
If there are no dependencies, you could try the <for/> task in Ant-Contrib. This lets you loop through a list like the one you have:
<for list="${src.dirs}"
param="my.src.dir"
delimiter=";">
<sequential>
<javac destdir="${javac.destdir}"
srcdir="#{my.src.dir}"
classpathref="main.classpath"/>
</sequential>
</for>
Of course, you might have to munge things for your correct destdir. You may find the <var/> task convenient when you use the <for/> task. The <var/> task allows you to reset variable names. When you repeat the <sequential/> set of tasks, you may find you want to reset certain properties.
By the way, if you have Ant 1.8 or higher, you can use the <local/> task instead of <var/>.
I use task to run a target for all values from the list, taken from one property.
<foreach list="val1,val2" delimiter="," target="my.target" param="param_name"/>
Now, I want to put those values to the separate properties file as there is a lot of them.
So the question is: how can I read multiple (don't know how many) properties (lines in file in fact) from the file into one property?
The property file should look like this:
val1
val2
anothervalue
foobar
And the output should be:
"val1,val2,anothervalue,foobar"
be put in one property.
You can achieve this using LineTokenizer filter with loadfile. For example:
<target name="t">
<loadfile property="data_range" srcFile="ls.txt">
<filterchain> <!-- this filter outputs lines delimited by "," -->
<tokenfilter delimoutput=","/>
</filterchain>
</loadfile>
<foreach list="${data_range}" param="line" delimiter="," target="print" />
</target>
<target name="print">
<echo>line [${line}]</echo> <!-- you can do anything here -->
</target>
I want to use manifestclasspath Ant task. I have a very large build.xml file with a couple of imported other build files and when I run it I get this:
build.xml:1289: The following error occurred while executing this line:
build.xml:165: Property 'some.property' already set!
I am sure that this property is defined only in manifestclasspath task. Here is my code:
<manifestclasspath property="some.property" jarfile="some.jar">
<classpath refid="some.classpath"/>
</manifestclasspath>
This code is located inside of <project>.
What am I doing wrong? Is there a way to add something like condition to set property only if it is not already set? I don't want to use custom Ant tasks such as Ant Contrib's if if there is other way around.
Antcall opens a new project scope, but by default, all of the properties of the current project will be available in the new project. Also if you used something like =
<antcall target="whatever">
<param name="some.property" value="somevalue"/>
</antcall>
in the calling project then ${some.property} is also already set and won't be overwritten, as properties once set are immutable in ant by design.
Alternatively, you may set the inheritAll attribute to false and only "user" properties (those passed on the command-line with -Dproperty=value) will be passed to the new project.
So, when ${some.property} ain't no user property, then use inheritAll="false" and you're done.
btw. it's better to use a dependency between targets via depends="..." attribute than to use antcall, because it opens a new project scope and properties set in the new project won't get back to the calling target because it lives in another project scope..
Following a snippet, note the difference, first without inheritAll attribute
<project default="foo">
<target name="foo">
<property name="name" value="value1" />
<antcall target="bar"/>
</target>
<target name="bar">
<property name="name" value="value2" />
<echo>$${name} = ${name}</echo>
</target>
</project>
output :
[echo] ${name} = value1
second with inheritAll=false
<project default="foo">
<target name="foo">
<property name="name" value="value1" />
<antcall target="bar" inheritAll="false" />
</target>
<target name="bar">
<property name="name" value="value2" />
<echo>$${name} = ${name}</echo>
</target>
</project>
output :
[echo] ${name} = value2
some rules of thumb for antcall, it's rarely used for good reasons :
1. it opens a new project scope (starting a new 'ant -buildfile yourfile.xml yourtarget') so it uses more memory, slowing down your build
2. depending targets of the called target will be called also !
3. properties don't get passed back to the calling target
In some cases it might be ok when calling the same 'standalone' target (a target that has no target it depends on) with different params for reuse. Normally macrodef or scriptdef are used for that purpose. So, think twice before using antcall which also puts superfluous complexity to your scripts, because it works against the normal flow.
Answer to your question in the comment, using a dependency graph instead of antcall
you have some target that holds all conditions and sets the appropriate properties which may be evaluated by targets via if and unless attributes to control the further flow
<project default="main">
<target name="some.target">
<echo>starting..</echo>
</target>
<!-- checking requirements.. -->
<target name="this.target">
<condition property="windowsbuild">
<os family="windows"/>
</condition>
<condition property="windowsbuild">
<os family="unix"/>
</condition>
<!-- ... -->
</target>
<!-- alternatively
<target name="yet.another.target" depends="this.target" if="unixbuild">
-->
<target name="another.target" depends="this.target" unless="windowsbuild">
<!-- your unixspecific stuff goes here .. -->
</target>
<!-- alternatively
<target name="yet.another.target" depends="this.target" if="windowsbuild">
-->
<target name="yet.another.target" depends="this.target" unless="unixbuild">
<!-- your windowspecific stuff goes here .. -->
</target>