Compiling without module identities
Alex Buckley
Alex.Buckley at Sun.COM
Tue Feb 3 18:24:08 EST 2009
So, with org.arrakis.* in /Users/atreides :
javac -classpath /Users/atreides
-d /Users/harkonnen
com/hakonnen/Foo.java
javac -classpath /Users/atreides
-d /Users/harkonnen
-moduleClasspath /Users/harkonnen
com/hakonnen/FooImpl.java
OK, there's a foreign directory at -classpath which holds Other Modules.
This is not aligned with the current meaning of -classpath, which holds
both source and classfiles from logically Any Module. Then there's -d,
which unfortunately throws all classfiles into one place, so you have to
divvy Spice classes out into atreides up front. Then there's
-moduleClasspath (really -localModulepath) which you only need to set if
the code in FooImpl.java refers to module-private types in any type
previously compiled and now available on -localModulepath (regardless of
whether it's also found in -d) and not found on -classpath.
You have to get all those paths exactly right on every compilation, and
still are limited to compiling one module at a time. (And the -classpath
and -localModulepath directories must not be aliased on the filesystem.)
This is supposed to be simple?
I reject the idea that #2 - separate compilation of a module's source
files - is uncommon. Surely you compile individual sources while
developing a bundle? Perhaps I am missing something, because I can
hardly believe someone would argue against separate compilation in Java.
With module membership in source, the compiler can place generated
classfiles in a directory corresponding to the module. No manual
divvying up, whether you compile one module's sources at a time or many.
Leave -d alone; have -m take a directory under which a directory for the
current module is created, and put classfiles in there.
Then:
Put "module M;" in individual .java files or, if you prefer, set
membership for a whole package by putting "module M @ 1.0;" in
package-info.java.
javac -classpath /Users/atreides
-m /Users/harkonnen
com/hakonnen/Foo.java
javac -classpath /Users/harkonnen
-m /Users/harkonnen
com/hakonnen/FooImpl.java
Like today, -classpath and -m (modular version of -d) are often the
same. javac knows the module of FooImpl and can get the module of Foo
when it reads Foo.class from -classpath, like today.
Again, I have no objection to a -module option on the command line that
sets module identity for command line and -sourcepath files. But it's an
additional mechanism to source membership.
Alex
Hal Hildebrand wrote:
> So Richard Hall suggested that I make a detailed proposal of what I'm
> talking about so that hopefully it will make the issue more clear.
>
> In my experience of developing modular code, I never compile more than
> the module in question. I do this by mapping Maven projects onto the
> produced OSGi bundle, one for one. But this can also be easily done
> with Ant, Make or any other build tool. Thus, I'm assuming that the
> *only* source code that will be compiled is to be of a particular
> module, regardless of whether the source being compiled is of the full
> module or a subset of the module. The reason is quite simple. If I
> compile the source of more than one module, then I'm adding more work to
> my life by having to sort out the resulting class files into their
> individual modules. Divvying up a mess of class files into separate
> jars is something that we used to do in our builds here at House
> Harkonnen, and that process actually caused a great deal of pain, as the
> splitting up of the compiled code is hard work - especially hard to
> automate in a large build. We spent a lot of effort to reorganize the
> source code and compilation such that we didn't have to perform this
> step - i.e. effectively modularizing the code. Organizing your source
> and compilation by module is considered best practice and besides the
> positive benefits, doing so is known to prevent other nasty things like
> circularities in your code.
>
> So, if we can agree that any source we are currently compiling is from a
> single module, then the issue is how to treat the dependencies. The
> dependencies of the compiled source fall into two categories:
>
> 1. additional classes that are in the same module
> 2. the dependencies of the module (aka the "imports", in OSGi slang)
>
>
> What I was proposing is that the java compiler be extended to know about
> the additional distinction of the module in the class path. For example
> here is my module:
>
> com.harkonnen.Foo
> com.harkonnen.impl.FooImpl
>
> With dependencies on:
>
> org.arrakis.Spice
>
> So, the scenario is that we want to compile Foo and FooImpl separately,
> and somehow make use of a module private method on Foo from FooImpl.
> Foo has dependency on Spice, FooImpl has dependency on Foo. The
> dependency Spice, being in a separate module, will have been previously
> compiled and is rooted in the directory /Users/atreides. To accomplish
> this, I posit the idea of the module class path that the java compiler
> now knows about. Let's say that the new flag is "-moduleClasspath".
> So, the compilation of Foo looks like:
>
> java -classpath /Users/atreides -d /Users/harkonnen com/hakonnen/Foo
>
> To compile FooImpl:
>
> java -classpath /Users/atreides -d /Users/harkonnen -moduleClasspath
> /Users/harkonnen com/hakonnen/Foo'
>
> Because the Spice is obtained from outside the moduleClasspath, the
> compiler knows that it is *not* in the current module being compiled.
> Because FooImpl *is* on the moduleClasspath, it knows that it is in the
> current module being compiled. Thus, FooImpl can use a module private
> method on Foo, but cannot use any module private methods on Spice.
>
> In this example, it's important to realize that the *only* source code
> that will be compiled is source that is in the current module. Thus,
> the question as to "what module any source code is in" has exactly one
> answer: "the current module".
>
> It is also important to note that the additional "module class path" is
> needed only to handle two edge cases of compilation:
>
> 1. libraries in the OSGi bundle class path
> 2. separate compilation of a module's source files
>
>
> I believe that the probability of #1 is far higher than the probability
> of #2, given my experience in creating modular code, as well as what
> I've seen in large scale commercial development here at House Harkonnen
> and other corporations. Consequently, if you're doing what comes
> naturally to developers compiling modules - i.e. compiling the entire
> source of the module - then you would not need any additional class path
> at all. The compiler knows that any source it is compiling is a module
> and any dependency it finds from the class path is considered to be in
> another module (can be multiple modules as it does not matter to the
> semantics).
More information about the jsr294-modularity-observer
mailing list