I have an ant target that copies a file from one location to another, say it is defined in the build.xml as:
${project}/some-component-ABC/lib/whatever.jar
But on the file system the actual path is
${project}/some-component-abc/lib/whatever.jar
No uppercase ABC in some-component-abc on the fliesystem...
This path will resolve in Windows (7) but not in Linux?
Why?
I'll figure out what to do with it, just wanted some background why the functional difference.
Per the following article: https://ubuntuforums.org/showthread.php?t=1227827
Linux is written in C, which is case sensitive. It makes for faster sorting.
Ant doesn't do anything fancy with paths - it just delegates down to the underlying filesystem. Windows' filesystem is not case-sensitive, while any linux filesystem I can think of is. So, in windows, some-component-abc and some-component-ABC are the same directory, while in linux they would not be.
As others have mentioned, for the most part Ant just stores strings for everything and relies on the OS's filesystem when it actually comes time to perform filesystem operations, so you will run into differences like this when running scripts in Linux vs Windows.
However, Ant does have tasks that manipulate path-like strings, and these can be used to groom references to files prior to using them. Here's an example:
~/test $ ls -1
build.xml
FILE
build.xml:
<project>
<pathconvert property="file">
<fileset dir="${basedir}" includes="file" casesensitive="false" />
</pathconvert>
<echo message="${file}" />
</project>
Output:
[echo] /home/me/test/FILE
Alternative approach (will return a path-like string relative to the fileset's dir attribute):
<project>
<fileset dir="${basedir}" includes="file" casesensitive="false" id="filepath" />
<property name="file" refid="filepath" />
<echo message="${file}" />
</project>
Output:
[echo] FILE
Related
I am having little problem with fixcrlf from ant. When I try to compile for unix target with fixcrlf filter, it modifies all files in the target folder, no matter of includes and excludes. I expect it should not convert any files that are not in the includes patterns, or at least I could force some files to not be converted via excludes attribute. None of that I tried been able to exclude anything. Even some binary files are modified and as result screwed up.
According to fixcrlf documentation from apache site, these parameters should work like this:
includes: comma- or space-separated list of patterns of files that must be included.
excludes: comma- or space-separated list of patterns of files that must be excluded.
When I run ant with parameters -verbose and -debug, there is no information on that fixcrlf did.
<copy todir="target">
<fileset dir="source1"><exclude name="**/*.bak"/></fileset>
<fileset dir="source2"><exclude name="**/*.bak"/></fileset>
<filterchain>
<fixcrlf srcdir="${src}" includes="**/*.sh,**/*.properties" excludes="**/*.xml" eol="lf" />
</filterchain>
</copy>
I have to copy a file if a property is set in ant target, but I always get an error for this code:
<condition property="component.is.x">
<equals arg1="${COMPONENT_ID}" arg2="x" />
</condition>
<target name="copyschemaparamsfile" if="sql.file.present" >
<if>
<equals arg1="${component.is.x}" arg2="true" />
<then>
<copy file="${in.root}/schema/${COMPONENT_ID}-schema.sql"
tofile="${tmp.dir}/${COMPONENT_ID}/x/schema/schema.sql"
failonerror="false" />
</then>
<else>
<copy file="${inf.root}/schema/${COMPONENT_ID}-schema.sql"
tofile="${tmp.dir}/${COMPONENT_ID}/${COMPONENT_ID}/schema/schema.sql" failonerror="false" />
</else>
</if>
</target>
Error is:
Ant could not find the task or a class this task relies upon.
This is common and has a number of causes; the usual
solutions are to read the manual pages then download and
install needed JAR files, or fix the build file:
- You have misspelt 'if'.
Fix: check your spelling.
- The task needs an external JAR file to execute
and this is not found at the right place in the classpath.
Fix: check the documentation for dependencies.
Fix: declare the task.
- The task is an Ant optional task and the JAR file and/or libraries
implementing the functionality were not found at the time you
yourself built your installation of Ant from the Ant sources.
Fix: Look in the ANT_HOME/lib for the 'ant-' JAR corresponding to the
task and make sure it contains more than merely a META-INF/MANIFEST.MF.
If all it contains is the manifest, then rebuild Ant with the needed
libraries present in ${ant.home}/lib/optional/ , or alternatively,
download a pre-built release version from apache.org
- The build file was written for a later version of Ant
Fix: upgrade to at least the latest release version of Ant
- The task is not an Ant core or optional task
and needs to be declared using <taskdef>.
- You are attempting to use a task defined using
<presetdef> or <macrodef> but have spelt wrong or not
defined it at the point of use
Remember that for JAR files to be visible to Ant tasks implemented
in ANT_HOME/lib, the files must be in the same directory or on the
classpath
I am always getting above error when I execute. Can someone please suggest how to check for a parameter and copy from one directory to other within an ant target?
Ant <if/> is part of Ant-Contrib. To use, follow the directions on the Ant-Contrib Tasks installation page:
(1) Copy ant-contrib-0.3.jar to the lib directory of your Ant
installation. If you want to use one of the tasks in your own project,
add the lines
<taskdef resource="net/sf/antcontrib/antcontrib.properties"/>
to your build file.
(2) Keep ant-contrib-0.3.jar in a separate location. You now have to
tell Ant explicitly where to find it (say in /usr/share/java/lib):
<taskdef resource="net/sf/antcontrib/antcontrib.properties">
<classpath>
<pathelement location="/usr/share/java/lib/ant-contrib-0.3.jar"/>
</classpath>
</taskdef>
I have several files scattered across several packages. I need to load the file one by one and perform operations using ANT but whenever I try, only one file gets loaded. For ex. I have 2 classes - com.abc.one.One and com.bcd.two.Two . The following script print both file name but only the first file as loaded file in both loop iterations
<target name="build" description="My Task">
<for param="file">
<path>
<fileset dir="C:\workspace\AntTest1" includes="**\*.java" />
</path>
<sequential>
<echo message="#{file}" />
<loadfile property="loadedFile" srcfile="#{file}" />
<echo message="${loadedFile}" />
</sequential>
</for>
</target>
I have tried searching the documentation but could not find the concise explanation on how to use loadfile task. I suspected that this might be because ant uses immutable string but could not get workaround. I tried to split the job by creating new target but that does not help me either. Any help is highly appreciated
Ant property can only be set once, and after it is set, it is immutable.
It has been some time since my Ant days, but perhaps the following solution can work: For each file, make an antcall call, with the file name as parameter. then, in the new target, load the file and perform your task. Notice that antcall can impact severely the runtime performance.
I was running Selenium unit tests in TestNG with the Ant Java task like so:
<java classpathref="runtime.classpath"
classname="org.testng.TestNG"
failonerror="false">
<arg value="-d" />
<arg value="${grid.location}/target/reports" />
<arg value="${lib.location}/testng.xml"/>
</java>
runtime.classpath is a pathlike structure that included <pathelement path="${basedir}/target/classes/" />, which I thought was needed to let TestNG know which classes to run.
<path id="runtime.classpath">
...
<!-- Target classes -->
<pathelement path="${basedir}/target/classes/" />
</path>
However, I kept seeing in the log that TestNG found 0 applicable classes.
I eventually got some help from a colleague and it appears this was the key change:
<path id="runtime.classpath">
...
<!-- path attribute changed to location -->
<pathelement location="${basedir}/target/classes/" />
</path>
This also pulls in the test classes correctly:
<java classpathref="runtime.classpath"
classname="org.testng.TestNG"
failonerror="false">
<arg value="-d" />
<arg value="${grid.location}/target/reports" />
<arg value="${lib.location}/testng.xml"/>
<classpath>
<pathelement location="${basedir}/target/classes/" />
</classpath>
</java>
What is the difference between the path and location attributes? I've looked at Writing a Simple Buildfile (specifically the Path-like Structures section), but in that manual it looks to me like location is more specific than path. That doesn't appear to be the case empirically, but I can't quite figure out why.
It looks like the difference between path and location is many entries vs one. A location is a file or directory, a path can be a list.
From the manual
The location attribute specifies a single file or directory relative
to the project's base directory (or an absolute filename), while the
path attribute accepts colon- or semicolon-separated lists of
locations. The path attribute is intended to be used with predefined
paths - in any other case, multiple elements with location attributes
should be preferred.
Note that the JVM used by ant has just about no relation to the JVM used by the java task. By default the environment of ant isn't the same as that of things started with the java task via ant. This is actually helpful when you want to use a different JVM from the one ant wants to use and makes things explicit, helping avoid surprises later on.
Check out the docs for the java task, particularly clonevm
clonevm: If set to true, then all system properties and the
bootclasspath of the forked Java Virtual Machine will be the same as
those of the Java VM running Ant. Default is "false" (ignored if fork
is disabled). since Ant 1.7
I'm trying to create a comma-delimited list of files or directories under the current directory. For instance, suppose I have the following folder structure:
Root
-- Directory1
-- Directory2
...
I want to generate a variable or property that contain "Directory1,Directory2." I've tried iterating (using ant-contrib "for" task) over a <dirset dir="." includes="*">, but this generates absolute paths; I've then extracted the file names using the "basename" task, however that in turn generates an output property. Since properties are immutable, what I get in practice is "Directory1,Directory1,..."
Is there a saner way of doing this, or will I have to write a Java extension to do this for me?
The pathconvert task can be used to format a dirset with arbitrary separators:
<dirset id="dirs" dir="." includes="*"/>
<pathconvert dirsep="/" pathsep="," property="dirs" refid="dirs"/>
<echo message="${dirs}"/>
Just confirming Jörn's answer was exactly what I needed (as a starting point) as well.
<dirset id="dirset.sandbox" dir="${sandbox.dir}" includes="*">
<exclude name="output"/>
</dirset>
<pathconvert pathsep=" " property="dirs.sandbox" refid="dirset.sandbox">
<mapper type="flatten"/>
</pathconvert>
<echo message="[*** the sandbox dir list is ${dirs.sandbox} ***]"/>
sandbox.dir is an absolute path similar to /root/build/workspace and contains several subdirectories.
The output is a space-separated list of those directories.