开发者

Idioms for supporing parent build using Ant 1.8 extension points

Please bear in mind the following examples are greatly simplified from our very complex build structure.

Suppose I have a build that's taking full advantage of Ant 1.8 extension-points, such that I have a common set of targets defined like:

<?xml version="1.0" encoding="utf-8"?>
<project name="common-targets">

    <extension-point name="compile" />
    <extension-point name="test" depends="compile" />
    <extension-point name="package" depends="test" />
    <extension-point name="deploy" depends="package" />

</project>

Each of the later phases depends on the earlier phase, creating a chain of well-defined steps other parts of the build can contribute to; for example, the compile step might be defined as:

<?xml version="1.0" encoding="utf-8"?>
<project name="compile">

    <import file="common-targets.xml" />

    <target name="compile:compile" extensionOf="compile">
        <echo message="Compiling..." />
    </target>

</project>

while the test might be:

<?xml version="1.0" encoding="utf-8"?>
<project name="test">

    <import file="common-targets.xml" />

    <target name="test:test" extensionOf="test">
        <echo message="Testing..." />
    </target>

</project>

and so on. I can combine these in various ways, and for the sake of discussion let's say they're in a single build file called default-lifecycle.xml:

<?xml version="1.0" encoding="utf-8"?>
<project name="default-lifecycle">

    <import file="compile.xml开发者_运维知识库" />
    <import file="test.xml" />
    <import file="package.xml" />
    <import file="deploy.xml" />

</project>

A project, call it child1, can use this like:

<?xml version="1.0" encoding="utf-8"?>
<project name="child1">
    <import file="../scripts/default-lifecycle.xml" />
</project>

while a peer to child1 (cleverly) called child2 would be the same:

<?xml version="1.0" encoding="utf-8"?>
<project name="child2">
    <import file="../scripts/default-lifecycle.xml" />
</project>

So, I've achieved a laudable goal of creating reusable builds that can be split across multiple projects. Even better, each build can be customized by adding targets that add to the well-defined extension points, making things very flexible when we need to.

However, I'm having trouble figuring out the best way to create a hierarchical parent/child build, such that I have a directory structure like:

.-+
  |
  +-build.xml
  +-child1
     |
     +-build.xml
  +-child2
     |
     +-build.xml
  +-scripts

so that I can call, say, the install target within the top-level build and have it do the install target in each of the children.

IMHO, ideally I'd do this by having a parent build import the common-targets and tying a target to each of the common targets, like this:

<?xml version="1.0" encoding="utf-8"?>
<project name="parent">

    <import file="common-targets.xml" />

    <target name="parent:compile" depends="parent:init-build-path" extensionOf="compile">
        <subant target="compile" buildpathref="parent..build-path" />
    </target>

    <target name="parent:test" depends="parent:init-build-path" extensionOf="test">
        <subant target="test" buildpathref="parent..build-path" />
    </target>

    <target name="parent:package" depends="parent:init-build-path" extensionOf="package">
        <subant target="package" buildpathref="parent..build-path" />
    </target>

    <target name="parent:deploy" depends="parent:init-build-path" extensionOf="deploy">
        <subant target="deploy" buildpathref="parent..build-path" />
    </target>

    <target name="parent:init-build-path">
        <path id="parent..build-path">
            <fileset dir="." includes="**/build.xml" excludes="build.xml" />
        </path>
        <echo message="Build order is ${toString:parent..build-path}" />
    </target>

</project>

However, this doesn't work for me because we end up doing a breadth first descent of the hierarchy instead of a depth first: if we do deploy on the top level of the hierarchy, we first do compile in each project, then we do test, then we do package, then we do deploy. I need it to do all the steps to deploy in child1, then all the steps in child2, etc.

What would work is by forgetting using extension points in the parent build and just define each target directly, like this:

<?xml version="1.0" encoding="utf-8"?>
<project name="parent">

    <target name="compile" depends="parent:init-build-path">
        <subant target="compile" buildpathref="parent..build-path" />
    </target>

    <target name="test" depends="parent:init-build-path">
        <subant target="test" buildpathref="parent..build-path" />
    </target>

    <target name="package" depends="parent:init-build-path">
        <subant target="package" buildpathref="parent..build-path" />
    </target>

    <target name="deploy" depends="parent:init-build-path">
        <subant target="deploy" buildpathref="parent..build-path" />
    </target>

    <target name="parent:init-build-path">
        <path id="parent..build-path">
            <fileset dir="." includes="**/build.xml" excludes="build.xml" />
        </path>
        <echo message="Build order is ${toString:parent..build-path}" />
    </target>

</project>

However, now my parent builds don't have the extension-point mechanism where they can be easily enhanced without overriding targets.

Am I over thinking things? Has the Ant community come up with an idiom, pattern, usage guideline, instructions, or anything to help me resolve this dilemma?


However, this doesn't work for me because we end up doing a breadth first descent of the hierarchy instead of a depth first: if we do deploy on the top level of the hierarchy, we first do compile in each project, then we do test, then we do package, then we do deploy. I need it to do all the steps to deploy in child1, then all the steps in child2, etc.

Really ? If you invoke 'ant parent:deploy' from the root, does it NOT do the complete deploy for the child1 project first, before invoking it on the child2 ?

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜