连接Ant构建文件

5
我正在使用Ant构建客户端和服务器,涉及编程内容。在构建客户端之前,必须先构建服务器。我已经准备好了所有所需的库,除了服务器 ear 文件未打包到客户端中。
我创建了三个 Ant 文件 build.xmlbuild-client.xmlbuild-server.xml。(单击任何文件名可查看文件) 文件 build-client.xmlbuild-server.xml 包含在 build.xml 中,以便可以从其中运行目标。
我遇到的问题是basedir变量在每个构建文件中都会发生改变。因此,如果我从build.xml运行build-client.xml中的目标,则基于变量相对于build.xml

如何在Ant脚本中多次更改基于变量?

另外,看看这些构建文件,你是否认为有更好的方法来实现我正在尝试做的事情?现在我认为在最终捆绑的ear之前,我必须将客户端war和服务器ear放在同一个位置。不过,我的想法可能存在缺陷,因为这些脚本似乎过于复杂。

3个回答

5

关于<import>任务的Ant文档会提供如何实现这一点的信息。

解析导入文件中的文件

假设您的主构建文件名为importing.xml,导入了一个位于文件系统上任何位置的构建文件imported.xml,并且imported.xml从imported.properties中读取一组属性:

<!-- importing.xml -->
<project name="importing" basedir="." default="...">
  <import file="${path_to_imported}/imported.xml"/>
</project>

<!-- imported.xml -->
<project name="imported" basedir="." default="...">
  <property file="imported.properties"/>
</project>

然而,这个代码片段将会根据导入xml文件的basedir解析imported.properties文件,因为Ant忽略了导入xml文件的basedir。正确使用imported.properties文件的方法是:

<!-- imported.xml -->
<project name="imported" basedir="." default="...">
  <dirname property="imported.basedir" file="${ant.file.imported}"/>
  <property file="${imported.basedir}/imported.properties"/>
</project>

如上所述,${ant.file.imported} 存储了构建脚本的路径,该脚本定义了名为imported的项目(简称为存储在imported.xml中的路径),而 <dirname> 则获取其目录。这种技术还允许将imported.xml作为独立文件使用(而不是被导入到其他项目中)。
基本上,您无法真正使用变量${basedir}或属性basedir="./../GrahamsProjClient"在您的项目标签中,但您可以构建它:
<!-- build-client.xml -->
<project name="GPClient" default="dist" >

  <dirname property="client.root.dir" file="${ant.file.GPClient}"/>
  <property name="real.basedir" value="${client.root.dir}/../GrahamsProjClient"/>

  <!-- Then from then on, replace ${basedir} with ${real.basedir} -->
  ...
</project>

您可以对 build-server.xml 做同样的操作,唯一需要注意的是项目名称必须在 ${ant.file.[project name]} 文件属性中出现,用于 <dirname />

3
我的普通规则是在正常的构建过程中不使用 <ant><subant>,因为它会破坏依赖检查。我们有一个开发人员将 build.xml 拆分成七个单独的构建文件,由于在其他构建文件中不断调用 <ant> 任务来执行其他操作,他执行了同一目标多达14次。然后他想知道为什么构建需要这么长时间。将这七个构建文件缝合回一个单一的 build.xml 中,并使用 <target>depends 参数,将构建缩短到不到两分钟。

然而,在这种情况下,你实际上有两个独立的项目和一个 build.xml,你正在使用该文件来调用这两个独立的项目。在这种情况下,你最好使用 <ant><subant> 调用,而不是 <import>

  • 这些调用不会干扰 ${basedir}
  • 这些调用允许您指定要包含在这些单独文件中的属性和资源。(可能的答案是)。
  • 您不需要担心多个目标共享相同的名称。您客户端构建中的 compile 目标不会与服务器构建中的 _compile_ 目标重叠。

Subant 更强大,但实现起来更棘手。使用 Subant,您可以让它搜索 build.xml 文件。大多数情况下,使用 <ant> 更容易并且能够实现您想要的功能。


我真的建议使用Ivy来处理依赖问题。 Ivy不仅可以处理客户端中的服务器依赖关系,还可以处理所有第三方jar文件的依赖关系。不再在项目中存储jar文件。当您将jar文件存储在项目中时,您会失去有关其实际版本和历史记录的信息。您在项目中看到一个`commons-io.jar`,您不知道它是哪个版本,甚至不知道它是否是官方的`commons-io.jar`,或者是您的开发人员在某个时刻搞乱了它。
问题在于,实现Ivy需要一些工作。您需要使用像NexusArtifactoryArchiva这样的Ivy存储库管理器。(实际上,这些是Maven存储库管理器,但Ivy与它们非常好地配合。)
然后,您需要将ivy.jar导入您的项目,并让ivysettings.xml文件指向您的Maven Ivy存储库服务器。
如果您使用Subversion作为版本控制系统,您可以执行以下操作:
  • 创建一个包括ivy.jar和一个设置所有内容的XML文件的Ivy项目。您可以查看Github上的一个。XML文件名为ivy.tasks.xml
  • 然后在您的项目中,使用svn:externals导入此项目。
  • 在您的build.xml中,您需要完成两件事:
    • 在您的<project>实体中添加Ivy命名空间。
    • 使用<import>任务导入具有所有设置的Ivy XML文件。
优点是更改您的Ivy项目将自动更改与Ivy交互的所有项目。例如,如果您更改Ivy服务器的URL或需要重新定义Ivy缓存目录。
一旦完成这一步骤,您只需要创建一个ivy.xml文件来定义您的依赖项,并使用<ivy:cachepath><ivy:retrieve>来检索所需的第三方JAR包。这将包括您的客户端需要的服务器JAR包。

0

我注意到使用Ant时,我无法像想要的那样更改变量。

解决方案是为每个要执行的目标从命令行运行Ant,因此不是像这样执行命令行语句:

ant target1 target2

或者

<target name="target1">
   <antcall target="target2">
</target>

我不得不从命令行顺序地调用目标

ant target1 ant target2

所以我选择将这些ant调用放在一个Python脚本中,该脚本只需进行os.system("");调用,其中我的命令行语句将在引号内。Bash也可以做到这一点。

这是ant使用每个目标的正确变量的唯一方法,如果这些变量具有相同的名称。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接