I want to use an condition property to set the property value to X if another property is defined and Y otherwise. However, I don't want the user to be able to override the condition property from the command line.
How can this be achieved?
I want to use an condition property to set the property value to X if another property is defined and Y otherwise. However, I don't want the user to be able to override the condition property from the command line.
How can this be achieved?
不,您不能覆盖命令行上设置的属性。至少,这并不容易做到。在命令行上覆盖属性的全部目的是允许用户覆盖默认值,以便在项目构建方式中进行修改。例如:
<property file="${basedir}/build.properties"/>
<property name="javac.debug" value="no"/>
<target name="compile">
<javac destdir="${main.destdir}"
debug="${javac.debug}">
默认情况下,编译 Java 代码时没有调试信息。也许这样做是为了使 jar 文件更小,或者更快地解释,或者可能使代码更难反编译和阅读。无论出于何种原因,此构建都不会将调试信息放入类文件中。
但是,开发人员确实需要此调试信息,因此他们希望能够覆盖此设置:
$ ant -Djavac.debug=true compile
或者,他们可以创建一个build.properties
文件并将值放入其中。
当您不使用 Ant 进行构建时,就会出现此类问题。我知道几个使用 Ant 脚本进行部署的站点。我通常不鼓励这样做,因为 Ant 并不是为这种类型的东西而设计的。例如,Ant 没有任何内置逻辑或循环。属性一经设置,便无法更改。这些对于构建语言来说是个好主意,但对于通用编程语言来说却是个糟糕的主意。
此外,开发人员不应该为 QA 或生产进行构建。这些应该由不会覆盖默认值的构建服务器完成。
现在如何摧毁这个经过深思熟虑的系统并造成绝对的破坏:
您可以在项目中使用ant-contrib任务。这样做将允许您访问 Ant Contrib var任务以取消设置属性。
下载 ant-contrib.jar 文件(无论最新版本是什么),并将其放在lib
项目下的目录中。然后你可以这样做:
<project name="danger-will-robinson" default="package" basedir="."
xmlns:ac="http://ant-contrib.sourceforge.net">
<!-- Define the Ant-Contrib tasks -->
<taskdef=resource="net/sf/antcontrib/antlib.xml"
uri="http://ant-contrib.sourceforge.net">
<classpath>
<fileset dir="${basedir}/lib">
<include name="ant-contrib*.jar"/>
</fileset>
</classpath>
</taskdef>
<!-- Unset Property "foo", so you can use it -->
<ac:var name="foo" unset="true"/>
请注意,<classpath>
指向${basedir}/lib
目录中的 ant-contrib jar。如果您将其签入您的源存储库,它将允许签出您的项目的每个人都能够进行构建,而无需在他们的系统上安装 ant-contrib jar。
请注意,我已经定义了一个“ac” XML 命名空间,因此 Ant-Contrib 任务不会与其他可能的第三方任务重叠。
一旦设置,ant 中的属性在设计上是不可变的。您可以使用任何提供对 ant api 访问的脚本语言(即 javascript)覆盖现有属性。
JDK >= 1.6 已经附带了一个 javascript 引擎,所以你可以使用类似的东西:
<project>
<property name="x" value="whatever"/>
<script language="javascript">
project.getProperty('x') ?
project.setProperty('foo', 'true') :
project.setProperty('foo', 'false');
</script>
<echo>$$[foo} => ${foo}</echo>
</project>
盒子外面。
但是,如果有人使用,那将无济于事ant -f yourbuild.xml -Dfoo=bla
!因为 userproperties(通过 -Dkey=value 定义的那些属性)具有特殊保护。
所以你的要求“..但是,我不希望用户能够从命令行覆盖条件属性”。
未满。
但是let
来自Ant addon Flaka的任务提供了覆盖甚至 userproperties 的可能性:
<project xmlns:fl="antlib:it.haefelinger.flaka">
<property name="x" value="whatever"/>
<!--
:= defines a new property whereas
::= overwrites any existing property
even userproperties
-->
<fl:let> foo ::= has.property['x'] ? 'true' : 'false'</fl:let>
<echo>$$[foo} => ${foo}</echo>
</project>
使用 ant -f yourbuild.xml -Dfoo=bla 运行这两个脚本以查看差异。
Ant api 也有方法 project.setUserProperty(String,String) 所以你也可以使用:
...
<script language="javascript">
project.getProperty('x') ?
project.setProperty('foo', 'true') :
project.setProperty('foo', 'false');
project.getUserProperty('x') ?
project.setUserProperty('foo', 'true') :
project.setUserProperty('foo', 'false');
</script>
...
防止通过 .. -D .. 设置 foo 属性,即使在命令行上定义了属性 x 也可以工作 -Dx=whatever
您必须做出选择,使用开箱即用的 javascript 脚本任务或 Flaka let 任务oneline 解决方案,但需要 Flaka jar。