# Java

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

    stdenv.mkDerivation {
      name = "...";
      src = fetchurl { ... };

      buildInputs = [ jdk ant ];

      buildPhase = "ant";
    }

Note that `jdk` is an alias for the OpenJDK.

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

    buildInputs = [ jdk libfoo ];

then `CLASSPATH` will be set to `/nix/store/...-libfoo/share/java/foo.jar`.

Private JARs should be installed in a location like `$out/share/package-name`.

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

    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"
      '';

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

It is possible to use a different Java compiler than `javac` from the OpenJDK. For instance, to use the Eclipse Java Compiler:

    buildInputs = [ jre ant ecj ];

(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:

    buildInputs = [ gcj ant ];

Here, Ant will automatically use `gij` (the GNU Java Runtime) instead of the OpenJRE.