【问题标题】:Ant manifestclasspath: property already setAnt manifestclasspath:属性已设置
【发布时间】:2011-06-28 10:45:15
【问题描述】:

我想使用manifestclasspath Ant 任务。我有一个非常大的 build.xml 文件,其中包含几个导入的其他构建文件,当我运行它时,我得到了这个:

build.xml:1289: The following error occurred while executing this line:
build.xml:165: Property 'some.property' already set!

我确定该属性仅在manifestclasspath 任务中定义。这是我的代码:

<manifestclasspath property="some.property" jarfile="some.jar">
    <classpath refid="some.classpath"/>
</manifestclasspath>

此代码位于&lt;project&gt; 内。

我做错了什么?有没有办法添加 condition 之类的东西来设置属性,前提是它尚未设置?如果有其他方法,我不想使用自定义 Ant 任务,例如 Ant Contrib 的 if

【问题讨论】:

  • 我最近遇到了同样的问题。您的构建脚本是否像我们的一样使用antcall?如果是这样,那么这就是您的问题的根源(因为 antcall 可能导致已经运行的目标再次运行)。

标签: ant classpath manifest


【解决方案1】:

Antcall 打开一个新的项目范围,但默认情况下,当前项目的所有属性都将在新项目中可用。另外,如果您使用了 =

之类的东西
<antcall target="whatever">
  <param name="some.property" value="somevalue"/>
</antcall>

在调用项目中 ${some.property} 也已经设置并且不会被覆盖,因为一旦设置属性在 ant 设计中是不可变的。 或者,您可以将 inheritAll 属性设置为 false,并且只有“用户”属性(在命令行中使用 -Dproperty=value 传递的那些)将传递给新项目。 所以,当 ${some.property} 不是用户属性时,使用 inheritAll="false" 就完成了。

顺便说一句。通过depends="..."属性在目标之间使用依赖比使用antcall更好,因为它打开了一个新的项目范围,并且在新项目中设置的属性不会返回到调用目标,因为它存在于另一个项目范围..

跟一个sn-p,注意区别,先不带inheritAll属性

<project default="foo">
 <target name="foo">
  <property name="name" value="value1" />
  <antcall target="bar"/>
 </target>

 <target name="bar">
  <property name="name" value="value2" />
  <echo>$${name} = ${name}</echo>
 </target>
</project>

输出:

[echo] ${name} = value1

第二个inheritAll=false

 <project default="foo">
     <target name="foo">
      <property name="name" value="value1" />
      <antcall target="bar" inheritAll="false" />
     </target>

     <target name="bar">
      <property name="name" value="value2" />
      <echo>$${name} = ${name}</echo>
     </target>
    </project>

输出:

[echo] ${name} = value2

antcall 的一些经验法则,它很少使用是有充分理由的:
1. 它会打开一个新的项目范围(启动一个新的“ant -buildfile yourfile.xml yourtarget”)
因此它会使用更多内存,从而减慢您的构建速度
2. 被调用目标的依赖目标也会被调用!
3. 属性不会被传递回调用目标

在某些情况下,使用不同的参数调用相同的“独立”目标(一个没有它依赖的目标的目标)以进行重用可能没问题。通常,macrodef 或 scriptdef 用于此目的。因此,在使用 antcall 之前请三思而后行,这也会给您的脚本带来多余的复杂性,因为它与正常流程不符。

在评论中回答您的问题,使用依赖图而不是 antcall
您有一些目标,它包含所有条件并设置适当的属性,目标可以通过 if 和 unless 属性评估这些属性以控制进一步的流程

<project default="main">

 <target name="some.target">
  <echo>starting..</echo>
 </target>

 <!-- checking requirements.. -->
 <target name="this.target">
  <condition property="windowsbuild">
   <os family="windows"/>
  </condition>
  <condition property="windowsbuild">
   <os family="unix"/>
  </condition>
  <!-- ... -->
 </target>

 <!-- alternatively
  <target name="yet.another.target" depends="this.target" if="unixbuild">
 -->
 <target name="another.target" depends="this.target" unless="windowsbuild">
  <!-- your unixspecific stuff goes here .. -->
 </target>

 <!-- alternatively
  <target name="yet.another.target" depends="this.target" if="windowsbuild">
 -->
 <target name="yet.another.target" depends="this.target" unless="unixbuild">
  <!-- your windowspecific stuff goes here .. -->
 </target>

【讨论】:

  • 你会怎么写 没有antcall?
  • 感谢您的回答。 Windows/unix 并不是我在评论中的意思,但是你回答了我的第一个问题。现在我明白发生了什么,我的问题也解决了。非常感谢您的宝贵时间:-)
  • windows/unix 只是您在第一条评论中的第二个问题的示例;我认为您掌握了如何创建依赖流的逻辑。如果您需要更具体的答案,您必须提供更多详细信息或提出另一个问题。不客气:-)
猜你喜欢
  • 1970-01-01
  • 2012-08-15
  • 2014-02-04
  • 2015-01-11
  • 1970-01-01
  • 2020-01-08
  • 2012-10-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多