我以以下方式使用apacheant:
我有项目P1、P2、P3。其中一些项目有模块,比如P2有M1、M2等。所有项目都有自己的ant构建脚本,并且所有项目都必须实现一组预定义的目标(build、dist等),这些脚本希望在调用时定义一些属性。比方说(build.dir.base)
模块遵循类似的结构,因此每个模块都有自己的构建文件,用于实现预定义的目标集,并期望设置一些属性。(比如build.dir.base-与项目相同)
我还有一个全局蚂蚁脚本,用于构建所有项目(或子集)
在代码中看起来像:
build-all.xml:
<project name="x">
<property name="build.dir.base" location="system.build.base" />
<target name="build">
<echo message="build.dir.base as defined for build-all.xml=${build.dir.base}" />
<subant antfile="build.xml" target="build" inheritAll="false" inheritRefs="false">
<dirset dir="${system.base}" includes="${project-list}" />
<property name="build.dir.base" location="${build.dir.base}" />
</subant>
</target>
</project>
build.xml(每个有模块的项目一个,如果项目没有模块,则没有subant
):
<project name="y">
<property name="build.dir" location="${basedir}/build" />
<target name="build">
<echo message="build.dir.base as defined for project=${build.dir.base}" />
<subant antfile="build.xml" target="build" inheritAll="false" inheritRefs="false">
<dirset dir="project.base" includes="${module-list}" />
<property name="build.dir.base" location="${build.dir.base}/${name}" />
</subant>
</target>
</project>
对于具有模块的项目:build.xml(用于模块):
<project name="z">
<property name="build.dir.base" location="build.dir.base" />
<target name="build">
<echo message="build.dir.base as defined for module=${build.dir.base}" />
</target>
</project>
这种结构允许独立构建项目,也可以独立构建模块,或者使用build-all.xml构建整个系统。此外,最终产品具有以下结构:
- ${system.build.base}/P1
- ${system.build.base}/P2/M1
- ${system.build.base}/P2/M2
etc
然而,由于ant>=1.8.0,这就不可能了。原因是build-all.xml中的<property name="build.dir.base" location="${basedir}/build" />
在build.xml中优先于<property name="build.dir.base" location="${build.dir.base}/${name}" />
(为项目构建)。因此,项目"子模块"的目的地是${system.build.base}/M1
,而不是${system.build.base}/P2/M1
这说明了在命令行上定义的属性不能被嵌套元素覆盖自蚂蚁1.8.0以来。任务的嵌套结构也是如此:如果构建文件a通过任务设置嵌套元素的属性来调用B,而B包含调用C的任务,则C将看到a中设置的值,即使B也使用了嵌套元素
如果某些父级也定义了subant
的属性,则无法覆盖该属性。这是严重的,因为构建应该知道父级出于某种无关原因使用的属性。
对于这种不兼容的行为更改,是否有解决方法?由于,我的构建系统在很大程度上依赖于这样一个事实,即<subant inheritAll="false" inheritRefs="false">
将在不污染子构建的情况下执行exec。
https://issues.apache.org/bugzilla/show_bug.cgi?id=49891似乎也与这个问题有关。
在尝试了许多不同的东西(包括过滤掉不需要的属性然后重置它的技术)之后,我得出结论,在子ant任务中覆盖命令行属性是不可能的。
不是一个完整的答案,但我发现您可以通过执行以下操作来防止子任务继承特定属性:
<resources id='aoeu'>
<intersect>
<propertyset>
<propertyref builtin="commandline"/>
</propertyset>
<propertyset negate="true">
<propertyref name="property.not.to.be.inherited"/>
</propertyset>
</intersect>
</resources>
<groovy>
ant.propertyset(id:"snth") {
project.references["aoeu"].each {
propertyref(name:"${it.name}")
}
}
</groovy>
<subant buildpathref="buildpath">
<propertyset>
<propertyset refid="snth"/>
</propertyset>
<target name="zvwm"/>
</subant>
这并非不可能!!可以使用scriptdef覆盖属性self.getProject().setInheritedProperty(键,值)。查看API
您可以使用antcontrib-var任务。http://ant-contrib.sourceforge.net/tasks/tasks/variable_task.html