Search code examples
javaxmlant

How to properly use a target of an importing build file?


I am pretty new to ant and extended an existing build file a.xml:

I created an additional build file b.xml which is imported by a.xml. The target example defined in b.xml provides a new (optional) feature when building with ant, that requires the ${version} property. The ${version} property is created/provided by the target determine.version in a.xml.

To ensure the existence/access of ${version} in b.xml I've added the depends="determine.version" parameter to the target example in b.xml. Thereby, I've added an dependency to a non-resolvable target, when running b.xml solely (which is not intended).

The question:

I don't feel comfortable with this solution and want to ask whether there is a cleaner way to ensure the existence and access of ${version} in b.xml.

a.xml


<project name="a" basedir="." >
   ...
   <target name="determine.version">
      ...
   </target>

   ... 

   <import file="b.xml" as="b" />
</project>

b.xml

<project name="b" basedir="." >
   ...
   <target name="example" depends="determine.version">
      ...
      do s.th. with ${version}
      ...
   </target>

</project>

I am thankful for any advice, recommendation or comment to this!


Solution

  • If you wish to keep b.xml such that it will work when used directly / independently of a.xml, one solution would be to setup b.xml with its own determine.version target and override that target in a.xml.

    b.xml would need:

    <target name="determine.version">
      ... does nothing or whatever is needed to satisfy b's "example" target when a.xml not used
    </target>
    

    a.xml can then override determine.version and depend on the default implementation in b.xml so it is called in the correct position when evaluating b.xml's "example" target. The way to reference a dependency of imports is to specify {buildfile}.targetname - in this case b.determine.version - assuming that you want both a+b's determine.version to run:

    <target name="determine.version" depends="b.determine.version">
      ...
    </target>
    

    Alternatively

    The above setup is awkward in that the names used in a/b xml are linked. Instead you could try out extension-point in ant builds which makes names in a depend on b, but not both ways. It would need something like this:

    b.xml - B declares an extension point that referenced by "example":

    <extension-point name="setupversion" />
    <target name="example" depends="setupversion">
    

    a.xml - A declares a target (which does not need to be called determine.version) that will run before all targets that depend on "setupversion"

    <import file="b.xml" />
    <target name="determine.version" extensionOf="setupversion">