Ant, set environmental variable for <ant> task? - ant

I want to run another ant build file from ant, and the <ant> task looks perfect for this.
The other build file uses environmental variables for a couple things. Is there a way to set environmental variables for the child ant process?
I see that the <exec> task seems to support nested <env>s, but nothing similar for <ant>.

From the documentation of ant task,
By default, all of the properties of the current project will be available
in the new project.
You can also set properties in the new project from the old project by using
nested property tags.
<ant antfile="subproject/property_based_subbuild.xml">
<property environment="env"/>
</ant>

by default the inner ant call inherits the parent properties
<ant inheritAll="true" antfile="subproject/subbuild.xml">
<!--inheritAll="true" is default value, this is unecessary -->
<property name="myprop" value="foo"/>
<antcall target="myTarget"></antcall>
<ant antfile="myAntFile"></ant>
</ant>
In this case, "myTarget" and all targets on "myAntFile" can get "foo" as "myprop" value.

Related

Force Ant to substitue a substitution variable

I use a software (Drops) based on ant script.
I try to dynamically generate the destination path of a file that I want to copy. To do this I execute a linux command line.
In my application, I have this properties :
environment.props.environment_name=recette
application.props.target.gmao=/opt/${environment.props.environment_name}/gmao-ws
I expected Ant to replace ${environment.props.environment_name} by its value at runtime. But it doesn't.
Here is the Ant script that I wrote :
<project xmlns:drops="antlib:com.arcadsoftware.mmk.anttasks" name="deployJar" basedir="." default="main">
<taskdef resource="net/sf/antcontrib/antlib.xml"/>
<taskdef resource="com/dropssoftware/drops/ant/antlib.xml"/>
<loadDropsContext/>
<target name="main">
<!-- get the value of the property "application.props.target.gmao" -->
<propertycopy name="target.dir" from="application.props.target.gmao"/>
<!-- I expect this to print target.dir=/opt/recette/gmao-ws but it print target.dir=/opt/${environment.props.environment_name}/gmao-ws -->
<echoproperties />
<!-- Supposed to copy from /opt/drops/storage/afile.jar to /opt/recette/gmao-ws but the property "target.dir" is wrong -->
<exec executable="sudo">
<arg value="/bin/cp"/>
<arg value="${param.artifacts.root}/${param.jar.root}"/>
<arg value="${target.dir}"/>
</exec>
</target>
</project>
With this input :
param.env=gmao
param.artifacts.root=/opt/drops/storage/
It is supposed to copy a file from the artifacts directory to the /opt/recette/gmao-ws directory. But Ant tried to copy it to /opt/${environment.props.environment_name}/gmao-ws.
I don't understand why Ant doesn't replace ${environment.props.environment_name} by its value.
Is it possible to force Ant to replace the substitution variable by its value ?
Not entirely clear what you're trying to do. The propertycopy task is not part of normal Ant, coming from a 3rd party extension called ant-contrib
I suspect what you're trying to do can be done with normal property substitution. I have provided an example.
Example
A simple example of how to pass in parameters to a build file by setting properties:
$ ant -Dparam.from=AAA -Dparam.to=BBB
build:
[echo]
[echo] sudo
[echo] /bin/cp
[echo] /opt/drops/storage/AAA
[echo] /opt/drops/storage/BBB
[echo]
build.xml
Note the 3 properties declared at the top? These are effectively the default values available for override.
<project name="demo" default="build">
<property name="param.artifacts.root" value="/opt/drops/storage"/>
<property name="param.from" value="fromDir"/>
<property name="param.to" value="toDir"/>
<target name="build">
<echo>
sudo
/bin/cp
${param.artifacts.root}/${param.from}
${param.artifacts.root}/${param.to}
</echo>
</target>
</project>
I think that I find the answer to my question in ant document :
https://ant.apache.org/manual/properties.html
Normally property values can not be changed, once a property is set, most tasks will not allow its value to be modified.
In the case of the software that I use : Drops, it loaded the application properties BEFORE the environment properties.
So application.props.target.gmao is set BEFORE environment.props.environment_name and the ${environment.props.environment_name} cannot be replace.
The answer to my question is seems to be NO, it's not possible to force Ant to replace the substitution variable by its value.
It's done automatically if the variables are loaded in the good order.

How to verify wheter ${property}.attribute is set in ant

I have multiple projects. Each of the project may or may not have a dependent classes. If I have dependent classes I have to build a jar based on the java files in the class property and add to project1 jar if the property is specified or it should be ignored.
Now I have to dynamically loop through all of the projects and in the target i have to test for the existance of the property and build if the property exist.
<target name="test">
<foreach list="${projects}" target="test2" param="project"/>
</target>
<target name="test2">
<!-- Here i have to test wheter ${project}.class exist or not-->
</target>
The following is a sample property file
projects=project1,project2,...
project1.class=class1.java,class2.java
Here project2 doesn't have a .class property,So it should not build a dependency jar. How can I test the existance of the property . I know is set can be used to know the status of property but this comes dynamically can someone help on this ?
You are on the right track with <isset>:
<target name="test2">
<if>
<isset property="${project}.class"/>
<then>
<echo message="${project}.class exists -- let's run a build"/>
</then>
</if>
</target>

Using "antcall" in included ant files

I have a shared ant script b.ant which internally use antcall. It calculates a property that the client scripts use. I use include instead of import client scripts to avoid unintentional overwriting of targets, but this gives me a problem with the antcall.
When using include all targets in b are prefixes, and depends attributes in b are updated accordingly. This is however not true for antcall. Is there a there are way to handle this, i.e. make antcall always call the "local" ant target?
I can workaround this by using import, but then I'll get all the overwrite problems. It is not possible to use depends instead of antcall.
Example files
I have two files:
a.ant
<project>
<include file="b.ant" as="b" />
<target name="test-depends" depends="b.depend">
<echo>${calculated-property}</echo>
</target>
<target name="test-call" depends="b.call">
<echo>${calculated-property}</echo>
</target>
</project>
b.ant
<project>
<target name="depend" depends="some-target">
<property name="calculated-property" value="Hello World"/>
</target>
<target name="call">
<antcall target="some-target" inheritrefs="true"/>
<property name="calculated-property" value="Hello World"/>
</target>
<target name="some-target"/>
</project>
Example output
Calling test-depend works as expected but test-call fails with this output:
b.call:
BUILD FAILED
D:\ws\rambo2\ws-dobshl\ant-test\b.ant:6: The following error occurred while executing this line:
Target "some-target" does not exist in the project "null".
Total time: 258 milliseconds
Ant is a dependency matrix specification language. Usually a bunch of <antcall/>, <ant/>, <include/> and <import/> is a sign of a poorly written build script. It's a developer trying to force Ant to act like a programming language.
For developer, it makes sense to break up a program into smaller files. Even Python and Perl scripts can benefit from this. However, breaking up an Ant build script usually causes problems. We had a developer who went through every project and broke up all the build.xml files into six or seven separate build files in order to improve the process. It basically broke the whole Ant dependency mechanism. To fix it, he then tossed in a bunch of <ant/> calls and <include> tasks. In the end, it meant that each target was called between 12 to 20 times.
Not using <import/> and <antcall/> isn't a hard and fast rule. But, I've been using Ant for years and rarely ever used these mechanisms. When I do, it's usually for a shared build file that multiple projects will use (which sounds like what you have) but instead of defining targets in my shared build file, I define macros. This eliminates the target namespace issues that you are having, and the macros work better because they act more like Ant tasks. This is especially true with the introduction of <local/> in Ant 1.8.
See if you can restructure the shared build file into using <macrodef/> instead of targets. It will make it much easier to include your shared build file.
Give a name to the <project> in b.ant and then change the target of the <antcall>:
<project name="b"> <!-- Give the project a name -->
<target name="depend" depends="some-target">
<property name="calculated-property" value="In b.depend"/>
</target>
<target name="call">
<!-- Specify the name of the project containing the target -->
<antcall target="b.some-target" inheritrefs="true"/>
<property name="calculated-property" value="In b.call"/>
</target>
<target name="some-target"/>
</project>
The result of ant -f a.ant test-call:
b.call:
b.some-target:
test-call:
[echo] In b.call
BUILD SUCCESSFUL
With the changes to b.ant, the <include> in a.ant can be simplified by removing the as attribute:
<include file="b.ant" />

ant file that depends on another ant file

I have two projects, each with its own ant build file.
What should I do so that, when I build project B, it will first build project A using project A's antfile?
You can achieve this by using the ant task, which runs ant on an external buildfile.
Example:
<ant antfile="../otherproject/build.xml" target="compile"/>
Properties
By default all current properties are passed to the invoked ant build, this can be disabled by setting inheritAll="false", if you want the other build to behave natively.
Properties that are need can be passed by nested tags:
<ant inheritAll="false" antfile="../otherproject/build.xml" target="compile">
<property name="my.property" value="myValue"/>
</ant>

Can Ant expand environment variables from a properties file?

I have a question regarding Ant and its treatment of environment variables.
To illustrate I have a small sample.
Given the Ant build file test.xml:
<project name="myproj" default="testProps">
<property environment="env"/>
<target name="testProps">
<echo message="${env.MyEnvVar}"/>
<echo message="${MY_PROPERTY}"/>
</target>
</project>
And the properties file test.props:
MY_PROPERTY=${env.MyEnvVar}
Now set the environment variable MyEnvVar to some value (foo in my case) and run Ant using this command line:
ant -f test.xml -propertyfile test.props testProps
The output I get is:
[echo] foo
[echo] ${env.MyEnvVar}
What I would like to know is whether there is any way to structure the input properties file such that I get
[echo] foo
[echo] foo
That is, I would like to name an environment variable in the properties file which is replaced within the Ant script. Note - I know how to access environment variables directly (as is done here). What I need to do is make use of a set of Ant scripts that expect one collection of properties in an environment that defines the same properties using different names. Thus the thought of "bridging" them in a properties file.
I am using Ant version 1.6.5.
You need to read the test.props property file after the environment - you could do so using another property task, i.e. add
<property file="test.props" />
after your existing property environment task.
In full:
<property environment="env" />
<property file="test.props" />
<target name="testProps">
<echo message="${env.MyEnvVar}"/>
<echo message="${MY_PROPERTY}"/>
</target>
When you supply the properties file on the command line this gets processed before the content of the build, but at that time ${env.MyEnvVar} is not yet set.

Resources