You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@ant.apache.org by gl...@ca.ibm.com on 2000/05/17 22:28:56 UTC

Re: A question about "available" and doing conditionals in a build xml file.





There is a pretty easy way around your problem if you are willing to create
more targets in your build, use a custom task, and use the "if" attribute
of the target.

Try something like the following:

<target name="compile_src"
depends="check_idl2java,do_idl2java,do_java_compile">
  <!-- dummy target used to control the order of execution -->
</target>

<target name="check_idl2java">
  <available file="some_well_known_file" property="found.generated"/>
  <ifnotdef property="found.generated" set="couldnt.find.generated"/>
</target>

<target name="do_idl2java" if="couldnt.find.generated"
depends="check_idl2java">
  <!-- do your idl to java compilation --->
</target>

<target name="do_java_compile" depends="do_idl2java">
  <!-- yadda yadda yadda -->
</target>

The ifnotdef task simply checks at execute and init time if the property
specified by the "property" attribute exists.  If it does, it sets the
property specified by the "set" attribute to "true", or to a specified
value if there is an = in the text.  There is also an "unset" attribute you
can use to remove a property.  I have a corresponding ifdef task that does
the logical opposite.

Here's the code for the ifnotdef task.  I've moved it from our
com.ibm.id.tools.ant.taskdefs package to the
org.apache.tools.ant.taskdefs.optional to make incorporating it a little
easier for you.  Sorry for the poor indenting, but VisualAge for Java
doesn't do the best job of exporting code from its repository to a file.
:-(

--- START FILE ---
package org.apache.tools.ant.taskdefs.optional;

import org.apache.tools.ant.*;
import org.apache.tools.ant.taskdefs.*;

/**
 * The IfNotDef taks is used to set and unset/remove properties at runtime.
 *
 * Creation date: (3/14/00 10:42:24 PM)
 * @author: Glenn McAllister
 */
public class IfNotDef extends Task {
        private java.lang.String set = null;
        private java.lang.String prop = null;
        private java.lang.String unSet = null;
/**
 * The execute method is used rather than init to ensure that the setting
and
 * unsetting of properties happens at runtime, rather than at "compile"
time.
 *
 * Creation date: (3/14/00 10:48:30 PM)
 * @exception org.apache.tools.ant.BuildException The standard build
exception wrapper.
 */
public void execute() throws org.apache.tools.ant.BuildException {
        if (prop == null) {
                throw new BuildException("The property to test must have a
value!");
        }

        if(project.getProperty(prop) == null) {
                if (set != null) {
                        setProperty();
                }

                if (unSet != null) {
                        project.log("Removing property " +
unSet,"IfNotDef",project.MSG_VERBOSE);
                        project.getProperties().remove(unSet);
                }
        } // if
}
/**
 * Set the name of the project property to test the existance of.
 *
 * Creation date: (3/14/00 10:46:09 PM)
 * @param newProp java.lang.String
 */
public void setProp(java.lang.String newProp) {
        prop = newProp;
}
/**
 * If the property exists, set the value to true, or to a specific value if
the
 * "set" attribute has an equals sign in it.
 * <p>
 * For example,<br>
 * <code>
 * <IfNotDef prop="some.property"
set="i.want.to.set.this.to=some_nifty_value" />
 * </code><br>
 * will set the property i.want.to.set.this.to to the string
some_nifty_value.
 * </p>
 *
 * Creation date: (3/15/00 7:52:17 PM)
 * @param set java.lang.String
 */
protected void setProperty() {
        // check to see if the property is to be set to a specific value.
        int pos;
        String prop_to_set = null;
        String value = null;

        if ((pos = set.indexOf("=")) > 0) {
                prop_to_set = set.substring(0,pos-1);
                value = set.substring(pos+1);
        } else {
                prop_to_set = set;
                value = "true";
        }
        project.setProperty(prop_to_set, value);
}
/**
 * The name of the property to set to "true", or to a specific value.
 * <p>
 * For example,<br>
 * <code>
 * <IfNotDef prop="some.property"
set="i.want.to.set.this.to=some_nifty_value" />
 * </code><br>
 * will set the property i.want.to.set.this.to to the string
some_nifty_value.
 * </p>
 *
 * Creation date: (3/14/00 10:43:35 PM)
 * @param newSet java.lang.String
 */
public void setSet(java.lang.String newSet) {
        set = newSet;
}
/**
 * The name of the property to remove from the project property set.
 *
 * Creation date: (3/14/00 10:46:38 PM)
 * @param newUnSet java.lang.String
 */
public void setUnset(java.lang.String newUnSet) {
        unSet = newUnSet;
}
}
--- END FILE ---

Glenn McAllister
TID - Software Developer - VisualAge for Java
IBM Toronto Lab, (416) 448-3805
"An approximate answer to the right question is better than the
right answer to the wrong question." - John W. Tukey

Conor MacNeill wrote:

>
> Conditional execution of tasks is a topic of considerable debate on the
ant
> list. Many people have a strong desire to avoid creating within ant a new
> programming language.
>
> Conor

I agree 100%. And, I'm new to this arena, so
I'm not up to speed on what's been proposed, debated,
etc.

I'm trying to move from an Imakefile / Makefile
universe, and that stuff is a MESS. Full of fragments of
shell script, etc, etc. I have been able to do 95% of what
those Imakefiles did without anything special, and the build
xml file is more more readable.

But, there's the remaining 5%. And that 5% are the tasks
that have some conditional processing. If the build
universe were perfect, we could live without it. But,
I've never encountered a perfect world yet.

When I read about the "available" task,
it made sense that I could set a property to check
to see if something is available. But, if there isn't any
facility to use those properties to conditionally
perform some other task, then what's the point?

For example, we use CORBA. Before the java sources can
be compiled, we need to run a program that does idl to java
processing, creating additional java sources to be compiled.

If I make the compile target depend on the idl2java target,
then every time I compile, the idl2java processing occurs
and the generated java files' time stamps change, so now
ant thinks there are a bunch of files that need to be
recompiled. But the content of those generated files
really didn't change, so there is no reason to
re-compile. If I could set and TEST a property to see if one
of the generated files was present, I could suppress
the idl2java processing, and solve this problem. Next
time I do a "clean", the generated java files would
disappear, the corresponding 'available' property would be false,
and so I'd do the idl2java processing, then the compile.

I can't be the only one with this kind of situation in
a build. But right now, since I can't conditionally
run a java program based on the value of a property,
I have to live with having the idl to java processing happen
every build, causing extra compilation.

Or am I being dumb in this area, and not catching on to
some capability that would do what I want???

Thanks!

-ken




Re: A question about "available" and doing conditionals in abuild xml file.

Posted by Ken Wood <kw...@i2.com>.
Thanks, I've got a variation of this that
works great. I appreciate your advise. I've
also learned more about the general state
of 'Ant' from the followups, and I appreciate
those as well.

Just FYI, what I did was this - when I do 
the 'clean' target, I use "exec touch"
to create a file called "need.idl.made". Then,
I can use the available property to control
the idl2java target. That target runs if
"need.idl.made" is present. Within the idl2java
target I use the delete task to remove "need.idl.made"
and so the next time I compile, the idl2java step
is skipped. This way, I only needed one target to
set the property, and didn't need the custom task
to set a second property based on the first property.


glennm@ca.ibm.com wrote:
> 
> There is a pretty easy way around your problem if you are willing to create
> more targets in your build, use a custom task, and use the "if" attribute
> of the target.
> 
>

Re: A question about "available" and doing conditionals in a build xml file.

Posted by Mariusz Nowostawski <ma...@marni.otago.ac.nz>.
Well, I am also pretty new to the issue with conditional tasks, but
if Ant allows to have targets with "if", there is really no big
difference to allow targets with "ifnot" or "unless". That would make the
example below given by Glenn much simpler and shorter (and it would mean
no need for ifdef and ifnotdef tasks).

I also like the idea of available + ifdef + ifnotdef `tasks (if we can
have
only if in targets).

Would it be possible for those three tasks to have the same way for
setting a property?  In proposed by Glenn solution attribute
"property" means two different things in "available" and "if*def" tasks,
which can be confusing. Maybe:
<available file="some_well_known_file" property="a.property"/>
...
<ifnotdef test="a.property" property="another.property"/>
<ifdef test="a.property" property="another.property"/>

Mariusz


-----------
Glenn wrote:

> There is a pretty easy way around your problem if you are willing to create
> more targets in your build, use a custom task, and use the "if" attribute
> of the target.
> 
> Try something like the following:
> 
> <target name="compile_src"
> depends="check_idl2java,do_idl2java,do_java_compile">
>   <!-- dummy target used to control the order of execution -->
> </target>
> 
> <target name="check_idl2java">
>   <available file="some_well_known_file" property="found.generated"/>
>   <ifnotdef property="found.generated" set="couldnt.find.generated"/>
> </target>
> 
> <target name="do_idl2java" if="couldnt.find.generated"
> depends="check_idl2java">
>   <!-- do your idl to java compilation --->
> </target>
> 
> <target name="do_java_compile" depends="do_idl2java">
>   <!-- yadda yadda yadda -->
> </target>
> 
> The ifnotdef task simply checks at execute and init time if the property
> specified by the "property" attribute exists.  If it does, it sets the
> property specified by the "set" attribute to "true", or to a specified
> value if there is an = in the text.  There is also an "unset" attribute you
> can use to remove a property.  I have a corresponding ifdef task that does
> the logical opposite.
> 
> Here's the code for the ifnotdef task.  I've moved it from our
> com.ibm.id.tools.ant.taskdefs package to the
> org.apache.tools.ant.taskdefs.optional to make incorporating it a little
> easier for you.  Sorry for the poor indenting, but VisualAge for Java
> doesn't do the best job of exporting code from its repository to a file.
> :-(

[....]

> 
> Glenn McAllister
> TID - Software Developer - VisualAge for Java
> IBM Toronto Lab, (416) 448-3805
> "An approximate answer to the right question is better than the
> right answer to the wrong question." - John W. Tukey
>