Jarc: a jar file compiler

Using the “make” tool to build a jar file was never a good option, mostly because Java files are different from C/C++ files. Today most people use Ant but I never liked it so around 2002 I started writing a tool that would permit to build a jar file in one step. I had two requirements in mind: First the tool had to be faster than running javac and jar – at the time the JVM was really slow, so I used zip and jikes, at least until IBM stopped updating jikes.

The second requirement was to compile only the Java files that were necessary to build the jar file, the idea been to give to the jar tool only the name of the “root” Java classes, and let it figure out the dependencies (I am not an Ant specialist but it seems to me that Ant is still not capable of doing this correctly). What was missing was a convenient way of passing the list of “root” classes to the tools, and this is when I thought of using the manifest file for this.

A manifest file is a text file stored inside the META-INF directory of the jar file. This file contains the meta-information about the jar file and is generated by the jar tool. The idea was to invert the process – instead of having the jar tool generating this manifest file from the command line parameters, why not use this file as the source of the information needed to build a jar file?

The jarc tool (jar compiler) takes as input one or more manifest files, parses the content and tries to build a jar file of same name. The tool will use the class names found in the manifest file as the “root” classes to use as dependencies. A manifest file looks like this:

Manifest-Version: 1.0
Class-Path: /usr/share/java/jspeex.jar
Main-Class: org.implementers.apps.Main

Name: org/implementers/apps/Main.class

Name: org/implementers/apps/resources/schema.xsd

If this text is stored in a file named apps.mf, then running “jarc apps” will build a jar file named apps.jar by executing the following steps:

  • The org.implementers.apps.Main class will be compiled together with all the classes that depends on it. The content of the Class-Path attribute is passed to the compiler as if a -classpath option was used.
  • The org/implementers/apps/resources/schema.xsd file will be copied from the disk to the jar file.
  • The manifest file itself will be filtered and copied inside the jar file.
  • A short bash program will be generated to call the class described in the Main-Class attribute

There is also some attributes that can be added in the manifest to drive the build. One example is the X-Jarc-Service that can be added to an entry to declare it as a service as shown in the following example:

Name: org/implementers/nio/channels/spi/CompositeProvider.class
X-Jarc-Service: java.nio.channels.spi.SelectorProvider

When jarc reads this line, it generates in the jar file a service file in META-INF/services.

The tools is accessible on the following Debian repository (see a previous post on this blog for the explanation on how to configure Ubuntu or Debian):

deb http://debian.implementers.org/ testing/$(ARCH)/
deb http://debian.implementers.org/ testing/all/
deb-src http://debian.implementers.org/ testing/source/

The tools is contained in the “jarc” package and is distributed under the GPL v3 license.

I wrote the previous version of jarc when I was working for my former employer, so to be sure to not infringe on their rights, I rewrote the tool from scratch in Java (the original version was a bash script). Actually the new version implements only the minimum necessary to build itself, so expect updates in the future.

Update 01/31/2010:
jarc was put in the unstable repository by mistake. The new versions (starting with 0.2.3) will be in testing. The best is to have both testing and stable in your /etc/apt/sources.list file and remove unstable completely:

deb http://debian.implementers.org/ testing/$(ARCH)/
deb http://debian.implementers.org/ testing/all/
deb-src http://debian.implementers.org/ testing/source/
deb http://debian.implementers.org/ stable/$(ARCH)/
deb http://debian.implementers.org/ stable/all/
deb-src http://debian.implementers.org/ stable/source/