JavaDeps version 1.1

Automatic Dependency Tracking for Java

Tracking dependencies amongst a group of source files is always a chore.  With Java it's even worse: source files may be mutually-dependent, and make doesn't deal with this situation at all!

JavaDeps is a tool to generate dependency rules for Java sources, inspired by the "-MM" flag of gcc. This program analyzes a set of java source files, and outputs their dependencies, along with makefile rules to build the resulting classes.

Please address your comments and criticisms to me. I am particularly interested in improving the documentation, portability, and usability of this tool. If the documentation is even slightly unclear, please let me know! Much appreciated.

How to use JavaDeps

How does this differ from javac's -depend flag?

There are two differences. One is that it works. :-)

Up to and including release 1.1.3 of Sun's JDK, the -depend flag for javac is broken: it only recompiles source files if the associated .class file is missing. It does not recompile if the .class file is merely out-of-date, contrary to documentation.

As an example, suppose I have three classes:

class A { B b; }
class B { C c; }
class C { }

Clearly class A depends on class B, and class B depends on class C. Suppose each is in their own file: A.java, B.java, and C.java. If I do javac A.java, the compiler will create all three corresponding .class files. Good: this is as documented.

However, if I change C.java, compiling A.java will not rebuild the (out of date) C.class file, no matter whether I use the -depend flag, or not. Bug!

The other difference between JavaDeps and -depend can be illustrated with the same example. Suppose that the change to class C actually changed the interface: maybe the parameter list for one of its methods got changed. Suppose that class B uses this method, but you forget to update B.java. Running javac -depend A.java will not rebuild B.class because it is still up-to-date with respect to its source file. But C.class will be recompiled. The result: a run-time exception when an instance of B tries to call the changed method of class C.

Using JavaDeps, what happens is that the file B.class ends up depending on C.class. So, a rebuild of the latter triggers a rebuild of the former.

Parse Errors

JavaDeps contains a full-fledged Java parser inside it. The parser is built from a language description that matches the Java Language Specification precisely. This causes a few problems, because java compilers (including Sun's own) are a bit looser in the language they accept.

Believe it or not, the Java Language Spec requires that all single-line comments (those that begin with "//") must end with a newline. If you happen to have such a comment at the end of your file, you must be sure that the file ends with a newline. If not, a lexical error results. I haven't had time yet to look into this seriously. As a work-around, just make sure all files end with a newline.

Other than the above, please report all discrepancies between what JavaDeps accepts, and what your favourite Java compiler accepts to me!

Why is this? The description of the Java language that I have access to conforms to (or aims to conform to) the published standard. Unfortunately, it seems that Sun's JDK compilers (javac) are a bit looser in what they accept. Thus it happens that code which javac will compile may generate a parse error using JavaDeps.

Since I have no access to the language description that Sun uses for javac, I have to fix the discrepancies as they are reported to me. I have already a couple reports of such incompatibilities (thanks!) and will fix any received as soon as I can reproduce them.

Installing JavaDeps

Sadly, there is no fancy install-tool yet, so installation is manual.

To win95/winNT users: read these notes before submitting a bug report. In particular, if you do not follow rule 3, please note this in your report. Thanks.

The recommended install procedure is:

  1. Copy the jar file to somewhere of your liking.
  2. Copy the script jdeps to a convenient place on your PATH.
  3. Edit the jdeps script. You will need to change the value for jarFile to be the location of jdeps.jar. You may also need to change the value of java. Note carefully the comments at the top of the script file.

Technical Details

JavaDeps parses the java language of the input files, using a parser built from JavaCC. The language parsed is that specified by their Java1.1.jj grammar from JavaCC version 1.1.

Whenever the parser comes across a type name, imports, implements, and the like, it counts this as possibly a reference to some other class file. After all the class files have been parsed, these possible references are resolved. One of the reasons this code is still considered alpha, is that I'm not 100% positive that all possible references have been caught. If you are a language parsing guru, and happen to spot some omission in the grammar file, I'd appreciate a note.

If you want to hack on the code, full source is provided in the package. You do not need JavaCC, unless you modify the grammar, as all the built java files are provided too. If you fix a bug or enhance it in some way, I'd really appreciate knowing. A diff file would be wonderful!

ChangeLog

Copyright and License

JavaDeps is copyright 1997,1998 by Steven Robbins, and distributed under the GNU public license.