How to verify wheter ${property}.attribute is set in ant - 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>

Related

How to pass Ant property values set in one target to another which does not depend on the first

Below is the example Ant task.
<target name="evalTask">
<condition property="conditionValue" >
<mycustomTask:evaluateCondition/>
</condition>
</target>
<target name="checkAndUpdateFlag" unless="conditionValue">
<property name="isEnabled" value="true"/>
</target>
<target name="targetA" depends="checkAndUpdateFlag" unless="conditionValue">
<echo message="Do something if the conditionValue is set" />
</target>
<target name="targetB">
<echo message=" Value of isEnabled : ${isEnabled} />
</target>
In the above example target "evalTask" will set the property "conditionValue" is the my custom task "evalauateCondition returns true.
The target "targetA" will get executed only if the property "conditionValue" is set. Which I am working fine. But the property "isEnabled" in "checkAndUpdateFlag" is not getting set or it never gets inside "checkAndUpdateFlag" target and I still get the "isEnabled" property value inside "targetB" as ${isEnabled}. Basically the "isEnabled" is never set.
Below is the ant command I used to run this targets.
ant targetA targetB
Any suggestion on why I am not getting the value of isEnabled in targetB ?
In your example, the evalTask target never runs so the conditionValue property is never set.
Since the conditionValue property isn't set, the checkAndUpdateFlag target won't run:
<target name="checkAndUpdateFlag" unless="conditionValue">
The unless="conditionValue" tells Ant to skip the <target name="checkAndUpdateFlag"> if the conditionValue property isn't set.
Possible solution #1:
Add a depends to checkAndUpdateFlag:
<target name="checkAndUpdateFlag" unless="conditionValue" depends="evalTask">
<!-- ... -->
Possible solution #2:
Call the evalTask target first on the command line:
ant evalTask targetA targetB

Conditional property in Ant properties' file

Is it possible to set a property value in Ant property files (as opposed to build.xml) in a conditional way? For example, if apache.root property is set - the my_property will be ${apache.root}/myapp, /var/www/myapp otherwise. If not, what would be the common practice - reusable build.xml files?
Use the condition task:
<project name="demo" default="run">
<condition property="my_property" value="${apache.root}/myapp" else="/var/www/myapp">
<isset property="apache.root"/>
</condition>
<target name="run">
<echo message="my_property=${my_property}"/>
</target>
</project>
You can include different property files based on environments or the conditional variables. For example
<echo>Building ${ant.project.name} on OS: ${os.name}-${os.arch}</echo>
<property file="build-${os.name}.properties" />
this would include a file named 'build-Windows 7.properties' or 'build-Linux.properties' depending on where the build is being run. Of course the property directive looks in the current directory as well as home directory. So the property file could be a part of the build source or in the home directory of the build account.
You can use the condition tag to generate part of the name of the property file as well to select
One of the simplest form of condition you can use is:
<exec executable="hostname" outputproperty="hostname"/>
<condition property="python" value="/usr/bin/python3.4">
<equals arg1="${hostname}" arg2="host0"/>
</condition>
<property name="python" value="/usr/bin/python"/>
to accommodate different python installation path for example. Here, default install path is /usr/bin/python except for host0 where it /usr/bin/python3.4
The OP was asking about a properties file, not within the ant build file. Unfortunately conditionals cannot be done from within the build file. What you can do is have separate property files for each set of dependant properties. For instance:
Build.xml
<condition property="app.name" value="appA">
<equals arg1="${appName}" arg2="A" />
</condition>
<condition property="app.name" value="appB">
<equals arg1="${appName}" arg2="B" />
</condition>
<property file="${app.name}.properties" />
<!-- since properties are immutable, set your defaults here -->
<property name="apache.root" value="/var" />
<property file="restOfProps.properties" />
appA.properties
apache.root=/appA
restOfProps.properties
my_property=${apache.root}/myapp

running specific target in different ant scripts in different directories

We have a large amount of apps. They all have a build.xml file located in the projects base directory. I am trying to create an ant script that will go through and call a specific target on each of the build.xml files in all the projects.
Here are the issues:
Some of the projects are in deeper directories than others.
Only some of the projects need to be built at a time.
I was trying to use subant + antfile and defining a CSV of file paths in a properties file, but this did not work. Below is what i have and the error i am getting.
If there is a better way to do this or you know what my problem is, please let me know! Thanks!
This is the property defined in a property file. I am wanting the person running the script to add the file paths in here that are relative to the current location of the script they are running.
projects.to.build=
This is the subant task i am trying to use in the main build script.
<filelist
id="projectNames"
dir="${basedir}"
files="${projects.to.build}"
/>
<target name="debugAll" description="Builds all the projects listed in the projectNames.properties file.">
<subant target="debug" antfile="${projects.to.build}">
</subant>
</target>
Here is the error i get when i try to run the build script when there are projects defined in the properties file. I am using the relative path. For example: ..\Apps\AnApp1\build.xml,..\Apps\AnApp2\build.xml,..\OtherApps\foo\AnotherApp1\build.xml
"No Build Path Specified" (at my subant task)
You specified the antfile attribute, so ANT was expecting to a single build.xml file.
The subant documentation describes how you can use a fileset as child parameter.
Here's an example:
<project name="Subant demo" default="run-debug-target">
<target name="run-debug-target">
<subant target="debug">
<fileset dir="." includes="**/build.xml" excludes="build.xml"/>
</subant>
</target>
</project>
Update
Alternatively a filelist could be used:
<project name="Dry run" default="run">
<target name="run">
<subant target="test">
<filelist dir="projects" files="one/build.xml,two/build.xml,three/build.xml,four/build.xml"/>
</subant>
</target>
</project>
Processing the following build files:
projects/one/build.xml
projects/two/build.xml
projects/three/build.xml
projects/four/build.xml
Is it possible to run the target in the all the build files concurrently ?
E.g.
<project name="Dry run" default="run">
<target name="run">
<subant target="test">
<filelist dir="projects" files="one/build.xml,two/build.xml,three/build.xml,four/build.xml"/>
</subant>
</target>
</project>
In this example, is there any way to run target "test" present in all the build files (one/build.xml,two/build.xml,three/build.xml,four/build.xml) concurrently ?

Creating an ear-File with ant

I am new to ant i referred many sites , i need to build.xml for my project which consists
of two modules i have application.xml file which represents corresponding war file
so my question is it sufficient to add the application.xml file
<ear destfile="${dist.dir}/${ant.project.name}.ear" appxml="${conf.dir}/application.xml">
<metainf dir="${build.dir}/META-INF"/>
<fileset dir="${dist.dir}" includes="*.jar,*.war"/>
</ear>
whether this will refer the corresponding war files or i need to compile the whole scenario please let me know. how solve this.
I'm not 100% sure what you're asking.
In order to use the <ear> task, you already need to have compiled the required jars and wars.
If those jars and wars have already been built, you simply refer to them in your <ear> task as you did in your example. The application.xml must already exist before you build your ear. The application.xml doesn't build the jars and wars, you have to do that.
If you haven't already built the wars and jars, you need to do that first. A general outline of a build.xml looks something like this:
<project name="foo" basedir="." default="package">
<!-- Some standard properties you've defined -->
<property name="target.dir" value="${basedir}/target"/>
<property name="xxx" value="yyy"/>
<property name="xxx" value="yyy"/>
<property name="xxx" value="yyy"/>
<!-- Compile properties that allow overrides -->
<property name="javac.nowarn" value="false"/>
<property name="javac.listfiles" value="false"/>
<property name="javac.srcdir" value="source"/>
<property name="javac.distdir" value="${target.dir}/classes"/>
<target name="clean"
description="cleans everything nice and shiny">
<delete dir="${target.dir}"/>
</target>
<target name="compile"
description="Compiles everything">
<mkdir dir="${javac.distdir}"/>
<javac srcdir="${javac.srcdir}"
destdir="${javac.destdir}"
[...]
[...]/>
</target>
<target name="package.jar"
depends="compile"
description="Package jarfile">
<jar destfile="${target.dir}/jarname.jar"
[...]
[...]/>
</target>
<target name="package.jar2"
depends="compile"
description="Package jarfile">
<jar destfile="${target.dir}/jarname2.jar"
[...]
[...]/>
</target>
<target name="package.war"
depends="compile"
description="Package jarfile">
<war destfile="${target.dir}/jarname.jar"
[...]
[...]/>
</target>
<target name="package"
depends="package.jar"
description="Make the ear">
<ear destfile="${target.dir}/earfile.ear"
[...]/>
</target>
</project>
Basically, it consists of a bunch of targets and each target does one task. You can have targets depend upon other targets. For example, this particular build.xml will automatically run the package task. The package task depends upon the package.jar task which depends upon the compile task. Thus, the build.xml file will first call compile, then package.jar, then package.
The important thing to remember is that you don't specify the order of the events. You let Ant figure that out, and you let Ant figure out what you need to do. Let's say you've modified a java source file. Ant knows that it has to recompile only that one file. It also knows that it might have to rebuild the jarfile that contains that classfile. And, it then knows it has to rebuild the ear. Most tasks can figure it out on their own, and you don't do a clean for each build. (You notice that the clean target isn't called by package or compile. You have to call it manually).
The only other thing I recommend is that you try to keep your work area clean. Any files you create should be put into the ${target.dir} directory. That way, when you do a clean, you only have to delete that one directory.
I hope this answer your question.

Ant build scripts

I am using ant script for generating war file, it will generate the war file. please see the below script
<target name="war" depends="build">
<mkdir dir="${dist}" />
<jar destfile="${dist}/${proj_name}.war" basedir="${build}" />
</target>
If it generates a new war file, then i want to have a property to set the value as "newupdates" otherwise i want to know "noupdates"
A strategy to do this could be to use the UpToDate task to set the property.
You just have to copy the war file to war.bak just after performing the uptodate check, to prepare for the next run.
Another strategy (probably even better) would be to use the UpToDate task to determine if the war has to be generated, setting a property, e.g myuptodateproperty. Then call your war generation target, and make sure it has an if=${myuptodateproperty} constraint, in order not to regenerate the war if it is not needed.
You can use something in the line of (untested code, may need some work):
<target name="war" depends="clean,fillbuildanddist,build">
<mkdir dir="${dist}" />
<uptodate targetfile="${dist}/${proj_name}.war" property="uptodatewar">
<fileset dir="${build}" />
</uptodate>
<antcall target="makewar" />
</target>
<target name="makewar" unless="uptodatewar">
<jar destfile="${dist}/${proj_name}.war" basedir="${build}" />
</target>
With this, the property uptodatewar should be set to true only if the war does not need to be rebuilt, and thus the jar task will only be called in this case. In targets that depend on the war target, you can use the uptodatewar to perform tasks only if the war is new.

Resources