subant on condition - ant

I'd like to execute subant on some condition. something like:
<if>
<equals value="value1" property="${some.property">
<then>
<subant target="#{target}" failonerror="true" inheritall="false">
<buildpath refid="some-ref1" />
</subant>
</then>
<else>
<subant target="#{target}" failonerror="true" inheritall="false">
<buildpath refid="some-ref2" />
</subant>
</else>
</if>
But can't find a way to do it. Read the ant manual and googled, but no solution is found.
Thanks.

I believe the error may lie in your equals tag. Instead of using the 'value' and 'propery' attributes, try using 'arg1' and 'arg2', i.e.:
<equals arg1="value1" arg2="${some.property}">
Check out the examples in the ant-contrib doc: http://ant-contrib.sourceforge.net/tasks/tasks/if.html.
If the problem is that your 'if', 'then', and/or 'else' tags are not resolving properly, then you may be missing the ant-contrib libraries. Ant-contrib is not natively included with ant, but you can download it here: http://sourceforge.net/projects/ant-contrib/files/
Per the ant-contrib site (http://ant-contrib.sourceforge.net/), here's what you must do to install ant-contrib:
Option 1: Copy ant-contrib-0.3.jar to the lib directory of your Ant installation. If you want to use one of the tasks in your own project, add the lines
<taskdef resource="net/sf/antcontrib/antcontrib.properties"/>
to your build file.
Option 2: Keep ant-contrib-0.3.jar in a separate location. You now have to tell Ant explicitly where to find it (say in /usr/share/java/lib):
<taskdef resource="net/sf/antcontrib/antcontrib.properties">
<classpath>
<pathelement location="/usr/share/java/lib/ant-contrib-0.3.jar"/>
</classpath>
</taskdef>

Please look up a <target if="${some.property}>. You may want another target with an unless.
If the property has to do with a file existing, see Ant task to check a file exists?. Even if this is not your main concern, I am sure you can get the idea from the accepted answer.

Do you mean calling another target
if so here is
<if>
<equals value="value1" property="${some.property">
<then>
<antcall target="#{target}" failonerror="true" inheritall="false">
</then>
<else>
<antcall target="#{target}" failonerror="true" inheritall="false">
</else>
</if>

Related

How to check if Ant is executed under certain path?

How can I use Ant to verify that the current working directory is located (arbitrarily deeply nested) under a certain path? For example, I want to execute a target only if the current directory is part of /some/dir/, for example if Ant is executed in directory /some/dir/to/my/project/.
The best I could come up with is a String contains condition:
<if>
<contains string="${basedir}" substring="/some/dir/"/>
<then>
<echo>Execute!</echo>
</then>
<else>
<echo>Skip.</echo>
</else>
</if>
This works for my current purpose but I'm afraid it might break some time in the future... for example when a build is executed in path /not/some/dir/ which is also contains the specified directory string.
Are there any more robust solutions like a startsWith comparison or even better a file system based check...?
There is no specific startswith condition in native Ant, but there is a matches condition that takes regular expressions.
As a side note, ant-contrib is rarely necessary for most build scripts, and will often lead to unreliable code. I would strongly recommend avoiding it.
Here's a sample script to illustrate how you can use the matches condition with native Ant. The test target is, of course, just for demonstration.
<property name="pattern" value="^/some/dir" />
<target name="init">
<condition property="basedir.starts.with">
<matches pattern="${pattern}" string="${basedir}" />
</condition>
</target>
<target name="execute" depends="init" if="basedir.starts.with">
<echo message="Executing" />
</target>
<target name="test">
<condition property="dir1.starts.with">
<matches pattern="${pattern}" string="/some/dir/" />
</condition>
<condition property="dir2.starts.with">
<matches pattern="${pattern}" string="/some/dir/to/my/project/" />
</condition>
<condition property="dir3.starts.with">
<matches pattern="${pattern}" string="/not/some/dir/" />
</condition>
<echo message="${dir1.starts.with}" />
<echo message="${dir2.starts.with}" />
<echo message="${dir3.starts.with}" />
</target>

ant conditional execution (if-else statement in ant) and checking that a property isn't empty string

Currently I have this code in ant script:
<target name="-pre-compile" if="${log.disabled}">
<antcall target="remove-logs"/>
</target>
It's pretty self explanatory: if log.disable=true in properties file, then my remove-logs target will be called. Now I need to make minor changes to if/else. Pseudo-code:
<target name="-pre-compile">
if("${log.disabled}")
<antcall target="remove-logs"/>
else if("${log.disabled.level}" != "")
<antcall target="remove-logs-levels"/>
</target>
how can I write that in ant?
Also, note that all these if/them ant-contrib do not work for me:
<target name="test-xxx">
<echo level="info">testing</echo>
<if>
<equals arg1="${log.disabled}" arg2="true" />
<then>
<echo message="true" />
</then>
<else>
<echo message="false" />
</else>
</if>
</target>
get's me this output:
custom_rules.xml:73: if doesn't support the nested "equals" element.
PS. Once again, I ended up writing javascript instead of wasting time with ant itself. What a crappy make replacement...
Ant provide conditionals. Frankly using ant-contrib is easier. It provides an if task. See a more detailed answer in ant-contrib - if/then/else task

Check the existence file in ant [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Ant task to check if a file exists?
How can one check if a file exist in a directory, if not use another file in different location. I tried the follow but does not help me with what I want. Could someone help?
<condition property="somefile.available">
<or>
<available file="/home/doc/somefile"/>
<and>
<available file="/usr/local/somefile" />
</and>
</or>
</condition>
Use condition tests to establish if files are present. Then have a target for each true condition
<target name="go" depends="file-checks, do-something-with-first-file, do-something-with-second-file"/>
<target name="file-checks">
<available file="/home/doc/somefile" property="first.file.found"/>
<available file="/usr/local/somefile" property="second.file.found"/>
</target>
<target name="do-something-with-first-file" if="first.file.found">
???
</target>
<target name="do-something-with-second-file" if="second.file.found">
???
</target>
If you don't mind using ant-contrib you can take the procedural approach like this:
<if>
<available file="file1"/>
<then>
<property name="file.exists" value="true"/>
</then>
<else>
<if>
<available file="file2"/>
<then>
<copy file="file2" tofile="file1"/>
<property name="file.exists" value="true"/>
</then>
</if>
</else>
</if>
Otherwise you can probably use a target that is conditional on a property being set to indicate whether the file already exists in the preferred location, like Ant task to run an Ant target only if a file exists? but using unless instead of if.

In Ant, can I use a property inside a target's "depends"?

I m trying to do this with Ant:
<property name="test" value="123"/>
<target name="helloworld" depends="${test}"/>
But I'm getting error "Target ${test} does not exist in this project."
So I m guessing I can do this?
You can use the AntCall Task to call a Task inside another Task.
<project>
<target name="asdf">
<property name="prop" value="qwer" />
<antcall target="${prop}" />
</target>
<target name="qwer">
<echo message="in qwer" />
</target>
</project>
To make one depend on the other, you can set a parameter in the dependent task and check it in your calling task.
Rather than depends, you can check a property using the if attribute. See the manual for more details.
For example:
<target name="helloworld" if="test"/>
Note this only checks if the property is set (you can use unless to check if it is unset).
An alternative, more complex but powerful, approach is to use a nested condition on a depended target:
<target name="helloworld" depends="myTarget.check" if="myTarget.run">
...
</target>
<target name="myTarget.check">
<condition property="test">
<and>
<available file="foo.txt"/>
<available file="bar.txt"/>
</and>
</condition>

Testing Macrodef Attribute without IF

I am attempting to remove all lines that begin with log if a macrodef attribute is set to prod (example below). I plan on using replaceregexp to remove all lines beginning with log. However, I am not sure how to test if an attribute is set to a specific value, besides using the if task. I would like to not introduce any non-core Ant tasks to perform this, but I can't come up with any other solutions. Do I have any other options besides using the if-task?
Thanks
<macrodef name="setBuildstamp">
<attribute name="platform" />
<sequential>
<if>
<equals arg1="platform" arg2="prod" />
<then>
<replaceregexp match="^log\(.*" value="" />
</then>
</if>
</sequential>
</macrodef>
You should use a reference to a parameter, like this #{platform}.
Also, your replaceregexp task is missing a few parameters.
I think that in your particular case it is better to use linecontainsregexp filter reader. Here is modified code (note negate argument to linecontainsregexp).
<macrodef name="setBuildstamp">
<attribute name="platform" />
<sequential>
<if>
<equals arg1="#{platform}" arg2="prod" />
<then>
<copy todir="dest-dir">
<fileset dir="src-dir"/>
<filterchain>
<linecontainsregexp
regexp="^log\(.*"
negate="true"
/>
</filterchain>
</copy>
</then>
</if>
</sequential>
</macrodef>
They may be a couple of ways to solve this, but none are as straightforward as using the ant-contrib element. I'm not sure if this will get you what you need for your application, but you could try the following:
Using conditional targets. If you can replace your macrodef with a target to call, this may work for you. Note that this will set the property globally, so it might not work for your application.
<target name="default">
<condition property="platformIsProd">
<equals arg1="${platform}" arg2="prod" />
</condition>
<antcall target="do-buildstamp" />
</target>
<target name="do-buildstamp" if="platformIsProd">
<echo>doing prod stuff...</echo>
</target>
Handle the 'else' case. If you need to handle an alternate case, you'll need to provide a few targets...
<target name="default">
<property name="platform" value="prod" />
<antcall target="do-buildstamp" />
</target>
<target name="do-buildstamp">
<condition property="platformIsProd">
<equals arg1="${platform}" arg2="prod" />
</condition>
<antcall target="do-buildstamp-prod" />
<antcall target="do-buildstamp-other" />
</target>
<target name="do-buildstamp-prod" if="platformIsProd">
<echo>doing internal prod stuff...</echo>
</target>
<target name="do-buildstamp-other" unless="platformIsProd">
<echo>doing internal non-prod stuff...</echo>
</target>
Using an external build file. If you need to make multiple calls with different values for your property, you could isolate this in another build file within the same project. This creates a bit of a performance hit, but you would not need the additional library.
in build.xml:
<target name="default">
<ant antfile="buildstamp.xml" target="do-buildstamp" />
<ant antfile="buildstamp.xml" target="do-buildstamp">
<property name="platform" value="prod" />
</ant>
<ant antfile="buildstamp.xml" target="do-buildstamp">
<property name="platform" value="nonprod" />
</ant>
</target>
in buildstamp.xml:
<condition property="platformIsProd">
<equals arg1="${platform}" arg2="prod" />
</condition>
<target name="do-buildstamp">
<antcall target="do-buildstamp-prod" />
<antcall target="do-buildstamp-other" />
</target>
<target name="do-buildstamp-prod" if="platformIsProd">
<echo>doing external prod stuff...</echo>
</target>
<target name="do-buildstamp-other" unless="platformIsProd">
<echo>doing external non-prod stuff...</echo>
</target>
Add ant-contrib to your project. Of course, if you can add a file to your project, the easiest thing would be to just add the ant-contrib.jar file. You could put it under a "tools" folder and pull it in using a taskdef:
<taskdef resource="net/sf/antcontrib/antlib.xml" classpath="${basedir}/tools/ant-contrib.jar" />
It looks like when you are building your project specifically for your Production environment - you are stripping out code you don't want to run in Production. Thus you are creating a different binary than what will run in your Dev or Testing environment.
How about using an environment variable or property file at run-time instead of build-time which determines whether or not logging happens? This way when you're having trouble in Production and you want to use the same exact binary (instead of determining the revision, checking out the code, rebuilding with a different environment flag) you just re-deploy it to your Dev or Test environment and turn on debugging in a properties file or environment variable?

Resources