Is there any way to get number of properties defined or provided through command line option?
I couldn't find any way till now.
Basically I have to check if command line properties are less than or greater than a specified number of properties, build should fail using
Instead of counting numbers you can check the required properties are set and fail the build if it is not set.
<project name="check" default="build">
<condition property="params.set">
<and>
<isset property="one"/>
<isset property="two"/>
</and>
</condition>
<target name="check">
<fail unless="params.set">
Must specify the parameters: one, two
</fail>
</target>
<target name="build" depends="check">
<echo>
one = ${one}
two = ${two}
</echo>
</target>
</project>
Related
is it possible to access from the ant script of the nbi (installer project) to variables defined in the platform.properties file, like the nbjdk.active which is setted when in a project the Java platform is changed?
The goal is from the ant script select one of the packaged jre (32 or 64) in function of this variable.
Thanks in advance.
Edit:
this is the build script fragment from when I try to access this variables:
<target name="-generate-bundles">
<for-each property="platform" list="${target.platforms}" separator=" ">
<condition property="bundle.extention.${platform}" value="exe">
<contains string="${platform}" substring="windows"/>
</condition>
<condition property="bundle.extention.${platform}" value="sh">
<or>
<contains string="${platform}" substring="linux"/>
<contains string="${platform}" substring="solaris"/>
</or>
</condition>
<condition property="bundle.extention.${platform}" value="zip">
<contains string="${platform}" substring="macosx"/>
</condition>
<set property="bundle.extention" source="bundle.extention.${platform}"/>
<create-bundle root="${output.dir}/registry-temp"
platform="${platform}"
target="${bundles.release.dir}/${bundle.files.prefix}-${platform}.${bundle.extention}">
<component uid="${main.product.uid}" version="1.0.0.0.0"/>
<!-- HERE I WANT TO CHECK THE VARIABLE AND SELECT ONE OF THE PACKED JRE -->
<!--<property name="nbi.bundled.jvm.file" value="D:\packed\jre1.8.0_65_32bits\jre.exe"/>-->
<property name="nbi.bundled.jvm.file" value="D:\packed\jre1.8.0_25_64bits\jre.exe"/>
</create-bundle>
<echo>************************</echo>
<echo>********* OS: ${platform}</echo>
<echo>********* Arch: ${os.arch}</echo>
<echo>********* JDK in NB: ${jdk.home}</echo>
<echo>********* JDK in platform.properties: HERE I TRY TO ACCESS VARIABLE</echo>
<echo>************************</echo>
<if property="bundle.extention" value="zip">
<antcall target="zip-to-tgz">
<param name="input.file" value="${bundles.release.dir}/${bundle.files.prefix}-${platform}.zip"/>
<param name="output.file" value="${bundles.release.dir}/${bundle.files.prefix}-${platform}.tgz"/>
</antcall>
<delete file="${bundles.release.dir}/${bundle.files.prefix}-${platform}.zip"/>
</if>
</for-each>
<echo>Installer(s) for [${target.platforms}] are available at ${bundles.release.dir}</echo>
</target>
and this is the variable in platform.properties file:
nbjdk.active=JDK_1.8.0_65-32bits
Here is the property file contents which are going to be accessed in the build script:
Below build script example shows how to access property abc which is from test.properties file.
All you need is to load the property file before accessing it as shown in the script using, of course, change the property file path as per your environment.
<property file="D:/Temp/test.properties"/>
Then use ${abc} whereever its value is needed as shown in the echo task below.
test.properties contents
abc=123
def=234
build.xml
<project name="imported" basedir="." default="test">
<property file="D:/Temp/test.properties"/>
<target name="test" description="check if the property can be retrieved from file">
<echo message="Property abc's value from file is ${abc}"/>
</target>
</project>
Output
test:
[echo] Property abc's value from file is 123
BUILD SUCCESSFUL
Total time: 0 seconds
[Finished in 4.7s]
Hope this is helpful.
I have a property file (x.props) that contains properties required for an Ant build:
x.props:
prop1=something
prop2=somethingElse
set in build.xml:
<property file="x.props" />
The properties contained in x.props are then used in a path task:
<path id="project.class.path">
<pathelement location="${prop1}/important.jar"/>
<pathelement location="${prop2}/anotherImportant.jar"/>
</path>
Before compilation starts. I don't explicitly create these properties in build.xml
The x.props file can be different for each local user, but for server builds it doesn't change.
I created an x.props.template file to address the problem of users accidentally checking in or updating this file (but they need to be able to check it out). I want to be able to create an x.props file from the x.props.template (I set x.props as svn:ignore).
Users can save the template file as x.props and edit it and - theoretically, the server Ant build.xml can copy the template file to the server x.props if it doesn't exist.
But that's not happening. I tried using a target:
<target name="x-props-file" unless="prop1" description="create a
local.properties file if it doesn't exist">
<copy file="x.props.template" tofile="x.props" />
</target>
But it's called AFTER the path is set.
I tried creating the file as a condition:
<condition available="x.props">
<not>
<copy file="x.props.template" tofile="x.props" />
</not>
</condition>
But 'not' and 'condition' don't work with copy.
loadProperties will fail if the file isn't found - but it won't copy a file.
Ideally I'd like to be able to copy the new x.props right after the initial file load fails.
Is there any way around this?
ant version 1.1
java 7
Thanks
This would probably be simplest with ant-contrib's <if> task:
<if>
<not>
<available file="x.props" />
</not>
<then>
<copy file="x.props.template" tofile="x.props" />
</then>
</if>
Edit: I just rediscovered this answer that I gave years ago after a comment was added, and realized that there's a much better solution that doesn't rely on ant-contrib. It's probably way too late to be of much use to the original poster, but I figured I'd offer it up anyway in case it helps someone:
<property file="x.props" />
<property name="prop1" value="something" />
<property name="prop1" value="somethingElse" />
<path id="project.class.path">
<pathelement location="${prop1}/important.jar"/>
<pathelement location="${prop2}/anotherImportant.jar"/>
</path>
No need for an extra template file. Just attempt to load the property file first and set your defaults immediately after that, making use of Ant's inherent property immutability.
Conversely, if you really want to use a separate properties file to hold your default values, just do the same thing as above but replace the individual property assignments with another property file load:
<property file="x.props" />
<property file="default.props" />
I have problem testing file existence with ant. I want to check if files exist in target test, and if not, I want download files in target download. But the download target will be executed always (if files exist or not). Can anybody show what is wrong?
<!-- Test lib files if exist -->
<target name="test">
<condition property="is.resource.exists" value="true" else="false">
<and>
<resourceexists>
<file file="${lib}/jdom-2.0.5.jar" />
</resourceexists>
<resourceexists>
<file file="${lib}/miglayout-4.0-swing.jar" />
</resourceexists>
</and>
</condition>
</target>
<!-- Download lib files if not exist -->
<target name="download" if="is.resource.exists" depends="test">
<exec dir="${lib}" executable="${lib}/get-libs.sh" />
</target>
A <target> with an if attribute will execute if the property in the if attribute exists. Similarly, a <target> with an unless attribute will execute if the property in the unless attribute doesn't exist. It doesn't matter what the value of the property is: true, false, kumquat, or whatever.
Replace the if="is.resource.exists" with unless="is.resource.exists" and you should be good.
Can I build multiple projects from one build-file. Example:
<project basedir="." default="all" name="app1">
...
</project>
<project basedir="." default="all" name="app2">
...
</project>
Currently I type ant -f build1.xml compile and it builds my application and I have to use two separate build files. Is there some way to get it running in a way that i have both the projects defined a common build-file and I can type something like ant app1 compile or ant app2 compile?
Here's what my build-file looks like:
<?xml version="1.0" encoding="UTF-8"?>
<project name="azebooster" default="dist" basedir=".">
<!-- Globals -->
<property name="src" location="src/com/aelitis"/>
<property name="build" location="build/azebooster"/>
<property name="jar" location="jar/azebooster"/>
<property name="resources" location="res/azebooster"/>
<!-- Paths -->
<path id="classpath">
<fileset dir="." includes="**/*.jar"/>
</path>
<!-- Start it -->
<target name="init">
<tstamp/>
<mkdir dir="${build}"/>
<mkdir dir="${jar}"/>
</target>
<!-- Build it -->
<target name="compile" depends="init" description="compile the source" >
<javac srcdir="${src}" destdir="${build}">
<classpath>
<path refid="classpath"/>
</classpath>
</javac>
</target>
<!-- Jar it -->
<target name="jar" depends="compile">
<jar destfile="${jar}/${ant.project.name}.jar">
<fileset dir="${build}"/>
<fileset dir="${resources}" />
</jar>
</target>
<!-- Clean it -->
<target name="clean" description="clean up" >
<tstamp/>
<delete dir="${build}"/>
<delete dir="${jar}"/>
</target>
</project>
Thank you.
Yes you can create a default.build file (in this way you don't need to specify the file, because it's used by default). On it you can create the following targets:
<target name="all" depends="app1, app2" />
<target name="app1">
<ant antfile=<app1file> target="compile" />
</target>
<target name="app2">
<ant antfile=<app2file> target="compile" />
</target>
On this way you can use both ant file from one unique file.
And you can do all in only one file, if you replace the app1 and app2 targets, with the needed targets to compile them that you have in the separate files.
EDITED:
You have different ways to include both of them in only one file, maybe the easiest one is include a suffix for each project on each target. And you can call the specific project target or the target for both.
I put you an example with the compile target (and for init target too).
You can use compile for compile both projects (I call the other project other), and compileazeboster to compile the azeboster project.
You can search the common things to avoid the innecesary duplicated code (common paths, targets and so on)
<property name="srcazebooster" location="src/com/aelitis"/>
<property name="buildazebooster" location="build/azebooster"/>
<property name="jarazebooster" location="jar/azebooster"/>
<property name="srcother" location="src/other"/>
<property name="buildother" location="build/other"/>
<property name="jarother" location="jar/other"/>
<!-- Start it -->
<target name="init" depends="initazebooster, initother"/>
<!-- Build it -->
<target name="compile" depends="compileazebooster, compileother" description="compile the source for all" />
<!-- Start azebooster-->
<target name="initazebooster">
<tstamp/>
<mkdir dir="${buildazebooster}"/>
<mkdir dir="${jarazebooster}"/>
</target>
<!-- Build azeboster-->
<target name="compileazebooster" depends="initazebooster" description="compile the source for azebooster" >
<javac srcdir="${srcazebooster}" destdir="${buildazebooster}">
<classpath>
<path refid="classpath"/>
</classpath>
</javac>
</target>
<!-- Start other-->
<target name="initother">
<tstamp/>
<mkdir dir="${buildotherr}"/>
<mkdir dir="${jarother}"/>
</target>
<!-- Build other-->
<target name="compileother" depends="initother" description="compile the source for other" >
<javac srcdir="${srcother}" destdir="${buildother}">
<classpath>
<path refid="classpath"/>
</classpath>
</javac>
</target>
You will probably be able to do what you want using macros (though it depends precisely on what is common between your two projects), though your command is more likely to be
ant compile app1
or
ant compile app2
where compile is a target which calls a macro, using app1/app2 as a parameter to either decide which macro to call or to pass into the macro itself.
I would like to add to the excellent answer of Borja some important steps.
How to organize the common ant files?
Let's say we have some big Project consisting of many Eclipse projects. All of them are in a worspace folder. Thus, the workspace itself makes the global Project. (Notice P/p difference). Very often you already have an Ant build file in the workspace folder. Or you have created the common ant files (build and properties) in it by yourself.
Later you want to launch that global build file. How? Do you want to go into the workspace folder, change to the command line or shell window and run the ant from there, having the output in the external console and switching from Eclipse to that window and back? And the same problem for editing? Having two additional windows? No, surely you want to have all windows, editing and output, in Eclipse. But how can we reference those global build files from inside the Eclipse?
Go to Package Explorer.
Make an empty project(not Java one), let's name it _Global (we want to see it always on the top).
Right click on its name. Choose Import -> General -> File System.
Press Advanced. Check Create links in Workspace, Create virtual folders, create link locations. The last choose for WORKSPACE_LOC.
In From Directory go to the workspace or where you have created the common build. After all, it could be even the common one for several workspaces.
You will see a dialogue with file names on the right with checkfields. Check the files you need. (You will need to import every new common file you created thereafter).
Finish.
Now you see your project with references to the global files. As for properties files, you are ready. But for build files you need some more steps:
Right click your global build file, -> Run -> Run Configurations. You are in the Ant Build group of configurations.
Press the New Launch Configuration button with plus on it (above the launch configurations list). Now you have the run configuration for that global build.
Set its parameters and run/debug it.
I want to delete the directory if the property "delete-compiled-dir" is set to true. If the property is false then do not execute it. Right now I have
<target name="deleted-after-compilation" depends="compile,jar">
<condition property="${delete-compiled-dir}" value="true">
<delete dir="${compilation-dir}" />
</condition>
<echo> Deleting Compiled Directory Classes </echo>
</target>
I get the error message :
condition doesn't support the nested "delete" element.
You can add the condition to your target using if (see manual).
The target will only be executed when the property compilation-dir is set (to any value, e.g. false).
<target name="deleted-after-compilation" depends="compile,jar"
if="${compilation-dir}">
<delete dir="${compilation-dir}" />
<echo> Deleting Compiled Directory Classes </echo>
</target>
To only execute it when a property is set to true, you need to set another property first and check this one in the if. You could add both as dependency the another target:
<target name="set-delete-property">
<condition property="delete-compilation-dir">
<istrue value="${compilation-dir}"/>
</condition>
</target>
<target name="deleted-after-compilation"
depends="compile,jar" if="${compilation-dir}">
....
<target name="some-target"
depends="set-delete-property,deleted-after-compilation">
</target>
There are a few ways to do this:
Use conditions on the target entity
Targets can contain if and unless conditions. The target will execute depending whether or not the property is set. (Not set to true, just set). This is a common way to see if you need to do something or not:
<target name="deleted.after.compilation"
if="delete.compiled.dir"
depends="jar">
<delete dir="${compilation-dir}" />
<echo> Deleting Compiled Directory Classes </echo>
</target>
You can set the property on the command line:
$ ant -Ddelete.compiled.dir all
Note: I use periods as separators for the names of properties and targets. Also note that I only depend upon the target jar since jar is also dependent upon compile, there's no need to have them both.
Use Ant's 1.9.1 conditional clauses
As of Ant 1.9.1, Ant has conditional attributes that can be added to tasks. You need to add a Namepsace declaration in your <project> entity:
<project ...
xmlns:if="ant:if"
xmlns:unless="ant:unless">
<target name="deleted.after.compilation"
depends="jar">
<delete dir="${compilation-dir}" if:true="${delete.compiled.dir}"/>
<echo if:true="${delete.compiled.dir}"> Deleting Compiled Directory Classes </echo>
</target>
Use Ant-Contrib's If Statement
Ha ha, that wacky Ant-Contrib library. No one knows who maintains it, and it hasn't been touched in years, but many people depend so heavily on it.
<project ...>
<taskdef resource="net/sf/antcontrib/antlib.xml">
<classpath>
<fileset dir="${ivy.dir}/antcontrib">
<include name="ant-contrib*.jar"/>
</fileset>
</classpath>
</taskdef>
<target name="deleted.after.compilation"
depends="jar">
<if>
<istrue value="${delete.compiled.dir}"/>
<then>
<delete dir="${compilation-dir}"/>
<echo>Deleting Compiled Directory Classes </echo>
</then?
</if>
</target>
You can see why Ant-Contrib is popular. It contains a lot of power, and we all know it. Plus, if someone is still using Ant 1.8 or 1.7, this will still work.
if you have get the property ,you can just use it in a target.
<target name="delete" if="${delete-compiled-dir}">
<delete dir="${compilation-dir}" />
</target>
As of Ant 1.9.1, you can use conditionals on any task. Described here.
Add this namespace to your project element:
<project name="yourproject" xmlns:if="ant:if">
Then add this to your delete:
<delete dir="${compilation-dir}" if:true="${delete-compiled-dir}"/>