From: Andreas Leitgeb on 2 May 2010 09:17 Mike Schilling <mscottschilling(a)hotmail.com> wrote: >> Now B has a dependency on A. If A changes, for any reason: [...] >> then B has to recompiled. That's pretty standard stuff I think. There >> really isn't any need to detect an overloaded method, this >> simple dependency graph catches it, and many other cases too. > The overload is a subtle case, because the added method isn;t actually used > by anyone, so dependencies at the granularity of method usage won't catch > it. (Unless you conflate all overloads as being "the same method", which is > probably a good idea.) Or, somewhat finer-grained: conflate all overloaded methods that take the same number of arguments - with some special reasoning about varargs... Another approach was: Maintain a database of each .class's API, and if, after an incremental build, any recompiled class has a changed API, or any class was removed, or added, then do a clean build. Insert "non-private" whereever you find it appropriate.
From: Joshua Maurice on 2 May 2010 17:08 On May 1, 7:38 am, Lew <no...(a)lewscanon.com> wrote: > Joshua Maurice wrote: > > So, I post here because I feel better prepared to discuss this > > subject. I still disagree that "build from clean" is the correct > > answer. That would make our product's build still around ~25 minutes > > for just the Java compilation of around ~20,000 source files (and > > growing). There must / should be something better. Separation > > translation units make so much sense. I just wish Java had them. > > What, you never heard of JAR files? > > There's no excuse for "build clean" having to touch all 20K files. And what if all of the code is under active development, aka new features are being added to each layer on a weekly basis? And what if a large portion of that Java code is generated from a model file to facilitate serialization between C++ and Java? Thus a change to a single file would require recompiling a large amount of generated "interface" files, which theoretically touches a large portion of the 20,000 Java files. And that's still no excuse to not having an incremental compile. Even if componentized, with a full clean build every time, that could be 5 to 10 minutes lost of my work for every compile which is just wasted time.
From: Joshua Maurice on 2 May 2010 17:09 On May 1, 9:02 am, markspace <nos...(a)nowhere.com> wrote: > Joshua Maurice wrote: > > So, I post here because I feel better prepared to discuss this > > subject. I still disagree that "build from clean" is the correct > > answer. > > Ant can do most kinds of Java source dependencies for you: > > <http://ant.apache.org/manual/OptionalTasks/depend.html> Please read the paper in my opening post. Then, consider that a build machine cannot (easily) distinguish between "most" and "all". I want a fully correct incremental build. A 90% correct incremental build is useful to nearly no one, as you would do many sanity-check clean builds.
From: Joshua Maurice on 2 May 2010 17:11 On May 1, 10:43 am, Lew <no...(a)lewscanon.com> wrote: > Mike Schilling wrote: > > "The most obvious example of these limitations is that the task can't tell > > which classes to recompile when a constant primitive data type exported by > > other classes is changed. For example, a change in the definition of > > something like > > public final class Constants { > > public final static boolean DEBUG=false; > > } > > > will not be picked up by other classes. " > > > That is, it's an incremental (no pun intended) improvement on the usual Ant > > algorithm of "recompile what onviouslt needs recompilation; if that doesn't > > seem to work, do a clean build" > > You can't blame Ant for that one. The class that depends on the compile-time > constant, such as 'DEBUG' in your example, compiles the constant into its > class, not the symbol. Without some external indication of the dependency, > there's not any way for a compiler or build tool to detect that it exists.. > > With respect to dependencies where the symbol is stored in the class rather > than its value, even 'javac' handles the situation pretty well. I'm not blaming anyone in particular. I just want to know how to get a fully correct, aka 100% incremental build under the actions: adding, removing, modifying java files, and adding, removing, or modifying build steps of "take these jars, compile them to class files, then jar them", aka the standard developer actions.
From: Joshua Maurice on 2 May 2010 17:12
On May 1, 11:24 am, Lew <no...(a)lewscanon.com> wrote: > Lew wrote: > >> The class that depends on the > >> compile-time constant, such as 'DEBUG' in your example, compiles the > >> constant into its class, not the symbol. Without some external > >> indication of the dependency, there's not any way for a compiler or > >> build tool to detect that it exists. > Mike Schilling wrote: > > Other than by noting it when the symbol is used during compilation, and > > storing that bit of information somewhere. But the details of that get > > messy. > > I said that there is no way, not that there couldn't be a way. > > Lew wrote: > >> With respect to dependencies where the symbol is stored in the class > >> rather than its value, even 'javac' handles the situation pretty well. > Mike Schilling wrote: > > There are other difficult cases, like a method being added in class A that > > results in a method in B (one of A's descendents) becoming overloaded, such > > that a client of B should now choose the new overload. Java really makes > > this stuff hard. (C# is no better.) > > How would any language handle this? > > Short of a class being aware of every possible past, present and future > extension of it. > > You do present a good argument against overuse of inheritance. Read the paper in my opening post, Ghost Dependencies. |