2011-02-26 47 views
6

我在一个小组中工作,我们生产许多小应用程序,并使用ANT来构建流程。什么是一些很好的方式来分发一个通用的ant文件以包含在构建中?

我们希望有一些我们常用的常用指令。目前,我们需要一个映射驱动器到一个共同的位置,并使用

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

必须有一个更好的办法来分配一个共同的Ant文件在很多项目中,包括无需映射驱动器。你有什么其他的建议?

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

回答

4

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

由于蚂蚁1.8.0任务也可以从网址或 的classpath资源 进口资源(这是网址, 真的)。如果您需要了解当前构建文件的来源是否 已经 是一个文件或URL你可以咨询 属性ant.file.type.projectname (使用相同的例子如上 ant.file.type.builddocs)其中 的值为“file”或“url”。

+0

非常感谢!我正在寻找错误的任务。难怪我找不到它。一些例子的链接也会有很大的帮助:如果你有一些好的,你可以随意使用。 – nrobey 2011-02-26 17:30:56

+4

如果您想要可重复构建,这是一个糟糕的主意。 – 2011-02-27 18:29:09

+0

@Dominic Mitchell - 好点。如果common_directive.xml不是静态的,最好是更好地管理该依赖关系。 – 2011-02-27 22:13:47

1

Dominic Mitchell是关于URL引用是一个糟糕的主意,如果你想重复的评论建立让我想...

另一种解决方案来考虑,如果你正在使用SVN版本控制,是创建一个指向common_directive.xmlSVN Externals Definition

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

有时是构造是开出了 数量不同检出的 工作副本非常有用。对于 的示例,您可能希望不同的 子目录来自不同的存储库中的 位置或可能来自不同存储库 的 。你当然可以通过手动使用svn checkout来创建 这种嵌套的 工作副本结构,您尝试使用 来实现。但是,如果此布局对使用您的 存储库的所有人都很重要,则每个其他用户都需要 才能执行您执行的相同结帐操作 。

幸运的是,Subversion提供了 支持外部定义。 An 外部定义是一个 本地目录到版本 目录的URL(理想情况下为 特定版本)的映射。在Subversion中,您使用 属性svn:externals属性声明 组中的外部定义。您可以使用 svn propset或svn propedit创建或修改此属性(请参阅 部分,名称为“Manipulating Properties”)。它可以在任何 版本化的目录中设置,其值 描述位置应该是 检出的位置和客户端目录 的外部存储库 。

svn:externals 属性的方便之处在于,一旦它被设置在 版本的目录,大家谁 检查出与 目录的工作拷贝,同样得到 外部定义的好处。换句话说, 一旦一个人做出的努力,以 定义嵌套的工作副本 结构,没有其他人有 麻烦,Subversion会,检查 了原先的工作拷贝后, 也自动检查出 外部工作副本。

+0

我爱你的建议,并有我自己的建议。不幸的是,由于过去svn:外部滥用,这个部门被这种方法“烧毁”,并且对此非常厌恶。不过,我会再试一次,因为你提出了这个问题。谢谢! – nrobey 2011-03-06 02:03:04

+1

@nrobey - 如果你的团队关心构建的可重复性和可靠性,看起来好像SVN外部将比使用映射驱动器更好。 externals属性受版本控制,如果您指向常见构建路径的SVN位置,则该内容也受版本控制。您可以指向常见构建回购的特定标记。 – 2011-03-06 02:31:39

+1

如果你关心可重复构建,那么使用svn:external通常是不好的。更经常的是,不是svn:external没有修订(AKA unpinned),这意味着你不知道什么版本被用于任何特定的构建。您可以制定一项政策,要求指定修订版,但这很难执行,否则难以维护。 – 2011-03-07 06:13:36

2

我已经计算出创建包含在目录中我们可重复使用的构建脚本一个jar文件的解决方案,比如COM /例子/ ANT/sharedbuild,它可以在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解析使用属性和循环每个,从中获取文件名,并导入。

我在硬盘上的固定位置(相对于我的项目)引用jar文件。我认为我们可以做得更好。理想情况下,我想从中央位置获取(版本化!)jar文件。既然我们已经使用艾维(与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. 有很多重复的样板,特别是版本号。

为了缓解这些问题,在每个包含build.xml的目录中,我还有一个bootstrap.xml(名称并不重要)。每个版本。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工具,我们可以获得真正的共享但可重复的构建。

+0

时间,冗长,乐于助人+1。我希望更多的人像这样回答!谢谢! – nrobey 2011-03-06 01:31:51

+0

你有没有特别的原因使用'get'而不是'ivy:retrieve'? – 2011-03-07 06:16:03

+0

@Tom:共享构建是引导常春藤的方法,因此试图用常青藤来获取常春藤的东西将会在循环逻辑中完全扭曲你的大脑。 – 2011-03-07 20:38:53

相关问题