On 11/12/2012, at 10:34 AM, Hans Dockter wrote:
>
> On Dec 11, 2012, at 12:03 AM, Adam Murdoch <[email protected]>
> wrote:
>
> <snip>
>
>>>>
>>>> The obvious downside here is that version is required for a project
>>>> dependency, but version is almost always a calculated value. Another
>>>> downside is that projects already have a convenient identifier in their
>>>> path, whereas this approach would require a project to define an
>>>> additional identifier.
>>>
>>> This is also about expressiveness. Despite the fact that the difference
>>> between external libraries and project dependencies is fuzzy from an
>>> organizational point of view there is often a big difference. So it is nice
>>> to easily see the from an organization point of view different types of
>>> dependencies.
>>
>> Not sure what you mean here.
>
> Right now a reader of the build script can easily distinguish between project
> dependencies and external ones. This is not unimportant. There is the
> organizational difference between code my team/company is working on vs.
> classical libraries. Having a single notation wouldn't be very expressive in
> regard to this.
Ok, I understand. This is a very good point.
> With your proposal below you can have the expressiveness you want to
> distinguish different types of dependencies in your build.
>
>>
>>>
>>>>
>>>> 2. References to locally built things and things in a repository share a
>>>> new namespace. Every dependency declaration would use a single identifier,
>>>> and there would be a separate mapping, shared by all the projects, from
>>>> identifier to (group, module, version) or project.
>>>>
>>>> The idea here is that we also deal with the 'dependencyManagement' use
>>>> case as well, so that you define (group, module, version) in one place and
>>>> use a simple name everywhere that you need to refer to the dependency.
>>>> This is, in practise what larger builds do already, so it's not
>>>> necessarily more 'complicated'.
>>>>
>>>> allprojects {
>>>> modules {
>>>> someRepoThing 'my.org:some-repo-thing:1.2'
>>>> }
>>>> }
>>>>
>>>> dependencies {
>>>> compile someRepoThing
>>>> runtime someLocalThing // Probably some default rule to look for a
>>>> locally built component called 'someLocalThing'
>>>> }
>>>>
>>>> The obvious downside here is that you need to extra work if the dependency
>>>> is not reused. Plus it means every dependency declaration in every Gradle
>>>> build script in existence would need to change.
>>>>
>>>> 3. A combination of the above, so that all dependency declarations refer
>>>> to things using (group, component, version), but group and version are
>>>> optional. If not specified, we look for a mapping from component name to
>>>> (group, component, version) or (project, component). We'd have some place
>>>> where you can register these mapping to things in repositories, and
>>>> probably also have a default mapping where we look for a locally built
>>>> component with the given name and same group as the referring project.
>>>>
>>>> allprojects {
>>>> dependencies.modules {
>>>> junit "junit:junit:4.11"
>>>> }
>>>> }
>>>>
>>>> dependencies {
>>>> compile "com.google.guava:guava:13"
>>>> testCompile "junit" // or perhaps ":junit:" - maps to
>>>> "junit:junit:4.11"
>>>> testCompile "junit:4.8.2" // maps to "junit:junit:4.8.2"
>>>> runtime "some-local-thing" // default rule maps to component
>>>> 'some-local-thing' built by another project
>>>> }
>>>>
>>>> For me, this one is almost all upsides. It gives me a unified way to refer
>>>> to things, using (if I like) a simple name, and a place to define
>>>> meta-data about external things in a single place (such as, every
>>>> dependency to 'junit' should use 'junit:junit:4.11' unless otherwise
>>>> specified, or "my-lib" uses semantic versioning, or "groovy-all" conflicts
>>>> with "groovy", etc). It also gives me a point where I can put logic in to
>>>> influence whether a given dependency declaration is mapped to a locally
>>>> built thing or a thing in a repository.
>>>
>>> I like this very, very much.
>>>
>>>>
>>>> One major downside is that every project dependency in the world would
>>>> need to be changed, because project dependencies would go away (via a long
>>>> period of deprecation).
>>>
>>> They wouldn't necessarily need to go away. We should easily be able to map
>>> them as long as we want.
>>
>> If they don't go away, then you're really talking about option 4. below. The
>> point of option 3. is that there is exactly one way to express a dependency
>> and it's a separate mapping step as to whether that ends up pointing to
>> something external or something local.
>
> What I mean is that we can treat the 'old' notation as syntactic sugar and
> translate it internally to the new mechanism. This would not provide 100
> percent the same behavior but possibly be good enough backwards compatibility
> wise after a next major release.
Ok. This is an option. Would using a project dependency mean that there must be
a project on the other end (ie you can't substitute an external thing in
instead)? Or would using a project dependency mean that there is usually a
project on the other end, but might not be (ie you can substitute an external
thing in)?
--
Adam Murdoch
Gradle Co-founder
http://www.gradle.org
VP of Engineering, Gradleware Inc. - Gradle Training, Support, Consulting
http://www.gradleware.com