Ant 清单类路径:属性已设置

发布于 2024-11-18 00:01:16 字数 662 浏览 2 评论 0原文

我想使用 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>

此代码位于 内部。

我做错了什么?有没有办法添加类似 condition 的内容来设置属性(仅当属性尚未设置时)?如果有其他方法,我不想使用自定义 Ant 任务,例如 Ant Contrib 的 if

I want to use manifestclasspath Ant task. I have a very large build.xml file with a couple of imported other build files and when I run it I get this:

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

I am sure that this property is defined only in manifestclasspath task. Here is my code:

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

This code is located inside of <project>.

What am I doing wrong? Is there a way to add something like condition to set property only if it is not already set? I don't want to use custom Ant tasks such as Ant Contrib's if if there is other way around.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

枯叶蝶 2024-11-25 00:01:16

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

<antcall target="whatever">
  <param name="some.property" value="somevalue"/>
</antcall>

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

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

在代码片段之后,请注意差异,首先没有继承All属性

<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 和 except 属性来评估这些属性来控制进一步的流程

<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 opens a new project scope, but by default, all of the properties of the current project will be available in the new project. Also if you used something like =

<antcall target="whatever">
  <param name="some.property" value="somevalue"/>
</antcall>

in the calling project then ${some.property} is also already set and won't be overwritten, as properties once set are immutable in ant by design.
Alternatively, you may set the inheritAll attribute to false and only "user" properties (those passed on the command-line with -Dproperty=value) will be passed to the new project.
So, when ${some.property} ain't no user property, then use inheritAll="false" and you're done.

btw. it's better to use a dependency between targets via depends="..." attribute than to use antcall, because it opens a new project scope and properties set in the new project won't get back to the calling target because it lives in another project scope..

Following a snippet, note the difference, first without inheritAll attribute

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

output :

[echo] ${name} = value1

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

output :

[echo] ${name} = value2

some rules of thumb for antcall, it's rarely used for good reasons :
1. it opens a new project scope (starting a new 'ant -buildfile yourfile.xml yourtarget')
so it uses more memory, slowing down your build
2. depending targets of the called target will be called also !
3. properties don't get passed back to the calling target

In some cases it might be ok when calling the same 'standalone' target (a target that has no target it depends on) with different params for reuse. Normally macrodef or scriptdef are used for that purpose. So, think twice before using antcall which also puts superfluous complexity to your scripts, because it works against the normal flow.

Answer to your question in the comment, using a dependency graph instead of antcall
you have some target that holds all conditions and sets the appropriate properties which may be evaluated by targets via if and unless attributes to control the further flow

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文