使用Ant 1.8扩展点支持父构建的习惯用法

时间:2011-02-14 18:56:22

标签: ant

请注意,以下示例将从我们非常复杂的构建结构中大大简化。

假设我有一个正在充分利用Ant 1.8扩展点的构建,这样我就可以定义一组共同的目标:

<?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>

后面的每个阶段都依赖于早期阶段,创建一系列明确定义的步骤,构建的其他部分可以做出贡献;例如,编译步骤可以定义为:

<?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>

虽然测试可能是:

<?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>

等等。我可以通过各种方式将它们组合在一起,为了便于讨论,我们假设它们位于一个名为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>

一个项目,称之为child1,可以使用它:

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

虽然对于child1(聪明地)称为child2的对等体是相同的:

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

所以,我已经实现了一个值得称赞的目标,即创建可以在多个项目中拆分的可重用构建。更好的是,每个构建都可以通过添加添加到明确定义的扩展点的目标来定制,在需要时使事情变得非常灵活。

但是,我无法找到创建分层父/子构建的最佳方法,这样我就有了一个目录结构:

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

这样我就可以在顶层构建中调用安装目标,让它在每个子代中执行安装目标。

恕我直言,理想情况下我会通过让父版本导入公共目标并将目标绑定到每个公共目标来实现这一点,如下所示:

<?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>

然而,这对我来说不起作用,因为我们最终首先在层次结构中进行广泛的下降而不是深度优先:如果我们部署在层次结构的顶层,我们首先在每个项目中进行编译,然后我们做测试,然后我们做包,然后我们做部署。我需要它来完成在child1中部署的所有步骤,然后在child2等中执行所有步骤。

忘记在父版本中使用扩展点并直接定义每个目标是有用的,如下所示:

<?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>

但是,现在我的父版本没有扩展点机制,可以在不覆盖目标的情况下轻松增强它们。

我是在思考问题吗? Ant社区是否提出了成语,模式,使用指南,说明或任何可以帮助我解决这一难题的方法?

1 个答案:

答案 0 :(得分:0)

  

然而,这对我来说不起作用,因为我们最终首先在层次结构中进行广泛的下降而不是深度优先:如果我们部署在层次结构的顶层,我们首先在每个项目中进行编译,然后我们做测试,然后我们做包,然后我们做部署。我需要它来完成在child1中部署的所有步骤,然后在child2等中执行所有步骤。

真的吗? 如果从root用户调用'ant parent:deploy',那么在对child2项目调用它之前,它是否首先不对child1项目进行完全部署?