我在一个小组工作,我们生产许多小应用程序,并使用ANT进行构建过程。
我们希望以常用的方式安装一些常用的指令。目前,我们需要将映射驱动器映射到公共位置,然后使用
<import file="${env.MAPPED_DRIVE}/common_directive.xml">
必须有更好的方法来分发公共ant文件以包含在许多项目中而无需映射驱动器。你还有其他建议吗?
导入是一个“顶级”指令,这意味着它不能在目标内部工作。因此,我不能简单地创建一个下载文件的目标,然后导入它。
答案 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>
这有一些问题:
为了缓解这些问题,在包含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将在检查后 原出的工作副本, 自动也检查出来 外部工作副本。