<section xmlns="http://docbook.org/ns/docbook"
         xmlns:xlink="http://www.w3.org/1999/xlink"
         xml:id="sec-language-java">

<title>Java</title>

<para>Ant-based Java packages are typically built from source as follows:

<programlisting>
stdenv.mkDerivation {
  name = "...";
  src = fetchurl { ... };

  buildInputs = [ jdk ant ];

  buildPhase = "ant";
}
</programlisting>

Note that <varname>jdk</varname> is an alias for the OpenJDK.</para>

<para>JAR files that are intended to be used by other packages should
be installed in <filename>$out/share/java</filename>.  The OpenJDK has
a stdenv setup hook that adds any JARs in the
<filename>share/java</filename> directories of the build inputs to the
<envar>CLASSPATH</envar> environment variable.  For instance, if the
package <literal>libfoo</literal> installs a JAR named
<filename>foo.jar</filename> in its <filename>share/java</filename>
directory, and another package declares the attribute

<programlisting>
buildInputs = [ jdk libfoo ];
</programlisting>

then <envar>CLASSPATH</envar> will be set to
<filename>/nix/store/...-libfoo/share/java/foo.jar</filename>.</para>

<para>Private JARs
should be installed in a location like
<filename>$out/share/<replaceable>package-name</replaceable></filename>.</para>

<para>If your Java package provides a program, you need to generate a
wrapper script to run it using the OpenJRE.  You can use
<literal>makeWrapper</literal> for this:

<programlisting>
buildInputs = [ makeWrapper ];

installPhase =
  ''
    mkdir -p $out/bin
    makeWrapper ${jre}/bin/java $out/bin/foo \
      --add-flags "-cp $out/share/java/foo.jar org.foo.Main"
  '';
</programlisting>

Note the use of <literal>jre</literal>, which is the part of the
OpenJDK package that contains the Java Runtime Environment.  By using
<literal>${jre}/bin/java</literal> instead of
<literal>${jdk}/bin/java</literal>, you prevent your package from
depending on the JDK at runtime.</para>

<para>It is possible to use a different Java compiler than
<command>javac</command> from the OpenJDK.  For instance, to use the
Eclipse Java Compiler:

<programlisting>
buildInputs = [ jre ant ecj ];
</programlisting>

(Note that here you don’t need the full JDK as an input, but just the
JRE.)  The ECJ has a stdenv setup hook that sets some environment
variables to cause Ant to use ECJ, but this doesn’t work with all Ant
files.  Similarly, you can use the GNU Java Compiler:

<programlisting>
buildInputs = [ gcj ant ];
</programlisting>

Here, Ant will automatically use <command>gij</command> (the GNU Java
Runtime) instead of the OpenJRE.</para>

</section>

