我有一个客户端和一个我用Ant构建的服务器。客户端在构建之前依赖于首先构建的服务器。我有所有必需的库,除了客户端中捆绑的服务器ear文件。
我创建了3个蚂蚁文件build.xml
,build-client.xml
和build-server.xml
。 (单击任何文件名以查看它们)文件build-client.xml
和build-server.xml
包含在build.xml
中,以便它可以从中运行目标。
我遇到的问题是basedir
变量从构建文件更改为构建文件。因此,如果我从build-client.xml
build.xml
中运行目标,则basedir变量相对于build.xml
。
如何在Ant脚本中多次更改basedir变量?
另外,看看这些构建文件,您是否看到了更好的方法来做我想做的事情?现在,我想我必须在同一个位置同时拥有客户端战争和服务器耳朵,才能制作最终的捆绑耳朵。我对此的想法可能有缺陷,因为这些脚本似乎不必要地复杂。
答案 0 :(得分:5)
<import>
<!-- 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>
任务为您提供有关如何完成此任务的信息。
根据导入的文件解析文件
假设名为imports.xml的主构建文件导入位于文件系统任何位置的构建文件imported.xml,并且imported.xml从imported.properties中读取一组属性:
basedir
但是,此代码段将针对imports.xml的basedir
解析imported.properties,因为Ant会忽略imported.xml的<!-- imported.xml -->
<project name="imported" basedir="." default="...">
<dirname property="imported.basedir" file="${ant.file.imported}"/>
<property file="${imported.basedir}/imported.properties"/>
</project>
。使用imported.properties的正确方法是:
${ant.file.imported}
如上所述,<dirname>
存储构建脚本的路径,该路径定义了名为imported的项目(简而言之,它存储了imported.xml的路径),${basedir}
获取了其目录。此技术还允许将imported.xml用作独立文件(不在其他项目中导入)。
基本上,您无法真正使用项目代码中的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>
属性,而是可以构建它:
${ant.file.[project name]}
您可以对build-server.xml执行相同操作,唯一需要注意的是项目名称包含在<dirname />
的{{1}}文件属性中。
答案 1 :(得分:3)
我的正常规则是在正常构建过程中不使用<ant>
或<subant>
,因为它会破坏依赖性检查。我们让开发人员将build.xml分解为七个单独的构建文件,并且由于<ant>
任务不断调用其他构建文件中的内容,他执行相同的目标最多14次。然后,他想知道为什么他的构建需要这么长时间。将七个构建文件拼接成一个build.xml
并使用depends
参数<target>
将构建时间缩短到不到两分钟。
但是,在这种情况下,你所拥有的实际上是两个独立的项目和一个build.xml
,你用它来调用这两个独立的项目。在这种情况下,您最好使用<ant>
和<subant>
来电,而不是<import>
。
${basedir}
。_compile_
目标重叠。 Subant功能更强大,但实施起来比较棘手。使用Subant,您可以让它搜索build.xml文件。大部分时间使用<ant>
都比较容易,也可以做到你想要的。
我真正推荐的是使用Ivy来处理依赖性问题。 Ivy不仅可以处理客户端中的服务器依赖项,还可以处理所有第三方jar依赖项。不再在项目中存储jarfiles。在项目中存储jar文件时,会丢失有关其实际版本及其历史记录的信息。您在项目中看到commons-io.jar
,并且您不知道它是什么版本,或者即使它是官方的`commons-io.jar,或者您的某个开发人员将其视为某些点。
问题是Ivy需要做一些工作才能实现。您需要使用Ivy存储库管理器,例如Nexus,Artifactory或Archiva。 (实际上,这些是Maven存储库管理器,但Ivy与它们的工作非常顺利。)
然后,您需要将ivy.jar
导入项目并获取ivysettings.xml
文件以指向 Maven Ivy存储库服务器。
如果您使用Subversion作为版本控制系统,则可以执行以下操作:
ivy.tasks.xml
。svn:externals
导入此项目。 build.xml
中,您需要做两件事:
<project>
实体中添加Ivy名称空间。<import>
任务导入包含所有设置的Ivy XML文件。优点是更改您的常春藤项目将自动更改与Ivy交互的所有项目。例如,如果您更改Ivy服务器的URL,或者您需要重新定义Ivy缓存目录。
如果您这样做,只需创建一个定义依赖关系的ivy.xml
文件,然后使用<ivy:cachepath>
和<ivy:retrieve>
检索您需要的第三方jar。这将包括您的客户需要的服务器jar。
答案 2 :(得分:0)
我注意到蚂蚁的一件事是我无法像我想要的那样改变变量
解决方案是让命令行中的ant运行您想要执行的每个目标,而不是执行命令行语句,例如
ant target1 target2
或
<target name="target1">
<antcall target="target2">
</target>
我不得不从命令行顺序执行目标调用
ant target1
ant target2
所以我选择将这些ant调用放在python脚本中,这只是调用os.system("");
,我的命令行语句就在引号内。 bash也可以做到这一点
如果这些变量具有相同的名称,这是蚂蚁为每个目标使用适当变量的唯一方法