分发要包含在构建中的公共ant文件有哪些好方法?

时间:2011-02-26 02:47:24

标签: ant build-process

我在一个小组工作,我们生产许多小应用程序,并使用ANT进行构建过程。

我们希望以常用的方式安装一些常用的指令。目前,我们需要将映射驱动器映射到公共位置,然后使用

<import file="${env.MAPPED_DRIVE}/common_directive.xml">

必须有更好的方法来分发公共ant文件以包含在许多项目中而无需映射驱动器。你还有其他建议吗?

导入是一个“顶级”指令,这意味着它不能在目标内部工作。因此,我不能简单地创建一个下载文件的目标,然后导入它。

3 个答案:

答案 0 :(得分:4)

如果您正在使用ANT 1.8+, you could specify a URL并在网站上托管公共构建片段。

  

从Ant 1.8.0开始,任务也可以   从网址导入资源或   classpath资源(即URL,   真)。如果你需要知道是否   当前构建文件的源代码   是您可以咨询的文件或URL   属性ant.file.type.projectname   (使用与上面相同的例子   ant.file.type.builddocs)其中之一   具有值“file”或“url”。

答案 1 :(得分:2)

我已经找到了一个解决方案,在一个目录中创建一个包含我们可重用构建脚本的jar文件,例如com / example / ant / sharedbuild,它可以在Ant 1.8中导入:

<project>
    <import>
        <javaresource name="com/example/ant/sharedbuild/java.xml">
            <classpath location="../../../../target/ant-shared-build.jar" />
        </javaresource>
    </import>
</project>

在我的例子中,这定义了项目的所有“公共”目标,以进行基于java的构建。

语法有点冗长,特别是当我添加越来越多的包含文件时(例如,添加创建OSGi jar的能力)。通过将包含macrodef和scriptdef组合的antlib.xml添加到jar文件(与共享构建脚本位于同一目录中),构建文件现在看起来像这样(现在还创建了一个OSGi jar包):

<project xmlns:build="antlib:com.example.ant.sharedbuild">
    <taskdef uri="antlib:com.example.ant.sharedbuild"
             classpath="../../../../target/ant-shared-build.jar" />
    <build:build using="java, jar, bundle" />
</project>

不幸的是,我不能在macrodef或scriptdef中共享代码,但实际上并不难:用一个小的javascript来解析using属性并循环遍历每个,从中派生一个文件名,然后导入。 / p>

我在我的硬盘上的固定位置(相对于我的项目)引用了jar文件。我想我们可以做得更好。理想情况下,我想从中心位置获取(版本化!)jar文件。由于我们已经在使用Ivy(使用HTTP存储库),我们可以在那里发布jar文件(再次使用版本)并直接从那里获取它:

<project xmlns:build="antlib:com.example.ant.sharedbuild">
    <property name="ant.shared.build.jar.file"
              location="${user.home}/ant/ant-shared-build-1.5.3.jar" />
    <get src="http://repo.example.com/.../ant-shared-build-1.5.3.jar"
         dest="${ant.shared.build.jar.file}"
         skipexisting="true" />
    <taskdef uri="antlib:com.example.ant.sharedbuild"
             classpath="${ant.shared.build.jar.file}" />
    <build:build using="java, jar, bundle" />
</project>

这有一些问题:

  1. 它再次变得冗长。
  2. 每个build.xml都会重复详细程度。
  3. 有很多重复的样板,特别是版本号。
  4. 为了缓解这些问题,在包含build.xml的每个目录中,我还有一个bootstrap.xml(名称并不重要)。然后每个build.xml都包含以下文件:

    <project xmlns:build="antlib:com.example.ant.sharedbuild">
        <include file="bootstrap.xml" />
        <build:build using="java, jar, bundle" />
    </project>
    

    每个bootstrap.xml至少包含它的父级bootstrap.xml:

    <project>
        <include file="../bootstrap.xml" />
    </project>
    

    顶级bootstrap.xml(根),然后执行获取jar文件和创建自定义任务的工作,如上所述:

    <project>
        <property name="ant.shared.build.version"
                  value="1.5.3" />
        <property name="ant.shared.build.jar.filename"
                  value="ant-shared-build-${ant.shared.build.version}.jar" />
        <property name="ant.shared.build.jar.file"
                  location="${user.home}/ant/${ant.shared.build.jar.filename}" />
        <get src="http://repo.example.com/.../${ant.shared.build.jar.filename}"
             dest="${ant.shared.build.jar.file}"
             skipexisting="true" />
        <taskdef uri="antlib:com.example.ant.sharedbuild"
                 classpath="${ant.shared.build.jar.file}" />
    </project>
    

    虽然与问题没有直接关系,但我实际上是将macrodef和scriptdef重新编写为自定义ant任务,因为我希望能够支持如下语法:

    <project xmlns:build="antlib:com.example.ant.sharedbuild">
        <include file="bootstrap.xml" />
        <build:build>
            <using>
                <java />
                <bundle>
                    <manifest>
                        Import-Package: *,org.joda.time;version="[1.6.0,1.6.0]"
                        Bundle-Activator: com.example.time.impl.Activator
                    </manifest>
                </bundle>
            </using>
        </build:build>
    </project>
    

    我应该指出,只是创建一个可再发行的构建并不意味着它会有用。您仍然需要投入时间和精力来创建符合类似特征的设计的内聚,模块化,一致的实现。这一点更为重要,因为您需要跨项目,跨团队,跨组织边界等共享脚本。

    总之,通过创建一个带有版本号的jar文件,可以独立于特定文件位置或SCM工具进行分发,我们可以获得真正的共享但可重现的构建。

答案 2 :(得分:1)

Dominic Mitchell关于URL引用的评论如果你想要可重复的构建是一个坏主意让我思考......

如果您使用SVN进行版本控制,另一个需要考虑的解决方案是创建一个指向common_directive.xml的{​​{3}}。

然后,只需使用ANT导入文件引用的相对路径。

  

有时构建一个有用的东西   工作副本由一个   不同结账的数量。   例如,您可能想要不同   子目录来自不同的   存储库中的位置或者可能   来自不同的存储库   共。你当然可以设置   通过手工使用svn checkout来创建嵌套类的这种场景   你正在尝试的工作副本结构   实现。但如果这个布局是   对于每个使用你的人都很重要   存储库,每个其他用户都需要   执行相同的结帐   你做过的操作。

     

幸运的是,Subversion提供了   支持外部定义。 <强>一种   外部定义是一个映射   URL的本地目录 - 理想情况下   版本化的特定版本   目录。在Subversion中,您声明   使用的组中的外部定义   svn:externals属性。您可以   使用创建或修改此属性   svn propset或svn propedit(见   名为“SVN Externals Definition”的部分。它可以在任何设置   版本化目录及其值   描述了外部存储库   位置和客户端目录   那个位置应该是哪个   检查出来。

     

svn:externals的便利性   属性是一旦它被设置在一个   版本化的目录,每个人   检查出一份工作副本   目录也得到了好处   外部定义。换句话说,   一旦有人做出努力   定义嵌套的工作副本   结构,没有人必须   麻烦 - Subversion将在检查后   原出的工作副本,   自动也检查出来   外部工作副本。