How can I exclude sources in a javac task in ant? - java

I have the following in my build.xml:
<target name="compile.baz" depends="init">
<javac destdir="${build.dir}/classes" debug="on">
<compilerarg value="-Xlint:deprecation"/>
<src>
<pathelement location="${src.dir}/com/foo/bar/baz/" />
<pathelement location="${src.dir}/com/foo/bar/quux/" />
<!-- Need to exclude ${src.dir}/com/foo/bar/quux/dontwant/ -->
</src>
<classpath refid="classpath.jars" />
</javac>
...
</target>
This mostly does what I want, except that (as the comment says) I do not want the files in
${src.dir}/com/foo/bar/quux/dontwant/ to be compiled by this task (but I do want everything else under ${src.dir}/com/foo/bar/quux/ to be compiled in this task).
I'm a complete ant n00b, and the documentation hasn't been much help to me. I see several places where it says there are various exclude/excludes elements/attributes, but every variation I can think of either has no effect or results in an error like "blah doesn't support the 'exclude' attribute".

A couple of people suggested using <exclude>. This didn't work with the way my task was specified. trashgod's answer linked to the sixth example on this page which gave me an idea of how to restructure my task specification.
It looks like my problem was related to the way I was specifying the source files. Rather than using <pathelement> elements in a <src>, like this:
<src>
<pathelement location="${src.dir}/com/foo/bar/baz/" />
<pathelement location="${src.dir}/com/foo/bar/quux/" />
</src>
I switched to using a single <src> with a path and then a set of <include> elements, like this:
<src path="${src.dir}" />
<include name="com/foo/bar/baz/**" />
<include name="com/foo/bar/quux/**" />
This appears to be functionally identical, but is compatible with the use of <exclude>:
<exclude name="${src.dir}/com/foo/bar/quux/dontwant/**"/>
(Actually, I'm surprised that what was there in the first place worked at all.)

From my experiments you should not include full path for file you want to exclude.
This one doesn't work:
<javac>
(...>
<exclude name="${src.dir}/com/foo/blah/blah1/FILENAME.java"/>
(...)
</javac>
but this one does:
<javac>
(...>
<exclude name="com/foo/blah/blah1/FILENAME.java"/>
(...)
</javac>

Try
<javac>
(...>
<exclude name="${src.dir}/com/foo/bar/quux/dontwant/*" />
(...)
</javac>

I'm not sure about the rest, but the <exclude/> nested element should work in the Javac task. See the sixth example down.
Addendum: Patterns, including the ** notation, are discussed in Directory-based Tasks.
<target name="compile.baz" depends="init">
<javac destdir="${build.dir}/classes" debug="on">
<compilerarg value="-Xlint:deprecation"/>
<src>
<pathelement location="${src.dir}/com/foo/bar/baz/" />
<pathelement location="${src.dir}/com/foo/bar/quux/" />
</src>
<exclude name="${src.dir}/com/foo/bar/quux/dontwant/**"/>
...
</javac>
...
</target>

If you are trying to exclude Java classes but Ant is still trying to compile them then this may be due to references to these classes in your code.
If A.java has a reference to B.java and you try to exclude B.java then compiling A.java will require that B.java is compiled too.
This is one reason for interfaces in Java, so you can compile the interface without needing to compile the implementations.

try
folder "test" under {source.dir} would not be complied
<javac destdir="${compile.dir}" ...>
<src path="${source.dir}" />
<exclude name="test/**"/>
</javac>

Related

When are Ant path references set?

When I use a path reference ID, Ant seems to evaluate any variables inside the definition before any tasks run. For example, ${common.dist} and ${common.lib} below seem to be evaluated before any tasks run.
<path id="compile.classpath">
<fileset dir="lib">
<include name="*.jar" />
</fileset>
<fileset dir="${common.dist}">
<include name="*.jar" />
</fileset>
<fileset dir="${common.lib}">
<include name="*.jar" />
</fileset>
</path>
In the Ant output I see something like this:
Adding reference: compile.classpath
Property "common.dist" has not been set
Property "common.lib" has not been set
...
Build sequence for target(s) `package' is [...]
Complete build sequence is [...]
This makes it seem like the path reference is being processed before any targets are run.
I have a compile target like this:
<target name="compile" depends="init,common">
<javac destdir="build/classes" debug="true" deprecation="true" optimize="true">
<src path="src/java" />
<classpath>
<path refid="compile.classpath" />
</classpath>
</javac>
</target>
If I copy the guts of the path reference into the classpath element inside the compile target, things seem to work fine.
Any tasks outside a target are executed on every build, in order of appearance in the build.xml, before any targets are run. If you want to use properties in a <path> defined outside a target then you need to put the <property> task that defines the properties also outside a target, and before the <path>. If you need to load the properties within a target then you'll have to put the <path> definition inside a target too (either the same one or one that runs after the one defining the properties).
See this question (and my answer) for more details.
The answer is in the Ant manual - path like structures:
By default a path like structure will re-evaluate all nested resource
collections whenever it is used, which may lead to unnecessary
re-scanning of the filesystem ...
I think you maybe forgot to set the ${common.dist} and ${common.lib} properties. They should be outside any target:
<property name="common.dist" location="dist"/>
<property name="common.lib" location="lib"/>

Getting ant to run java file

I am having trouble just creating something simple, and it does not seem that any website is clear on how to do this, and honestly I think it should be simple.
I have a bunch of java files for a project. I want to compile all of them, and then run each file with specific arguments.
Basically I want the order of operations to be something like this
javac prob1.java
javac prob2.java
java prob1 parameter
java prob2 parameter
But I want that in ant (build.xml).
I can do the compile part just fine with
<project default="compile">
<target name="compile">
<javac srcdir="." />
</target>
</project>
I just can not get it to run say prob1 with an argument. I imagine this is extremely easy, but every solution I have found, does not seem to work. Also note prob1.class and prob2.class are in the same directory.
This should work:
<target name="run">
<java classname="prob1">
<classpath>
<pathelement location="."/>
</classpath>
<arg value="parameter" />
</java>
<java classname="prob2">
<classpath>
<pathelement location="."/>
</classpath>
<arg value="parameter" />
</java>
</target>

Enforce compilation dependencies with Ant compiler tasks

There are certain compiler dependencies that are not allowed in our (Java) environment. We have two servers, call them Application and Process. We have three root Java packages, call them Application, Process, and Shared. Application and Process are not allowed to reference each other, but they can each reference Shared. Shared can reference any class in any of the other two packages. How can I enforce these dependencies with Ant? The problem, as you might guess, is that in our Eclipse based environment everything compiles successfully, but we've come across runtime errors where a class is not there (since we have multiple servers).
I have attempted quite a few things but nothing has worked. See my current attempt below, where I have omitted irrelevant code for clarity. Comments are included.
<!--Compile the 'shared' directories. Since shared depends on Application and Process, we compile everything then delete Application and Process later. -->
<javac srcdir="${src.dir}" destdir="${build.dir}">
<classpath>
...
</classpath>
</javac>
<delete dir="${build.dir}/application" />
<delete dir="${build.dir}/process" />
<!--Compile the 'application' directories -->
<javac sourcepath="" srcdir="${src.dir}/application" destdir="${build.dir}">
<classpath>
<pathelement location="${build.dir}/shared" />
...
</classpath>
</javac>
<!--Compile the 'process' directories -->
<javac sourcepath="" srcdir="${src.dir}/process" destdir="${build.dir}">
<classpath>
<pathelement location="${build.dir}/shared" />
...
</classpath>
</javac>
you need to split shared into three parts, shared-standalone, shared-application and shared-process.
compile shared-standalone first,
compile shared-application together with application,
compile shared-process together with process.

Getting CLASSPATH from environment in ant build.xml

How can I get the CLASSPATH from the environment in a build.xml?
I've tried
<property environment="env"/>
<path id="classpath">
<pathelement location="${env.CLASSPATH}"/>
</path>
<target name="compile">
<javac includeantruntime="false">
<src path="${src}"/>
<classpath refid="classpath"/>
</javac>
</target>
I have a feeling this is failing because ${env.CLASSPATH} is a colon-separated list.
How then, can I get my classpath? I was surprised when ant didn't use my environment's CLASSPATH.
EDIT:
I've found a quick solution, but the preferred method is to use a separate properties file like the example here http://www.java2s.com/Code/Java/Ant/Useseparatepropertyfile.htm
Solution is, add
<property name="build.sysclasspath" value="first"/>
to the top of the build.xml
Yes, it's failing because it's a colon-separated list. In general, it's considered a bad idea to specify the class-path externally and use it within Ant. This is because running the same Ant script on different machines may yield different results. Instead, you're better of specifying the class-path from within Ant.

build.xml ant question

I am getting the following exception when running an applet:
Exception in thread "AWT-EventQueue-4" java.lang.NoClassDefFoundError: ice/net/SnapshotCacheManager
but the file is inside the jar.
I searched online and found it might be related to the applet not looking in the current directory and i need to add .; to the CLASSPATH but i am not sure how to add it to the build.xml
Thanks
Doron
Edit: Finally I figured it out, it wasn't an ant problem or the build XML, I got this exception because I signed two jars containing the same package differently, so there was a collision, not a very informative exception....
it might be useful to see what is in your current build.xml file, but the section you probably want to look at is the <target> element specifically the <src path> and <fileset> elements. Here is a VERY rough example with some guiding variables.
<property name="classes.home" value="/myproject/src"/>
<target name="compile_myproject" depends="clean">
<javac destdir="${classes.home}" debug="off" optimize="on" deprecation="on">
<classpath>
<fileset dir="/location/of/jars/">
<include name="*.jar"/>
<exclude name="jar-I-dont-want.jar"/>
</fileset>
<fileset dir="/location/of/axis2/jars">
<include name="**/*.jar"/>
</fileset>
</classpath>
<src path="${classes.home}"/>
<include name="/test/**/*.java"/>
<include name="other/location/*.java"/>
<exclude name="/debug/and/useless/files/**/*.java"/>
</javac>
</target>
note that ${classes.home} is a special variable defined at the top of the build.xml file. Many variables can be used to make things easier and specify relative paths.

Categories

Resources