I have a number of file/executable locations that are likely to be different depending on which computer I am running them on, and I would like to abstract these out through ant properties somehow. What's the best way to do this? Is there a system-wide ant setup script that gets called? Or can I make such a script?
In addition to Vladimir's solution you might have a default properties file for each of the OS or other you might deploy your build system on. Use the ${os.name} (and other Java system properties) to set up a path. For example
<property file="build-${os.name}.properties">
These files can be maintained and checked in into your version control system as well.
I use the more or less standard build.properties and build-local.properties files.
The first contains default values, common to all environments, the second only the exceptions. The first one is checked into subversion while the other is not.
EDIT : copy/pasting Akr's excellent idea
In addition you might have a default properties file for each of the OS or other you might deploy your build system on. These files can be checked in into your version control system as well.
The Ant script would then include all the files as follow (remember: in Ant the first definition wins):
<property file="build-local.properties"/>
<property file="build.properties"/>
<property file="build-${os.name}.properties">
Setup an ant build file called properties.xml, in which you should define the properties that you want to customize.
Here is properties.xml boilerplate I am using for my projects ( I've adapted it from one of the books on Ant ):
<?xml version="1.0" encoding="UTF-8"?>
<project
name="workspace-properties"
>
<dirname
property="workspace-properties.basedir"
file="${ant.file.workspace-properties}"
/>
<!--
==========================================================
Load Environment Variables
==========================================================
-->
<!-- #Load environment variables -->
<property environment="env" />
<!-- this is here to deal with the fact that an IntelliJ IDEA build
has no ant home
-->
<property
name="ant.home"
value="${env.ANT_HOME}"
/>
<!-- get Unix hostname, and set to Windows comparable name -->
<!-- #Trick to get host name x-platform -->
<property
name="env.COMPUTERNAME"
value="${env.HOSTNAME}"
/>
<!--
==========================================================
Load property files
Note: the ordering is VERY important.
==========================================================
-->
<!-- #Allow even users property file to relocate -->
<property
name="user.properties.file"
location="${user.home}/.build.properties"
/>
<!-- Load the application specific settings -->
<!-- #Project specific props -->
<property file="build.properties" />
<!--
==========================================================
Define your custom properties here.
You can overwrite them through build.properties and
${user.home}/.build.properties
==========================================================
-->
<property name="myexec1" location="/usr/bin/myexec1"/>
<property name="myexec2" location="/usr/bin/myexec2"/>
</project>
Important thing here is to come up with as many useful default property values as possible, then you may even never come up with custom build.properties files.
Then you just <import> this file in your project's build.xml.
<project
name="my-project"
>
<!-- this is done, so you may import my-project somewhere else -->
<dirname
property="my-project.basedir"
file="${ant.file.my-project}"
/>
<import file="${my-project.basedir}/relative/path/to/properties.xml"/>
<target name="using.myexec1">
<echo message="myexec1=${myexec1}"/>
</target>
</project>
If you want a custom value for myexec1 in my-project, just drop a custom flat build.properties file in the same directory where build.xml is located.
The build.properties file may look like this:
myexec1=c:/custom/path/to/myexec1.exe
Related
Let me first provide the background of the problem I'm facing.
I have a directory structure as below.
c:\myDirectory
c:\myDirectory\Project1
c:\myDirectory\Scripts
Under the c:\myDirectory\Scripts there is a script that download the source code (from svn) and creates the c:\myDirectory\Project1 directory.
I have another ant scripts ( c:\myDirectory\Scripts**compile-source.xml ) that compiles the Project1
from an ant script build.xml that is downloaded to c:\myDirectory\Project1
Snippet for c:\myDirectory\Scripts\compile-source.xml
<project name="compile" default="buildAll" basedir=".">
<property file=".\build.properties">
</property>
.......
<import file="${project.home.path}/${project.name}/build.xml"/>
<target name="buildAll">
<antcall target="jar-pack"/>
</target>
</project>
Snippet for c:\myDirectory\Project1\build.xml.
<project name="CommonFeatures" default="jar-pack" basedir=".">
<description>
A build file for the Common Features project
</description>
....
</project>
Note that the basedir for the project is set as "." for both the above ant scripts.
When I execute the script c:\myDirectory\Scripts\compile-source.xml from the c:\myDirectory\Scripts directory the target "jar-pack" present in the c:\myDirectory\Project1\build.xml gets executed.
However, the problem is that basedir attribude in build.xml ( basedir="." ) is the current working directory and in this case its c:\myDirectory\Scripts. Hence the script build.xml errors out since the basedir for build.xml is expected to be c:\myDirectory\Project1. The build.xml script would have worked, if basedir="." were set to "c:\myDirectory\Project1", but unfortunately build.xml file comes from the source code that is downloaded and I'm unable to edit.
So here's my question, Is it possible to do any of the following.
Override the value of the attribude basedir="." in build.xml when the is done in c:\myDirectory\Scripts\compile-source.xml ?
Is it possible to change the basedir in build.xml by any other mechanism so that the script c:\myDirectory\Project1\build.xml is executed under directory c:\myDirectory\Project1 ?
Any other way to resolve this issue?
Any help from Ant experts to overcome this issue is highly appreciated.
You can update basedir using subant task. Check this answer
Create the following build.xml file (assuming it is in Z:/any/folder):
<?xml version="1.0" encoding="UTF-8"?>
<project name="project">
<target name="mytarget">
<subant target="debug">
<property name="basedir" value="X:/any/dir/with/project"/>
<fileset dir="Y:/any/folder/with" includes="build.xml"/>
</subant>
</target>
</project>
The you can execute ant mytarget from Z:/any/folder
You can specifically reference the location of your build file, which is described in this stack overflow thread. This would allow you to get and use the directory your build file resides in as a reference point.
For your case the usage of the subant or ant tasks may be better suited, but nevertheless...
You can (but you should know/consider the side-effects!) extend ant with the common ant-contrib task definitions and use the var task which is able to override properties. Make sure to use the latest version (> 1.0b3).
<!-- adjust to your path and include it somewhere at the beginning of your project file -->
<taskdef resource="net/sf/antcontrib/antlib.xml" classpath="lib/ant-contrib-1.0b3.jar" />
<!-- works e.g. for basedir = /foo/bar to update it to /foo/bar/.. ~ /foo -->
<var name="basedir" value="${basedir}/.." />
update: but one has to be careful, because this does not change . (current working directory) (so <property name="x" location="tmp" /> would be relative to . and not to basedir anymore ; update: setting basedir outside of ant or via <project basedir= also sets . to basedir!). Here is some test target proving the effect on both:
<target name="tst.dummy.basedir-override">
<!-- example output:
tst.dummy.basedir-override:
[echo] basedir before: basedir=D:\tst, '.'=D:\tst\.
[echo] updating it via 'var' to '..'
[echo] basedir now: basedir=D:\tst/.., '.'=D:\tst\.
-->
<property name="cur" location="." /> <!-- makes the relative path absolute -->
<echo message="basedir before: basedir=${basedir}, '.'=${cur}" />
<echo message="updating it via 'var' to '..'" />
<var name="basedir" value="${basedir}/.." />
<property name="cur2" location="." /> <!-- makes the relative path absolute -->
<echo message="basedir now: basedir=${basedir}, '.'=${cur2}" />
</target>
I have a following directory structure
root_dir
fixed_dir
random_dir
subdir1
subdir2
subdir2.1
subdir3
subdir3.1
subdir3.2
In the ANT build file I know the root_dir, fixed_dir, and one directory that is either random_dir or a subdirectory below random_dir (subdirX). I need to determine the path of random_dir given some subdirX. Is it possible to find this directory in ANT and if so, how?
Here is a tested solution for finding the immediate subdirectory of a root directory that contains some subdirectory subdirX at any level of nesting given the file structure provided in the question.
<property name="root.dir" location="${basedir}/root_dir" />
<property name="subdirX" value="subdir2.1" />
<target name="find-immediate-subdir-of-root-containing-subdirX">
<dirset dir="${root.dir}" includes="**/${subdirX}" id="mydirset" />
<pathconvert property="random_dir" pathsep="${line.separator}" refid="mydirset">
<mapper type="regexp"
from="^(${root.dir}${file.separator}[^${file.separator}]+).*"
to="\1"/>
</pathconvert>
<echo message="${random_dir}" />
</target>
Output
find-immediate-subdir-of-root-containing-subdirX:
[echo] /ant/project/basedir/root_dir/random_dir
BUILD SUCCESSFUL
Total time: 1 second
With Ant addon Flaka you'll get the parent as property of a file object (see Flaka Manual, section 3.7.2, i.e.
<project xmlns:fl="antlib:it.haefelinger.flaka">
<!-- let standard ant tasks, i.e. echo
understand EL expresssions -->
<fl:install-property-handler />
<echo>#{file('${basedir}').parent}</echo>
<!-- or without fl:install-property-handler use fl:echo-->
<fl:echo>#{file('${basedir}').parent}</fl:echo>
</project>
so you would use :
#{file('${yoursubdir}').parent
I want create Ivy Ant tasks in xml editor in IDE (Intellij iDEA) with autocomplete based on xsd , but I cannot find xsd for register XML namespace xmlns:ivy="antlib:org.apache.ivy.ant"
Where I can find it?
I just copied the ivy jar to INTELLIJ_HOME/lib/ant and now intellij can resolve the ivy tasks.
Or import this ant file to your ant project, its actually the first ivy example in ivy documentation, make sure to always depend on install-ivy target, add your ant file to idea in the ant build window and you dont even have to install ivy and idea recognizes ivy tasks.
<property name="ivy.jar.dir" value="${user.home}/.ivy2/jars" />
<property name="ivy.jar.file" value="${ivy.jar.dir}/ivy.jar" />
<property name="ivy.install.version" value="2.2.0" />
<target name="check-ivy-installed" unless="INTERN-ivy.jar.exists">
<available property="INTERN-ivy.jar.exists" file="${ivy.jar.file}"/>
</target>
<target name="download-ivy" depends="check-ivy-installed" unless="INTERN-ivy.jar.exists">
<echo message="downloading and installing ivy"/>
<mkdir dir="${ivy.jar.dir}"/>
<!-- download Ivy from web site so that it can be used even without any special installation -->
<get src="http://repo1.maven.org/maven2/org/apache/ivy/ivy/${ivy.install.version}/ivy-${ivy.install.version}.jar"
dest="${ivy.jar.file}" usetimestamp="true"/>
<echo message="ivy installed"/>
</target>
<!-- =================================
target: install-ivy
this target is not necessary if you put ivy.jar in your ant lib directory
if you already have ivy in your ant lib, you can simply remove this
target and the dependency the 'go' target has on it
================================= -->
<target name="install-ivy" depends="download-ivy" description="--> install ivy">
<!-- try to load ivy here from local ivy dir, in case the user has not already dropped
it into ant's lib dir (note that the latter copy will always take precedence).
We will not fail as long as local lib dir exists (it may be empty) and
ivy is in at least one of ant's lib dir or the local lib dir. -->
<echo message="Installing ivy"/>
<path id="ivy.lib.path">
<fileset dir="${ivy.jar.dir}" includes="*.jar"/>
</path>
<taskdef resource="org/apache/ivy/ant/antlib.xml"
uri="antlib:org.apache.ivy.ant" classpathref="ivy.lib.path"/>
</target>
To complete Shalom's answer, the location where to add the ivy.jar for the IntelliJ IDEA Community Edition is INTELLIJ_HOME/lib/ant/lib (one more folder to go).
Maybe it also apply to the full version.
might be, there was no xsd in the past time this discussion started, but at least since may 2011 the ivy scheme is well documented at
http://ant.apache.org/ivy/schemas/ivy.xsd
which is linked right from the documentation in http://ant.apache.org/ivy/
so, to start over using the scheme, you just need:
<?xml version="1.0" encoding="UTF-8"?>
<project name="yourproject"
xmlns:ivy="antlib:org.apache.ivy.ant"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://ant.apache.org/ivy/schemas/ivy.xsd"
>
<!-- … -->
I guess this discussion might help you. It appears that there is no xsd for the ivy ant tasks, but Eclipse does autocomplete.
yes, no xsd for ivy ant tasks avialable. but i found the way to make autocomplete in Intellij IDEA
in ant build file need to define additional task:
<property name="ivy.jar.dir" value="C:/Apache/apache-ivy-2.2.0/"/>
<taskdef resource="org/apache/ivy/ant/antlib.xml"
uri="antlib:org.apache.ivy.ant">
<classpath>
<fileset dir="${ivy.jar.dir}" includes="*.jar"/>
</classpath>
</taskdef>
XML plugin for jEdit defines AntCompleteTask (ant task) that produces an xml file called ant-complete.xml. The resulting file looks as follows:
<element-list>
<!-- ... -->
<element name="classpath"
content="(fileset|dirset|extdirs|existing|filelist|pathelement|path)">
<attribute name="id" type="ID" />
<attribute name="location" type="CDATA" />
<attribute name="cache" type="(true|false|on|off|yes|no)" />
<attribute name="refid" type="CDATA" />
<attribute name="description" type="CDATA" />
<attribute name="path" type="CDATA" />
</element>
<!-- ... -->
The generated file may be downloaded as XML plugin archive. Open XML.jar and browse to xml/completion directory. It's syntax is defined in xml-completion-info.dtd.
The task code does not contain an explicit license, but it's at least GPL. Anyway you probably don't need to distribute that task, only to use it and this doesn't require any license.
I can't assess the usability of the resulting xml file, but jEdit uses it for autocompletion.
I'm building a Flex application that will need run under two different deployment scenarios:
First, the application will be hosted on the web. The SWF loads some external resources (images, text) so it requires network access, which is the Flex Builder 3 default build flag "-use-network=true". I don't need to do anything special; it just works.
Second, the application will be written to CD with autorun enabled to launch the index.html hosting the SWF. The SWF still needs to be able to load those same external resources, which reside on the CD in a subfolder. Since those files are on the CD, they are considered local, so Flash security requires the SWF to be built using a flag of "-use-network=false". I add that to the "Additional compiler arguments" text box found under "Flex Compiler" in the Flex project's Properties dialog.
That all works as expected, but it's tedious to have to manually modify the Flex Builder project settings to add or remove that flag as the case may be.
Ideally, I would like to just build the project once and have multiple output folders: one for the network deployment scenario, and another for the local deployment scenario.
What's the best way to do that? Is moving to an Ant build the way to go, or is there a simpler way? If an Ant build configuration is the correct way, do you have an example to share of such multiple build configurations?
Thanks for your help!
Once you get your head around the Ant build, it will make your life a lot easier. Building a multiple build file is no different from a single build file, you will just add an additional task inside of your build with the appropriate settings (you could also use a loop in ant, but that adds complexity)
So, expanding on the Flex Ant Tasks example from the docs, something like this should work (not-tested):
<?xml version="1.0" encoding="utf-8"?>
<!-- myMXMLCBuild.xml -->
<project name="My App Builder" basedir="." default="main">
<taskdef resource="flexTasks.tasks" classpath="${basedir}/flexTasks/lib/flexTasks.jar" />
<property name="FLEX_HOME" value="C:/flex/sdk"/>
<property name="APP_ROOT" value="apps"/>
<property name="DEPLOY_DIR" value="c:/jrun4/servers/default/default-war"/>
<target name="main" depends="clean, compile1, compile2">
</target>
<target name="compile1">
<mxmlc
file="${APP_ROOT}/Main.mxml"
output="${DEPLOY_DIR}/Main.swf"
actionscript-file-encoding="UTF-8"
keep-generated-actionscript="true"
incremental="true"
use-network="true"
>
<!-- Get default compiler options. -->
<load-config filename="${FLEX_HOME}/frameworks/flex-config.xml"/>
<!-- List of path elements that form the roots of ActionScript
class hierarchies. -->
<source-path path-element="${FLEX_HOME}/frameworks"/>
<!-- List of SWC files or directories that contain SWC files. -->
<compiler.library-path dir="${FLEX_HOME}/frameworks" append="true">
<include name="libs" />
<include name="../bundles/{locale}" />
</compiler.library-path>
<!-- Set size of output SWF file. -->
<default-size width="500" height="600" />
</mxmlc>
</target>
<target name="compile2">
<mxmlc
file="${APP_ROOT}/Main.mxml"
output="${CD_DEPLOY_DIR}/Main.swf"
actionscript-file-encoding="UTF-8"
keep-generated-actionscript="true"
incremental="true"
use-network="false"
>
<!-- Get default compiler options. -->
<load-config filename="${FLEX_HOME}/frameworks/flex-config.xml"/>
<!-- List of path elements that form the roots of ActionScript
class hierarchies. -->
<source-path path-element="${FLEX_HOME}/frameworks"/>
<!-- List of SWC files or directories that contain SWC files. -->
<compiler.library-path dir="${FLEX_HOME}/frameworks" append="true">
<include name="libs" />
<include name="../bundles/{locale}" />
</compiler.library-path>
<!-- Set size of output SWF file. -->
<default-size width="500" height="600" />
</mxmlc>
</target>
<target name="clean">
<delete dir="${APP_ROOT}/generated"/>
<delete>
<fileset dir="${DEPLOY_DIR}" includes="Main.swf"/>
</delete>
</target>
</project>
As a side note, if you are going to be running the Ant build in eclipse/Flash Builder you might as well increase the memory now.
I use in a project checkstyle and I have defined a SuppressionFilter in my checkstyle-configuration. I use Apache ant to make automatic builds via Continuous Integration.
My problems comes from the following situation: I don't want to fill to much files into the project-basedir, so the checkstyle.xml and the suppressions.xml are both in a subdirectory named conf (for configuration for build). Now Ant and Eclipse work differently for finding the suppressions.xml.
Ant use the project-basedir as basedir for finding the suppressions.xml, after I declared an ant-task to find the checkstyle.xml with the base-configuration of checkstyle. This checkstyle.xml now contains the following:
<module name="SuppressionFilter">
<property name="file" value="conf/suppressions.xml"/>
</module>
This way the ant-build finds the suppressions.xml, because the basedir of the build is the project-directory.
Now using the checkstyle-plugin for Eclipse brings a problem. It looks for the suppressions.xml starting with the path the checkstyle.xml has (conf). For Eclipse the declaration had to look like this, to work:
<module name="SuppressionFilter">
<property name="file" value="suppressions.xml"/>
</module>
EDIT: Even that doesn't work, Eclipse seems to need always an absolute path.
I want to know a way, that both Eclipse and Ant can work with the same checkstyle-configuration. Someone knows a solution to this problem? Absolute paths are no solution, because every developer and the CI-Server have different paths for the project-directory.
This question is pretty old, but I've found a better way to do it using the Checkstyle Advanced properties:
For the Eclipse Checkstyle plugin, the ${samedir} property expands to the directory that the configuration file is located within:
In your case, your module configuration would look like this:
<module name="SuppressionFilter">
<property name="file" value="${samedir}/conf/suppressions.xml" />
</module>
The Ant target would also set the samedir property:
<checkstyle config="${checkstyle.tool.dir}/checks.xml" failOnViolation="false">
<fileset dir="${src.dir}" includes="**/*.java" />
<property key="samedir" value="${checkstyle.tool.dir}/conf" />
</checkstyle>
Use Checkstyle's property expansion functionality. In your checkstyle.xml declare your SupressionFilter as:
<module name="SuppressionFilter">
<property name="file" value="${checkstyle.suppressions.file}" default="suppressions.xml"/>
</module>
Then modify your Checkstyle task in your Ant build script to include a nested property:
<checkstyle config="conf/checkstyle.xml">
<fileset dir="src" includes="**/*.java"/>
<property key="checkstyle.suppressions.file" value="conf/suppressions.xml"/>
</checkstyle>