Reputation: 19968
Consider the following project layout (assuming A and B depend on each other):
.
|-- bin1
|-- bin2
|-- src1
| `-- A.java
`-- src2
`-- B.java
After compilation, I want the classes to reside in their respective folders liike this:
.
|-- bin1
| `-- A.class
|-- bin2
| `-- B.class
|-- src1
| `-- A.java
`-- src2
`-- B.java
This is quite simple from the command line:
$ javac -implicit:none -sourcepath src1:src2 -d bin1 src1/*
$ javac -implicit:none -sourcepath src1:src2 -d bin2 src2/*
Eclipse also does it that way if so configured. But I cannot figure out how to do it with Ant.
Appendix: My current javac
tasks:
<javac destdir="${classes.1.dir}">
<src path="${src.1.dir}" />
<src path="${src.2.dir}" />
</javac>
<javac destdir="${classes.2.dir}">
<classpath path="${classes.1.dir}" />
<src path="${src.2.dir}" />
</javac>
Note the circular dependency. The second task works well, it only compiles what’s in src2
as it has a classpath
dependency on the other build. The first task, however, cannot take a classpath
, since nothing is yet compiled, and with src
it of course compiles too much.
Upvotes: 5
Views: 14513
Reputation: 33
Here is what works for me when dealing with complex source trees with no duplicate compilation. The key is how you build and reference the paths.
<path id="src.separate.java.path">
<pathelement path="separate-src1/java" />
<pathelement path="separate-src2/java" />
</path>
<property name="src.separate.java.path" refid="src.separate.java.path" />
<path id="src.java.path">
<pathelement path="src1/java" />
<pathelement path="src2/java" />
<pathelement path="src3/java" />
</path>
<property name="src.java.path" refid="src.java.path" />
<path id="src.java.all.path">
<path refid="src.separate.java.path" />
<path refid="src.java.path" />
</path>
<property name="src.java.all.path" refid="src.java.all.path" />
<target name="compile-java">
<mkdir dir="${separate.classes.dir}" />
<javac srcdir="${src.separate.java.path}" sourcepath="${src.java.all.path}" destdir="${separate.classes.dir}">
<classpath refid="project.class.path" />
<compilerarg value="-implicit:none"/>
</javac>
<mkdir dir="${build.classes.dir}" />
<javac srcdir="${src.java.path}" sourcepath="${src.java.all.path}" destdir="${build.classes.dir}">
<classpath refid="project.class.path"/>
<compilerarg value="-implicit:none"/>
</javac>
</target>
In order for this to work the source paths need to be made up of <pathelement>
s. If you use <fileset>
s the srcdir
attribute for javac will choke on the path. You also need to expand the path into a property for srcdir
and sourcepath
to be able to use it.
So srcdir
is the path to the source to compile and sourcepath
is the path to all source the compiler needs to do resolve references. <compilerarg value="-implicit:none"/>
tells the compiler to not generate class files for implicitly loaded source.
Of course you can do the same thing using nested <src>
elements in javac instead of the <path>
s and <property>
s, but that will force you to list your source paths twice.
Upvotes: 2
Reputation: 5010
I had the same problem. And i found some pretty easy solution.
You just need to specify several source foulders in srcdir
attribute in javac
task. And you should not specify destdir
attribute.
Something like this:
<javac srcdir="src1:src2" />
All the binaries (.class files) will be placed in the same places as sources. So the structure of the class files will be exactly the same. Then you can move all *.class to the separate place, so they won't be stored in the source foulders.
And no double compilation as in Kurt Kaylor's example.
Upvotes: 9
Reputation:
This is extremely ugly and needs some cleaning, but it should do what your looking for
<target name="compile" depends="clean,init" description="Compiles all source files.">
<mkdir dir="temp"/>
<javac srcdir="src1" sourcepath="src2" destdir="temp">
<classpath>
<fileset dir="lib">
<include name="**/*.jar"/>
</fileset>
</classpath>
</javac>
<javac srcdir="src2" sourcepath="src1" destdir="temp">
<classpath>
<fileset dir="lib">
<include name="**/*.jar"/>
</fileset>
</classpath>
</javac>
<javac srcdir="src1" destdir="bin1">
<classpath>
<fileset dir="lib">
<include name="**/*.jar"/>
</fileset>
<pathelement location="temp"/>
</classpath>
</javac>
<javac srcdir="src2" destdir="bin2">
<classpath>
<fileset dir="lib">
<include name="**/*.jar"/>
</fileset>
<pathelement location="temp"/>
</classpath>
</javac>
<delete dir="temp"/>
</target>
Upvotes: 2