Miles has asked me to respond to these points. I should declare my
interest because I have what may be regarded as a competing solution
-- Bndtools, a Bnd-based Eclipse IDE for OSGi. But I still believe in
the right tool for the job, and in fact I think Tycho would be a fine
choice for Scala IDE.
Nevertheless there are some misconceptions about Bnd which I feel I
must challenge.
Regarding the loss of compile time checks. Note that the compiler in
both cases is not Bnd nor Tycho -- it is javac, ecj or scalac. None of
these compilers knows anything about exported packages or private
packages: when we add a JAR or folder to the compilation classpath,
all of the classes therein are visible. So whatever solution we choose
must be layered on top of the compiler.
When using PDE/Tycho on Java code, a rather complex system of
visibility constraints is used. The challenge is that the compiler
must restrict the visible packages to the intersection of two sets:
the exported packages of the dependencies, AND the imported packages
of the current bundle. Ecj, the Eclipse Java Compiler, includes some
enhanced options to hide packages, but even then it is not
particularly close to the runtime checks that exist in OSGi. Also
neither javac nor (AFAIK) scalac support those additional options. As
you say "Scala still needs a bit of work"... quite an understatement
IMHO.
You state that with Tycho, dependencies are calculated before
compilation. That is incorrect... nothing is calculated, it must be
manually entered and maintained. This is the essence of the so-called
manifest first approach: the MANIFEST.MF file is the primary source
file which describes the dependencies and all other metadata for the
bundle. You make changes directly in MANIFEST.MF, and the file you
edit appears as-is in the resulting bundle, so you have to list all of
your Import-Packages by hand.
Bnd's approach is to treat the Java/Scala code (actually the compiled
bytecode) as prime. The dependencies are derived from what is actually
used, and Bnd does an excellent job of ensuring that ALL those
dependecies that actually exist in the code -- and ONLY those
dependencies -- are added to the Import-Package statement.
Let me go back to the compilation issue. Yes, we must find a way to
compile the current bundle, but this is actually easier than with PDE/
Tycho because we only need to restrict the visible packages to the
exports of the dependencies. The solution I have implemented in
Bndtools is to simply strip non-exported packages from the bundles
that I store in my repository -- this works with ANY compiler. Of
course I still keep the unstripped bundles around for use at runtime!
But suppose I don't bother to do that stripping -- what happens if a
bundle built with Bnd tries to use an internal package from another
bundle, e.g. "org.foo.internal"? The compilation will succeed, and Bnd
will detect the dependency and add "org.foo.internal" to the Import-
Package for my bundle. When I deploy the bundle at runtime it will
refuse to resolve, because no other bundle will export
"org.foo.internal".
Admittely this is a runtime error, but it is a LOT different from
something like a NoClassDefFoundError or ClassNotFoundException. The
evil thing about those exceptions is they only get thrown when a
certain code path is executed. But a resolution problem due to missing
imports is immediately apparent: your bundle will be stuck in the
INSTALLED state, and running the "diag" command on it will inform you
"Missing imported package: org.foo.internal".
Also I admit that we need to maintain some kind of module-level
dependencies, but the need from these is different from what you
state. They are needed only for two things: (1) compiling modules in
the correct order, and (2) ensuring enough JARs are visible on the
compiler classpath. However this does NOT affect the runtime
dependencies, which come only from Import-Packages and the package-
dependencies which ACTUALLY exist in the code. With a Maven/Bnd-style
build, there is no cost associated with adding extra module-level
dependencies (well, the compilation might be fractionally slower).
In contrast, a spurious Import-Package or Require-Bundle added to
MANIFEST.MF with a manifest-first tool will go straight through to
your bundle, which now will refuse to resolve when the
"org.dont.need.this" package is absent, even though your code doesn't
actually use the package.
So to summarise:
1) The compile-time checking in PDE is only produced at the great
expense of manual maintenance of Import-Packages, and even then is not
a great match for the true runtime checks performed by OSGi;
2) Bnd automates the production of Import-Package, and does so more
accurately and reliably than any manual process can;
3) Compile-time checks as good as PDE's can be achieved with Bnd by
using stripped bundles at compile time.
Now, going back to the more relevant question of which tooling Miles
should choose, as much as I would like such a visible project to be
using Bndtools, I would probably recommend Miles to choose Tycho, for
the following reasons:
1) Tycho is based on PDE and requires very little change (if any?) to
the layout of an existing PDE project;
2) As I understand it, Scala IDE has relatively few large-grained
bundles. Problems with manually maintaining manifests become much more
acute with larger numbers of bundles and packages, but I don't believe
that is Miles' number one problem;
3) Tycho is more mature than Bndtools and has the backing of a company
with deep pockets. Bndtools is something that I sincerely hope will
become widely adopted, but it is clearly not there yet.
Kind regards
Neil