Here's a simple Ant build file:
<?xml version="1.0" encoding="UTF-8"?>
<project name="Project" default="build" basedir=".">
<property name="compressAssets" value="false"/>
<target name="build" depends="compress-assets"/>
<target name="compress-assets" if="compressAssets">
<echo message="executed"/>
</target>
</project>
compressAssets is set to false, so how come the compress-assets target is executed every time? Note the if property on the target.
if does not check for the value of the property, it checks if the property has been set.
From the documentation:
<target name="build-module-A" if="module-A-present"/>
[...] if the module-A-present property is set (to any value, e.g. false), the target will be run.
In Ant 1.8, if now does check that the value is true (unless checks for false), so you can do:
<target name="blah" if="${do-blah}">
.
.
.
</target>
Related
Essentially, I am wondering how ant knows that $ means to pull from the properties file.. what if there was no properties file named?
Take example this build file
<?xml version="1.0" encoding="UTF-8"?>
<project name="Hello World Project" default="info">
<property file="build.properties"/>
<fileset dir="${build.dir}" >
<include name="**/*.java"/>
</fileset>
<target name="info">
<echo>${src}</echo>
</target>
</project>
I know that the $ sign is referencing a property in the build.properties file, however what if there is no properties file, what does the $ sign do in a regular Ant compilation?
Ant leaves references to non-existent properties unchanged. For example, the following Ant script...
<project name="ant-echo-missing-property" default="run">
<target name="run">
<property file="non-existent-file.properties"/>
<echo>${missing-property}</echo>
</target>
</project>
...outputs...
run:
[echo] ${missing-property}
build.xml
<target name="main">
<ant antfile="build-foo.xml" dir="${basedir}" target="foo"
inheritAll="false" useNativeBasedir="true">
<property name="messages" value="NOT_FOO_BAR"/>
</ant>
</target>
build-foo.xml
<target name="foo">
<property name="messages" value="FOO"/>
<ant antfile="build-bar.xml" dir="${basedir}" target="bar"
inheritAll="false" useNativeBasedir="true">
</ant>
</target>
build-bar.xml
<target name="bar">
<property name="messages" value="BAR"/>
<echo message="messages = ${messages}"/>
</target>
Tried:
ant -buildfile build-foo.xml foo
the messages is BAR, as expected.
ant -buildfile build.xml main
the messages is NOT_FOO_BAR.
The properties from main is passed multi-level down, even if it is not desired in build-foo.xml: inheritAll=false.
How to prevent the properties from being passed down to its descendant calls? Thanks.
From ant manual ant task :
You can also set properties in the new project from the old project by
using nested property tags. These properties are always passed to
the new project and any project created in that project regardless
of the setting of inheritAll. This allows you to parameterize your
subprojects.
instead :
<target name="main">
<ant antfile="build-foo.xml" dir="${basedir}" target="foo"
inheritAll="false" useNativeBasedir="true"/>
<property name="messages" value="NOT_FOO_BAR"/>
</target>
meets your expections.
My code:
<property environment="env"/>
<target name="detectTomcatFromEnv" unless="${env.CATALINA_HOME}">
<echo message="${env.CATALINA_HOME}"/>
</target>
I defined CATALINA_HOME and as I understand, target should not run.
But my result is:
detectTomcatFromEnv:
[echo] c:\apache-tomcat-7.0.21\
BUILD SUCCESSFUL
How it can be???
You need to remove the ${...} from unless:
<property environment="env"/>
<target name="detectTomcatFromEnv" unless="env.CATALINA_HOME">
<echo message="${env.CATALINA_HOME}"/>
</target>
See https://ant.apache.org/manual/targets.html:
unless: the name of the property that must not be set in order for
this target to execute, or something evaluating to false.
i have a project that uses a parent ant file
similar to this:
<project name="some-portlet" basedir="." default="deploy">
<import file="../build-common-portlet.xml" />
<target name="test">
<echo message="do foo"/>
RUN TEST FROM PARENT HERE
</target>
</project>
now i want to override the parent test target in this way:
do some copying of jars needed
run the test target from the parent file
the first part is no problem, but i do not see a way to call test from the parent file
i want the target to be named test also, so that CI can simply run the test target.
is there a way to call test in ../build-common-portlet.xml ?
The simplest way is to use dependency on parent's test.
For that it's important that you keep <project> name attribute in sync with its file name ( OK that's not, strictly speaking, necessary, but greatly improves your script's readability and maintainability ).
So in build-common-portlet.xml:
<project
name="build-common-portlet" <-- note the name
...
>
<target name="test">
<echo message="Calling parent test target"/>
...
</target>
</project>
That way you can just do:
<project name="some-portlet" basedir="." default="deploy">
<import file="../build-common-portlet.xml" />
<target name="test"
depends="build-common-portlet.test" <-- note parent specification
>
<echo message="do foo"/>
RUN TEST FROM PARENT HERE
</target>
</project>
>> In reply to comment
If you want to do some work before running parent's test, just create a new target and put dependency on it before parent's test:
<project name="some-portlet" basedir="." default="deploy">
<import file="../build-common-portlet.xml" />
<target name="copy-jars">
<echo message="copying jars"/>
</target>
<target name="test"
depends="
copy-jars,
build-common-portlet.test
"
/>
</project>
I found a solution, that would run my commands and then call test from the parent ant file.
Override the parent's test, then call when the parent's test once you've done your own "magic".
All other parent's targets can be called too.
So for somebody not knowing your ant file, she can call ant test the way it's expected.
<project name="some-portlet" basedir="." default="deploy">
<import file="../build-common-portlet.xml" />
<target name="test">
<echo message="do foo"/>
<ant antfile="../build-common-portlet.xml" target="test"/>
</target>
</project>
My build file is
<target name="default">
<antcall target="child_target"/>
<echo> ${prop1} </echo>
</target>
<target name="child_target">
<property name="prop1" value="val1"/>
</target>
I get an error that ${prop1} has not been set. How do I set a property in the target?
antcall creates a new project. From the Ant documentation:
The called target(s) are run in a new
project; be aware that this means
properties, references, etc. set by
called targets will not persist back
to the calling project.
Use depends instead:
<project default="default">
<target name="default" depends="child_target">
<echo>${prop1}</echo>
</target>
<target name="child_target">
<property name="prop1" value="val1"/>
</target>
</project>
Old and probably dead issue I know, but a property file loaded outside targets but inside the project would also work. Android does this with local.properties like so:
<?xml version="1.0" encoding="UTF-8"?>
<project name="avia" default="help">
<!-- The local.properties file is created and updated by the 'android' tool.
It contains the path to the SDK. It should *NOT* be checked into
Version Control Systems. -->
<property file="local.properties" />