Building Java projects

310 views
Skip to first unread message

Petr Wolf

unread,
Dec 27, 2011, 11:02:30 AM12/27/11
to ninja-build
Hi all,

the topic of using ninja to build Java projects has already been
discussed. When actually trying to use it, I came across two new
problems/questions.

1] When compiling *.java files, the number and names of the outpt
files are not known in advance.
A single foo.java will always produce foo.class PLUS one foo
$subclass.class per every subclass it contains. This is a problem for
expressing such rules in ninja.

Idea: Analogy to depfiles for outputs. Assuming we could tell what the
real outputs are *after* the compilation happened, we could list them
in a file and read together with the depfiles in the next ninja start
up.

2] How to discover dependencies between *.java files? There seem not
to be a direct analogy of gcc -m in the Java SDK. When googling, I
found some tools to discover the dependencies from .class files or
open source compilers which offer that feature. However, I wonder
whether someone has an experience of getting the dependency
information using the stanard Java SDK from Sun, erm ... Oracle.

Happy new year!

Petr

Elazar Leibovich

unread,
Dec 27, 2011, 11:30:37 AM12/27/11
to ninja...@googlegroups.com
Here's how I do that

"""

rule jar
  command = jar cvf $out $in
  description = JAR $out

rule javac
  command = javac -cp $classpath $in -d $out_dir
  description = JAVAC $out

build bin/debug/Foo.jar: jar $
    foo/debug/FooA.class $
    foo/debug/FooB.class $
    foo/debug/FooC.class

build foo/debug/FooA.class $
    foo/debug/FooB.class $
    foo/debug/FooC.class: javac $
    foo/FooA.java $
    foo/FooB.java $
    foo/FooC.java
  out_dir = foo/debug
  classpath = foo/jxl.jar

"""

ninja always assume all class files might be created. So it will always recompiles all the .java files in a package, and javac will recompile only what it needs.

I'm not sure something more sophisticated is worth your while, and I'm not sure it'll actually be faster (javac is pretty fast, and you might come up with a method to generate dependency information that would be slower than recompiling all files in a  package).

Evan Martin

unread,
Dec 27, 2011, 12:44:27 PM12/27/11
to ninja...@googlegroups.com
On Tue, Dec 27, 2011 at 8:02 AM, Petr Wolf <petr...@gmail.com> wrote:
> the topic of using ninja to build Java projects has already been
> discussed. When actually trying to use it, I came across two new
> problems/questions.

For reference, here are the docs on how Ant runs javac:
http://ant.apache.org/manual/Tasks/javac.html

I'm not too familiar with Java or Ant but it appears Ant works by
having a higher-level concept of "targets" that you can express
interdependencies between. Just guessing, but perhaps something like
this would work:

rule javac
command = javac -src $srcdir -dst $dstdir && touch $out

build module1.stamp: javac src/file1.java src/file2.java src/foo/file3.java
srcdir = src
dstdir = dst

build module2.stamp: javac helper/file1.java helper/file2.java | module1.stamp
srcdir = helper
dstdir = dst

That is, let javac handle all the java<->class relationships, and just
track the module-level dependencies in ninja.

> 1] When compiling *.java files, the number and names of the outpt
> files are not known in advance.
> A single foo.java will always produce foo.class PLUS one foo
> $subclass.class per every subclass it contains. This is a problem for
> expressing such rules in ninja.
>
> Idea: Analogy to depfiles for outputs. Assuming we could tell what the
> real outputs are *after* the compilation happened, we could list them
> in a file and read together with the depfiles in the next ninja start
> up.

Tracking dependencies at the per-file level is appealing in that it
could maybe avoid some overbuilding, but in practice if you change
module A to emit one extra $subclass.class file, you'll need to
rebuild all of dependent module B anyway (because you can't know which
pieces of module B use the extra file and which pieces don't).

> 2] How to discover dependencies between *.java files? There seem not
> to be a direct analogy of gcc -m in the Java SDK. When googling, I
> found some tools to discover the dependencies from .class files or
> open source compilers which offer that feature. However, I wonder
> whether someone has an experience of getting the dependency
> information using the stanard Java SDK from Sun, erm ... Oracle.

Both of these seem to require some detailed info from javac and it's
not clear to me it exposes that info.
But clearly javac itself must be able to figure out how to build such
files in the correct order, which is what prompted me to look at the
ant docs in the first place.

I am pretty ignorant of Java, so apologies in advance if this is
totally unhelpful...

Petr Wolf

unread,
Dec 28, 2011, 4:35:08 PM12/28/11
to ninja...@googlegroups.com
Thanks, guys. I'll base the implementation along these lines.
Reply all
Reply to author
Forward
0 new messages