On 1/06/10 10:25 AM, Jason Porter wrote:
On Mon, May 31, 2010 at 17:09, Adam Murdoch<[email protected]>  wrote:

On 29/05/10 3:57 AM, Steve Appling wrote:
We would really like to resolve the issues related to circular
dependencies (GRADLE-914 in particular) sometime soon.  I know this is
marked for 0.9, but so are 91 other issues.  Is this something that anyone
is planning on addressing in the short term (within the next couple of
weeks)?  If not, does anyone understand the underlying problem enough to
point me in the right direction?

I know of 2 problems. There may be more, but this is as far as I got:

1. The compile configuration is now transitive by default (for good or bad).
:( That blows.  Should be non transitive, if you need it on your
compile path, put it there.  This way I know exact what I need to
compile, not some third level transitive dependency that happens to be
there.  Major sad face on this one.

I tend to agree. Ideally this is a short term solution.

An alternative to making the compile configuration non transitive is instead to have a rule which does some static analysis of the source to enforce that only the direct dependencies of the compile configuration are used directly by the source. This rule might be evaluated by a post-compilation task (against the bytecode), or even during compilation (against the source).

The advantage of a static analysis approach is that we can use the same mechanism to evaluate additional rules - such as, to enforce that every dependency declared in the compile configuration must actually be used by the source. Or to limit the use of a given dependency to a particular source package.

Something like this might eventually evolve into a structure definition DSL. You might be able to, for example, define which classes make up the API of your code, and Gradle could enforce that the API is independent of the implementation, that other projects use only the API classes, and so on. It could use exactly the same information to determine which classes to include in the javadoc, and to automatically generate an API jar.

But, this does highlight some awkwardness in the dependency
dsl, where the only options are to include the jar on its own or the entire
transitive closure of everything the jar might need (even though it doesn't
for the purposes of compiling a dependent project). I think we need
something more flexible here, so we can provide a better default behaviour.
This would be nice so we can get back to compile being non-transitive.


What I'd like to do is something like this:

- Assume that we've split Configuration into 2 pieces: the incoming dependencies and the outgoing publications. Publications are the things that end up being published to the repository and in the generated pom.xml or ivy.xml

- Each java project has 2 publications: An 'api' publication and a 'runtime' publication.

- The api publication represents the artifacts that a dependent project needs in order to compile against the project. This would by default contain only the jar of the project (or only the api jar of the project, if such a thing exists)

- The runtime publication represents the artifacts that the project needs in order to be used at runtime. This would by default contain the jar of the project, plus all the runtime dependencies.

- It will be possible (and easy) to alter the publications: You will be able to add new publications, and add jars, artifacts, dependencies, and other publications to a given publication. There also be some way to control how a given publication is mapped to a given dependency descriptor (pom.xml, ivy.xml, manifest.mf, etc).

- A compile dependency would include all the artifacts from the api publication of the target project at compile time and all the artifacts from the runtime publication of the target project at runtime.

- A runtime dependency would include all the artifacts from the runtime publication of the target project at runtime.

- The above would work the same way for external dependencies. A dependency with a Gradle published ivy.xml would use the api and runtime configurations declared in the ivy.xml. A dependency with a pom.xml would treat the compile scope as the api publication and the runtime scope as the runtime publication. A dependency with an ivy.xml would treat the non-transitive default configuration as the api publication and the transitive default configuration as the runtime publication.

What this means is that, by default, things work as they did when compile was not transitive. However, this also gives the publishing project the ability to declare the things which make up its API, and allow all dependent project to just pick that up without having to repeat this information in their dependency declarations. Also, it introduces an important concept to the Gradle domain model: that a java project has an API.


--
Adam Murdoch
Gradle Developer
http://www.gradle.org
CTO, Gradle Inc. - Gradle Training, Support, Consulting
http://www.gradle.biz


---------------------------------------------------------------------
To unsubscribe from this list, please visit:

   http://xircles.codehaus.org/manage_email


Reply via email to