[Scons-dev] File-based build tools will never handle Java
Mark A. Flacy
mflacy at verizon.net
Thu Sep 6 12:29:03 EDT 2012
On Thursday 06 September 2012 10:21:46 Gary Oberbrunner wrote:
> On Wed, Sep 5, 2012 at 10:20 PM, Greg Ward <greg at gerg.ca> wrote:
> > OK, I finally sat down and did a little thought experiment, and have
> > convinced myself that file-based buld tools will never handle Java.
> > The reason? Dependency cycles.
> >
> > Short version: in Java, cycles between source files in the same
> > package are commonplace and often impossible to avoid. Because
> > interface and implementation are in the same file, that leads to DAG
> > cycles, which any DAG-of-files-based build tool (make, SCons, tup,
> > waf, ...) will reject.
>
> I don't think this is really a problem, or doesn't have to be. In
> SCons there are no dependencies *between* source files; only from
> object (.class files) to source (the object depends on the source(s)).
> And the jar depends on the class files. So I don't see how call
> graph complexities lead to build dependency cycles. If any of the
> source files change, certain objects and jars depend on those and have
> to be rebuilt. The real problem (at least as I understand it, I'm not
> a Java guy) is the fact that each .java produces unpredictable
> outputs. Am I correct about this, or are there actually real
> unavoidable build dependency cycles?
You are incorrect.
At the very least, you would have to take into account javac's somewhat
annoying habit of removing all references to static final constant primitives
in the code with the actual value. (In fact, any "if" statements that use
only such constants will be evaluated at compile time and any code that is in
the impossible branch will not be compiled at all.)
I can have class A define these two public static final ints...
public static final int SILLY_ONE = 5;
public static final int SILLY_TWO = B.STUPID + 6;
...and class B define these two public static final ints...
public static final int STUPID = A.SILLY_ONE + 2;
public static final int STUPID_TWO = A.SILLY_TWO + 3;
...and there's no way that you can compile the two classes independently of
each other. (And if you were to look inside the A.class file after the
compile, you would find no reference to B.STUPID. You would just find that
SILLY_TWO is set to 13. The B.class file would not have any references to
A.SILLY_ONE or A.SILLY_TWO. You'd just find that STUPID is set to 7 and
STUPID_TWO is set to 16.)
There's also no independent link phase, so the external symbol lookup portion
of a build that happens in other languages at link are handled by javac as
part of the compile.
A .java file will produce a deterministic set of .class files, but the normal
stumbling point are anonymous classes. The algorithm used to name them is not
defined in the java spec, IIRC, so java compile implementations can do their
own thing.
More information about the Scons-dev
mailing list