incubator-easyant-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Jean-Louis Boudart <>
Subject Re: Dependency management of the easyant plugins
Date Sat, 23 Apr 2011 23:21:56 GMT
Le 22 avril 2011 13:43, Nicolas Lalevée <> a écrit

> I would like to discuss the way the plugins are declaring the dependencies
> with each other.
> In easyant 0.8, there was some easyant include. Since it is an include and
> not an import, each plugin is somehow embedding its dependencies at runtime
> without directly exposing them to the plugins which are dependencies of it.
> So if two plugins wants to share some targets, they shouldn't declare these
> dependencies, it would be the responsibility to the one which includes them
> both to also include the plugin in common.
> In the refactoring of EASYANT-27 [1], I changed the includes with imports
> so there is no transitive issue about using extension point. Using extension
> point is kind of different of phases since the dependencies between targets
> are now explicit. Phases were the workflow every plugins was relying on. Now
> each plugin expose its points of extension, so each plugins is actually
> relying on each other. So include was not possible.
> I hope this is OK for everyone ?
Change on import vs include looks good for me even if we loose the ability
to "alias" a module.
Prefixing all targets of a plugins by hand will be error prone but maybe we
can find a workaround for this.

If i understand correctly, buildtype are supposed to load a set of plugins
and plug them through their extensionPoint, am i wrong ?
At first glance it seems to offer much more flexibility than what we had

Let's now discuss about "build lifecycle".
In easyant early stages we used a set of phases defining dependency between
each others.
Some plugins was "plugged by default" to standard phases. And buildtypes
were loading standard phases and sets of plugins.
There is at least two drawback of this solution :

   - As a enduser it was a bit confusing as you seen  all "PHASES" even if
   they don't contains any target. I guess enduser will all the time call the
   same phases (compile, test, package, verify, release) but will probably
   never call most of existing phases like process-sources etc...

   - Another drawback of this model was the coupling between plugins and
   phases. How someone can use it's own "lifecycle" ? Should he rebind all
   targets to his own phases ?

First can be addressed by exposing "high level target" for end users such as
compile, test, package, verify, etc.. (i'm not sure we need more). To limit
"copy/paste" between all our buildtype we should put thoses "high level
target" in a common plugin.

Second point is defacto addressed by your refactoring.

My last comment on the refactoring would be about relations between plugins.
I don't think we need to link plugins except if we had a good reason for it.
And if we need to link two plugins it would probably better to link on an
extensionPoint provided by an abstract module. In other cases linking
plugins should be done by buildtypes or by the enduser itself.

For example compile-java <import> ivy-provisioning. This sounds like a bad
choice for me as provisioning (filling a classpath for compilation) can be
done by others plugins such as "deps-lib".
In opposite i really like how cobertura / emma plugins interacts with tests
Both cobertura and emma plugins relies on test extension points defined in
an abtract-test plugin.

> Then I would like to go further. Because each plugin manage its own
> dependency, each import is an Ivy resolve behind the hood, there is not much
> dependency management of the plugins. Ivy is here barely used more than just
> downloading build files. There is no transitive dependency or conflict
> management.
> For instance:
> * build-std-java imports compile-java and ivy-provisioning
> * compile-java imports ivy-provisioning
> In this example, ivy-provisioning is resolved two times, and it is possible
> that the two resolved versions are not the same.
> I then suggest to move to a real dependency management of the plugins, by
> really using Ivy. Each plugin rather than importing himself its
> dependencies, it would just declares them. As a proof of concept, I
> implemented an Ant task that just does that. See the "experiment" folder I
> have just committed to test it.
> To run the sample, put the jars of both easyant and ivy into
> sample/ea-jars.
> Two special ant properties controls the task behaviour:
> * easyant.refresh : set it to true to force a resolve. Otherwise the last
> resolve report will be used
> * easyant.localrepo.basedir : set folder in which the scripts are
> retrieved, useful for embedding the build. If not set, the scripts are
> imported directly from the cache.
> As you could see the plugin dependencies are nicely resolved. So nicely
> that a script can have dependencies reusable in the script itself. See the
> script of org.apache.easyant#groovyfrontend. The classpath to find the
> project helper is computed by Ivy from the ivy.xml of the plugin.
> WDYT of the idea ?

BIG +1 :)

Jean Louis Boudart
Independent consultant
Project Lead

  • Unnamed multipart/alternative (inline, None, 0 bytes)
View raw message