Hi,

In working on the new plugin support, I think we might have overlooked plain 
java module build logic dependencies. Really, these are very much like plugins 
except there is no initialisation logic (i.e. plugin impl that we implicitly 
invoke). We have the same API compatibility and exporting concerns with these 
guys.

One of the key characteristics of the new plugin mechanism is that each plugin 
(build scripts are just plugins too) explicitly declare what they depend on 
(java libraries, gradle plugins, and maybe other things in the future). We have 
a new DSL for declaring plugin dependencies…

plugins {
  id “«some plugin id»
}

Given:

1. All build logic is specified via plugins 
2. Plugins can be implemented in different forms (e.g. Class vs. Script)
3. Certain domain objects have implicitly applied plugins (e.g. build.gradle)
4. Plugins depend on other plugins *and java libraries*

I think the plugins {} block is wrong. We probably need one block that 
encompasses all of the build logic dependencies (i.e. plugins and java 
libraries).

We probably want something closer to:

buildLogic {
  plugin “org.gradle.java”
  library “commons-collections:commons-collections:1.2.3"
}

Or,

buildLogic {
  plugins {
    id “org.gradle.java”
  }
  libraries {
    java “commons-collections:commons-collections:1.2.3”
  }
}

This would be the same construct that “script plugins” and “build scripts” use 
to declare their dependencies (because they are exactly the same thing).

But, while this is probably more conceptually correct, it makes the common case 
more verbose.

plugins {
  id “com.google.android"
}

vs.

buildLogic {
  plugin “com.google.android"
}

or,

buildLogic {
  plugins {
    id “com.google.android"
  } 
}


The term “buildLogic” is less than great. I don’t think that’s how users think 
of it. In a way `dependencies {}` at the top of the script is pretty good, but 
obviously that’s a non starter.

While this unification of “build scripts” as anonymous and implicit “script 
plugins” is nice for us, I don’t think that’s the mental model for users. This 
might be one of those unifications that makes things less intuitive.

The immediate concern is whether we are introducing doomed syntax with the 
`plugins {}` block. Some options:

1. Proceed with plugins {}, add another block/construct later (which might be 
adding some more bits to buildscript {}) 
2. Proceed with plugins {}, deprecate it later and move it to a new construct 
that supports plugin and library dependencies
3. Try to introduce something more evolvable now

I don’t like #1 very much, and #2 isn’t nice either. My ideas for #3 suffer 
from the, perhaps, needless verbosity as described above.

The problem with #1 (or two constructs in general) is that these things are 
inextricably connected. The public API exposed by the plugin dependencies and 
library dependencies must be compatible (i.e. resolved together, in a sense). 
Having one block for the specification of all build logic dependencies feels 
much better.


There is another option. We could allow a plugin implementation to be specified 
as one or more Java libraries, with effectively a noop implementation. From a 
conceptual and syntactic point of view, that leaves us with just plugins 
depending on other plugins (where plugins can be these weird java library only 
plugins). That might get us to a syntax like:

plugins {
  id “org.gradle.java”
  library “commons-collections:commons-collections:1.2.3"
}

Still doesn’t feel quite right though.

Any thoughts?

— 

Luke Daley
Gradleware
Join us for Gradle Summit 2014, June 12th and 13th in Santa Clara, CA: 
http://www.gradlesummit.com

Reply via email to