I am trying to change the ant.project.name property after the project declaration. I know this is not advisable but it's the only way I can fix a big problem with my project.
I found some interesting posts like this one:
Ant - How to set ${ant.project.name} to project folder name?
Instead of using:
<project basedir="." default="package">
<basename property="ant.project.name"
file="${basedir}"/>
</project>
I'd like to directly set the ant.project.name using a "value" instead of a property "file".
Do you have any ideas or suggestions? Or alternative ways?
Thank you!
As others already mentioned, it's not recommended to change values of standard ant properties.
Also properties once set are immutable in ant by design and for good reasons. Overriding properties should be used wisely and rarely.
The property ant.project.name is usually set via name attribute of project =>
<project name="whatever"> but it's not mandatory, means <project> ... </project> is sufficient to make your xml a valid antscript.
In your case <echo>${ant.project.name}</echo> would echo ${ant.project.name}, as property is not set, so you may create it with property task in your script : <property name="ant.project.name" value="whatever"/>. But using a propertyname that is normally used for 'ant internals' seems not the best choice.
If property is set within project tag it's possible to overwrite the value via script task, using builtin javascript engine and ant api, f.e. :
<project name="foo">
<property name="bla" value="foobar"/>
<echo>1. $${ant.project.name} => ${ant.project.name}</echo>
<script language="javascript">
project.setUserProperty('ant.project.name', project.getProperty('bla'));
</script>
<echo>2. $${ant.project.name} => ${ant.project.name}</echo>
</project>
output :
[echo] 1. ${ant.project.name} => foo
[echo] 2. ${ant.project.name} => foobar
Notice : as ant.project.name is not a 'normal' property (those properties declared via property task within ant script), you have to use the method project.setUserProperty(String, String) instead of project.setProperty(String, String). Userproperties are properties defined via -Dkey=value commandline argument and enjoy a special protection.
Ant also provides a bunch of builtin properties
Related
I need to retrieve all the properties' names from a properties file before loading it (using Ant)
I'll go into detail to explain the whole process:
A first properties file (let's name it as a.properties) is read and
all its properties loaded as project's properties.
#a.properties's contents
myvar1=1
myvar2=someTextHere
A second file (let's say b.properties) has to be loaded on the
project. Some already-set properties can also be contained in this
second file, so what we have to do is to update such variables with
the value found on it (by means of the ant-contrib's var target)
#b.properties's contents
myvar1=2 #updated value for a property that's is already set on the project
myvar3=1,2,3,4,5,6
So the expected subset (from a ANT project's properties perspective)
of property/value pairs would be:
myvar1=2
myvar2=someTextHere
myvar3=1,2,3,4,5,6
We cannot change the order in which those files are loaded on the project, which would be the easiest way of solving the issue (because of the behavior adopted by Ant when setting's properties)
Any feedback will be highly appreciated.
Regards
I assume that you need to read properties from different files before you build your source code
<target name=-init-const-properties description="read all properties required">
<propertyfile file="AbsolutePathToPropertyFile" comment="Write meaningfull
about the properties">
<entry value="${myvar1}" key="VAR1"/>
<entry value="${myvar2}" key="VAR2"/>
</propertyfile>
</target>
Note: you need to add proper AbsolutePathToPropertyFileand comment if required
In the target -init-const-properties you can add as many files you want to read and use this target as dependent target in which you going to use these property values. hope this will answer your question
I recommend having a standard file for build defaults called "build.properties". If you need to override any settings, then create an optional file called "build-local.properties".
My advice is to keep build logic simple. Using the ant-contrib extension to make properties act like variables is rarely needed in my experience.
Example
├── build-local.properties
├── build.properties
└── build.xml
Running the project produces the following output, where the value "two" is substituted:
$ ant
build:
[echo] Testing one, dos, three
Delete the optional file and it goes back to default values:
$ rm build-local.properties
$ ant
build:
[echo] Testing one, two, three
build.xml
The secret is the order in which the property files are loaded. If they don't exist then they don't create properties.
<project name="demo" default="build">
<property file="build-local.properties"/>
<property file="build.properties"/>
<target name="build">
<echo message="hello ${myvar1}, ${myvar2}, ${myvar3}"/>
</target>
</project>
build.properties
myvar1=one
myvar2=two
myvar3=three
build-local.properties
myvar2=dos
Finally, the approach I followed was to specify the second properties file (b.properties) from the command line:
ant <my_target> -propertyfile b.properties
So that's work fine to me...
Thanks all of you for your help.
Working with simple ant's property is tricky & doesn't allow to set needed value easily (properties are immutable). Using ant-conrib's var tasks allows properties to be set and unset.
Any genuinue or good reason behind making ant property designed to work in such a complex way?.
<property name="some.ant.prop" value=""/>
<if>
<isset property="some.ant.prop"/>
<then>
<echo message="immutable ant prop - not good, defined and just even set to null string : ${some.ant.prop}"/>
<property name="some.ant.prop" value="no-effect-value"/>
<echo message="no-effect on changing already defined prop : ${some.ant.prop}"/>
<var name="some.ant.prop" unset="true"/>
<property name="some.ant.prop" value="any-value-accepted"/>
<echo message="Overwritten prop value: ${some.ant.prop}"/>
</then>
</if>
Not for discussion or argument , but its good to know on more feasible alternatives. Thanks.
Ant ain't a programming language !
Properties once set are immutable in ant by design.The Pros and Cons have been discussed (much too) often and i won't go into details.
Several possibilities to get over those limitations :
In the past people used antcall for that purpose - with all its drawbacks, search for 'antcall vs. macrodef' to get the details. Ant 1.6 introduced macrodef and Ant 1.8 came with a new local task.
If macrodef and local are not sufficient you may use script task with builtin javascript engine (since JDK 1.6) or Groovy to access ant api.
There are also Ant addons like f.e. antcontrib or Flaka. If antcontrib var / unset feels too clumsy for you, the
Flaka's let task provides a more straight approach for overwriting properties :
<!-- set a new property -->
<fl:let>foo := 'bar'</fl:let>
<!-- overwrite an existing property or userproperty
(those properties defined on the commandline via -Dfoo=bar ..)
notice the double '::' in foo ::= 'baz' -->
<fl:let>foo ::= 'baz'</fl:let>
Finally : Either get used to ant and its limitations (but don't use antcall !) oruse Ant addon use ant from groovy or switch to Gradle.
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?
Starting from ant 1.8 for some use cases local task may be applicable. Since a property is made local it starts with an empty value. It's scope is limited to current target, but you may pass it to subsequent targets using param argument in antcall.
Nope, you can't override a property set on the command line. At least, it's not easy to do. The whole purpose of overriding properties on the command line is to allow users to override defaults in order to make modification in the way your project builds. For example:
<property file="${basedir}/build.properties"/>
<property name="javac.debug" value="no"/>
<target name="compile">
<javac destdir="${main.destdir}"
debug="${javac.debug}">
By default, the Java code is compiled without debugging information. Maybe this is done to make jar files smaller, or faster interpretation, or maybe to make the code harder to decompile and read. Whatever reason, this build won't put debug information into the classfiles.
However, developers do want this debugging information, so they want to be able to override this setting:
$ ant -Djavac.debug=true compile
Or, they can create a build.properties file and put the value in there.
This type of issue comes up when you're not using Ant for builds. I know several sites that use Ant scripts to do deployments. I usually discourage this because Ant isn't really made for this type of thing. For example, Ant doesn't have any built in logic or loops. Once a property is set, it can't be changed. These are good ideas for a build language, but a terrible idea for a general purpose programming language.
Also, developers shouldn't be doing builds for QA or production. Those should be done by a build server that won't override defaults.
Now how to destroy this whole well thought out system and cause absolute havoc:
You can use the ant-contrib tasks in your project. Doing this will allow you to access the Ant Contrib var task to unset properties.
Download the ant-contrib.jar file (whatever the latest version is), and put it in a lib directory under your project. Then you can do this:
<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"/>
Note that the <classpath> points to the ant-contrib jar in the ${basedir}/lib directory. If you check that into your source repository, it will allow everyone who checks out your project to be able to do the build without installing the ant-contrib jar on their system.
Note that I've defined a "ac" XML namespace, so Ant-Contrib tasks won't overlap other possible third party tasks.
Properties in ant once set are immutable by design. You may overwrite an existing property with any scripting language that provides access to ant api, i.e. javascript.
JDK >= 1.6 already ships with a javascript engine, so you may use something like :
<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>
out of the box.But that won't help if someone uses ant -f yourbuild.xml -Dfoo=bla !! as userproperties (those properties defined via -Dkey=value) have a special protection.
So your requirement "..However, I don't want the user to be able to override the condition property from the command line". is not fullfilled.
But the let task from Ant addon Flaka provides the possibillity to overwrite even 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>
Run both scripts with ant -f yourbuild.xml -Dfoo=bla to see the difference.
Ant api has also method project.setUserProperty(String,String) so you may use also:
...
<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>
...
to prevent the foo property to be set via .. -D .. and it will work even if property x is defined on commandline -Dx=whatever You have to make your choice, script task with javascript out of the box or Flaka let task
oneline solution but Flaka jar needed.
Is it possible to change ant property location attribute with .properties file like
property value attribute?
ant.xml
<property name="images" location="some_location" />
ant.properties
name=D:\images
See ant manual propertyfile => there is no attribute called location.
The location attribute from property task is only a 'special' case of a value, that knows how to deal with absolute and relative pathes.
If you need to edit | overwrite existing property values(locations) use either :
ant script task (groovy or groovy task recommended)
or some Ant addon like Flaka or Antcontrib, providing tasks for that purpose.
Declaring a property within the build file will override the same value imported from a properties file.
The only way to do this is setting the property value on the command-line as follows:
ant -Dimages=D:\images
How do you call a specific target in all build.xml located in all subdirectories using wildcards (ie not hard coding the subdirectory names)? The below answer is hardcoded. Is there a way to do it without hardcode?
Similar to this question: Pass ant target to multiple build.xml files in subdirectories
Use the Ant subant task like this:
<subant target="sometarget">
<fileset dir="." includes="*/build.xml" />
</subant>
If you include an "inheritall" attribute (same as how it's used in but defaults the opposite), you can share all your current project's properties and everything too. This also makes it very easy to overwrite tasks defined in your main build.xml file if you need to.
Read more about it here.
I'll setup different properties within my build.properties file. I use these to dynamically build paths in my targets.
Define the location of your build.properties file:
<!-- all properties are in build.properties -->
<property file="build.properties" />
Use those properties in your targets:
Properties in the build properties are similar to setting up an .ini file:
project.rootdir=c:/Deploy
project.tempbuilddir = c:/Deploy/Temp/Inetpub
project.builddir=c:/Deploy/Inetpub
# Build prefix will be added to that tags urls (.../tags/${project.buildprefix}Build_${today.date})
project.buildprefix=ACA_
I guess you could use a dynamic file as your properties file, if necessary, as long as you define the proper path to the file. You could point it to a server-side file to dynamically write your properties file (ColdFusion, PHP, JSP, whatever).
I've used ant-contrib's foreach task to do something like this.
http://ant-contrib.sourceforge.net/tasks/tasks/foreach.html
Sounds like a perfect candidate for the <subant> task.