嵌套子资源属性覆盖行为的解决方法(自1.8.0开始)

时间:2012-02-18 00:25:49

标签: ant

我正在以下列方式使用apache ant:

我有项目P1,P2,P3。其中一些项目有模块,比方说P2有M1,M2等。 所有项目都有自己的ant构建脚本,并且所有项目都必须实现一组预定义目标(build,dist等),脚本期望在调用时定义一些属性。让我们说(build.dir.base)

模块遵循类似的结构,因此每个模块都有自己的构建文件来实现预定义的目标集,并期望设置一些属性。 (比如build.dir.base - 与项目相同)

我还有一个构建所有项目(或子集)的全局ant脚本

在代码中看起来像:

积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

然而,由于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

这解释为Properties defined on the command line cannot be overridden by nested elements. Since Ant 1.8.0. the same is true for nested structures of tasks: if a build file A invokes B via an task setting a property with a nested element and B contains an tasks invoking C, C will see the value set in A, even if B used a nested element as well.

如果某些父母也定义了该属性,则无法覆盖subant的属性。这很严重,因为构建应该知道父级用于某些无关原因的属性。

这种不兼容的行为更改是否存在解决方法?因为,我的构建系统在很大程度上依赖于<subant inheritAll="false" inheritRefs="false">将执行exec而不污染子构建的事实。

4 个答案:

答案 0 :(得分:1)

不是一个完整的答案,但我发现你可以通过执行以下操作来阻止子任务继承特定属性:

<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>

答案 1 :(得分:1)

https://issues.apache.org/bugzilla/show_bug.cgi?id=49891似乎也与这个问题有关。

在尝试了许多不同的东西(包括过滤掉不需要的属性然后重置它的技术)后,我得出结论,在子任务中覆盖命令行属性是不可能的。

答案 2 :(得分:0)

这不是不可能!!您可以使用scriptdef覆盖属性 self.getProject()。setInheritedProperty(键,值)。看看API

答案 3 :(得分:0)