You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@ant.apache.org by Cyril Sagan <cy...@gmail.com> on 2013/09/27 00:15:49 UTC
"scoping" for macro definitions?
Is there a way to override a macro defined from a library I cannot
control, my goal is to provide a local implementation, but not have to
change all the callers.
I'm stuck on Ant 1.7.0, and cannot update.
How could I "fake out" a scoping mechanism to accomplish something like:
<super.macroImplementation/> or <project[@name].macroImplemenation/>
I tried using <presetdef/> to "override" the macro, but I can't figure
out how to invoke the original macro of the same name. I could
redefine the macro from the library in my local ant script, but I
don't want to open a possibility that my local implementation could
get out of sync with the one from the provided library.
Another way to express what I need is the macro equivalent of target
overriding, which is accomplished with the code snip below, but I need
it for <macrodef/>!
common.xml:
<project name="common_library">
<target name="stuff">
<!-- run stuff from common library -->
</target>
</project>
build.xml:
<project name="myBuild">
<import file="common.xml" />
<target name="stuff" depends="mystuff_first, common_library.stuff"
/>
<!-- henceforth target="stuff" is *my* implementation -->
</project>
But what if its a macro (or scriptdef)? In principle here's what I was
hoping could
work, but it doesn't, so that's why I'm asking:
common.xml:
<project name="common_library">
<macrodef name="routine">
<attribute name="arg1" />
<attribute name="arg2" />
<sequential>
<!-- macro definition from common library -->
</sequential>
</target>
</project>
build.xml:
<project name="myBuild">
<import file="common.xml" />
<presetdef name="routine">
<local_routine/>
</presetdef>
<macrodef name="local_routine">
<attribute name="arg1" />
<attribute name="arg2" />
<sequential>
<!-- add some logic here... -->
<common_library.routine arg1="@{arg1} arg2="@{arg2}" />
</sequential>
</macrodef>
<!-- henceforth <routine/> is *my* implementation -->
</project>
Any ideas would be much appreciated. Thanks.
--Cyril
RE: "scoping" for macro definitions?
Posted by Martin Gainty <mg...@hotmail.com>.
that was my initial answer .. but then I considered the collision of the global ant namespace (that macrodef plays in) with a customised non-ant namespace
<Macrodef> is implicitly declared within Ants global namespace
The default namespace used by Ant is "antlib:org.apache.tools.ant".
thus
embedding any other elements with non-ant namespaces inside Ant global namespace is verboten
(that is up until the end tag </Macrodef> is encountered)
Parser> I am parsing macrodef with antlib:org.apache.tools.ant namespace
Operator>Here is new Element with New Namespace embedded inside Macrodef
Parser:No you cannot I am still parsing the elements and attributes of antlib:org.apache.tools.ant.namespace
Since Ant namespace is globally available we can reference Ant namespace types inside customised namespaces
consider:
>From Ant 1.6.2, elements nested inside a namespaced element may also be in Ant's default namespace. This means that the following is now allowed:
<typedef resource="org/example/tasks.properties"
uri="http://example.org/tasks"/>
<my:task xmlns:my="http://example.org/tasks">
<config a="foo" b="bar"/> <!-- embedded element inside ANTs default namespace so this is ok-->
...
</my:task>
NOT allowed
<typedef resource="org/example/tasks.properties"
uri="http://example.org/tasks"/>
<task xmlns:my="http://example.org/tasks">
<my:config a="foo" b="bar"/> <!-- custom namespace is not aware of types declared from ant namespace -->
...
</task>
IMHO DefineAttribute static class (embedded in Macrodef) is the solution why
1)DefineAttribute stays within the Macrodef and stays within global ant namespace (antlib:org.apache.tools.ant) boundaries
2)DefineAttribute accomodates assignment of unique values for each instantation of the MacroDef
Here is the code
/**
481: * A nested define element for the MacroDef task.
482: *
483: * It provides an attribute with a guaranteed unique value
484: * on every instantiation of the macro. This allows to use
485: * this uniquely named attribute in property names used
486: * internally by the macro, thus creating unique property
487: * names and side-stepping Ant's property immutability rules.
488: * <p>
489: * Of course, this work around as the side effect of littering
490: * the global Ant property namespace, so is far for ideal, but
491: * will have to make do awaiting a better fix...
492: *
493: * @since ant 1.7
494: */
495:... public static class DefineAttribute extends Attribute {
496:
497: private static long count = 0;
498: private String prefix = "";
499:
500: /**
501: * Sets a prefix for the generated name.
502: *
503: * @param prefixValue the prefix to use.
504: */
505:... public void setPrefix(String prefixValue) {
506: prefix = prefixValue;
507: }
508:
509: /**
510: * Sets the default value.
511: *
512: * This is not allowed for the define nested element.
513: *
514: * @param defaultValue not used
515: * @throws BuildException, always
516: */
517:... public void setDefault(String defaultValue) {
518: throw new BuildException(
519: "Illegal attribute \"default\" for define element");
520: }
521:
522: /**
523: * Gets the default value for this attibute.
524: *
525: * @return the generated <em>unique</em> name, of the form
526: * "prefix#this classname#<aCounter>".
527: */
528:... public String getDefault() {
529:... synchronized (DefineAttribute.class) {
530: // Make sure counter is managed globally
531: return prefix + "#" + getClass().getName() + "#" + (++count);
532: }
533: }
534:
535: } // END static class DefineAttribute
http://www.javadocexamples.com/java_source/org/apache/tools/ant/taskdefs/MacroDef.java.html
-Martin
> Date: Thu, 26 Sep 2013 15:43:24 -0700
> From: vimilsaju@yahoo.com
> Subject: Re: "scoping" for macro definitions?
> To: user@ant.apache.org
>
> I am not sure if this feature is available in ant 1.7 but can't you use namespaces to scope the macrodefs like follows
>
> <project name="testBuild" default="all" basedir="." xmlns:c="common" >
> <typedef file="../build-common/buildCommon.xml"uri="common"/>
>
> Now all the macrodefs in buildCommon.xml has to be accessed as follows
>
> <c:theirmacro ...
>
> Any macrodef you define in your build.xml can be accessed without using the namespace syntax.
>
>
> ________________________________
> From: Cyril Sagan <cy...@gmail.com>
> To: Ant Users List <us...@ant.apache.org>
> Sent: Thursday, September 26, 2013 3:15 PM
> Subject: "scoping" for macro definitions?
>
>
> Is there a way to override a macro defined from a library I cannot
> control, my goal is to provide a local implementation, but not have to
> change all the callers.
>
> I'm stuck on Ant 1.7.0, and cannot update.
>
> How could I "fake out" a scoping mechanism to accomplish something like:
> <super.macroImplementation/> or <project[@name].macroImplemenation/>
>
> I tried using <presetdef/> to "override" the macro, but I can't figure
> out how to invoke the original macro of the same name. I could
> redefine the macro from the library in my local ant script, but I
> don't want to open a possibility that my local implementation could
> get out of sync with the one from the provided library.
>
> Another way to express what I need is the macro equivalent of target
> overriding, which is accomplished with the code snip below, but I need
> it for <macrodef/>!
>
> common.xml:
> <project name="common_library">
> <target name="stuff">
> <!-- run stuff from common library -->
> </target>
> </project>
>
> build.xml:
> <project name="myBuild">
> <import file="common.xml" />
> <target name="stuff" depends="mystuff_first, common_library.stuff"
> />
>
> <!-- henceforth target="stuff" is *my* implementation -->
> </project>
>
>
> But what if its a macro (or scriptdef)? In principle here's what I was
> hoping could
> work, but it doesn't, so that's why I'm asking:
>
> common.xml:
> <project name="common_library">
> <macrodef name="routine">
> <attribute name="arg1" />
> <attribute name="arg2" />
> <sequential>
> <!-- macro definition from common library -->
> </sequential>
> </target>
> </project>
>
> build.xml:
> <project name="myBuild">
> <import file="common.xml" />
> <presetdef name="routine">
> <local_routine/>
> </presetdef>
>
> <macrodef name="local_routine">
> <attribute name="arg1" />
> <attribute name="arg2" />
> <sequential>
> <!-- add some logic here... -->
> <common_library.routine arg1="@{arg1} arg2="@{arg2}" />
> </sequential>
> </macrodef>
>
> <!-- henceforth <routine/> is *my* implementation -->
> </project>
>
> Any ideas would be much appreciated. Thanks.
>
> --Cyril
Re: "scoping" for macro definitions?
Posted by Vimil Saju <vi...@yahoo.com>.
I am not sure if this feature is available in ant 1.7 but can't you use namespaces to scope the macrodefs like follows
<project name="testBuild" default="all" basedir="." xmlns:c="common" >
<typedef file="../build-common/buildCommon.xml"uri="common"/>
Now all the macrodefs in buildCommon.xml has to be accessed as follows
<c:theirmacro ...
Any macrodef you define in your build.xml can be accessed without using the namespace syntax.
________________________________
From: Cyril Sagan <cy...@gmail.com>
To: Ant Users List <us...@ant.apache.org>
Sent: Thursday, September 26, 2013 3:15 PM
Subject: "scoping" for macro definitions?
Is there a way to override a macro defined from a library I cannot
control, my goal is to provide a local implementation, but not have to
change all the callers.
I'm stuck on Ant 1.7.0, and cannot update.
How could I "fake out" a scoping mechanism to accomplish something like:
<super.macroImplementation/> or <project[@name].macroImplemenation/>
I tried using <presetdef/> to "override" the macro, but I can't figure
out how to invoke the original macro of the same name. I could
redefine the macro from the library in my local ant script, but I
don't want to open a possibility that my local implementation could
get out of sync with the one from the provided library.
Another way to express what I need is the macro equivalent of target
overriding, which is accomplished with the code snip below, but I need
it for <macrodef/>!
common.xml:
<project name="common_library">
<target name="stuff">
<!-- run stuff from common library -->
</target>
</project>
build.xml:
<project name="myBuild">
<import file="common.xml" />
<target name="stuff" depends="mystuff_first, common_library.stuff"
/>
<!-- henceforth target="stuff" is *my* implementation -->
</project>
But what if its a macro (or scriptdef)? In principle here's what I was
hoping could
work, but it doesn't, so that's why I'm asking:
common.xml:
<project name="common_library">
<macrodef name="routine">
<attribute name="arg1" />
<attribute name="arg2" />
<sequential>
<!-- macro definition from common library -->
</sequential>
</target>
</project>
build.xml:
<project name="myBuild">
<import file="common.xml" />
<presetdef name="routine">
<local_routine/>
</presetdef>
<macrodef name="local_routine">
<attribute name="arg1" />
<attribute name="arg2" />
<sequential>
<!-- add some logic here... -->
<common_library.routine arg1="@{arg1} arg2="@{arg2}" />
</sequential>
</macrodef>
<!-- henceforth <routine/> is *my* implementation -->
</project>
Any ideas would be much appreciated. Thanks.
--Cyril