On 18/09/2011, at 5:57 PM, Luke Daley wrote:

> 
> On 18/09/2011, at 3:12 AM, Adam Murdoch <[email protected]> wrote:
> 
>> Hi,
>> 
>> I'd rather we went with a variation on option 3. It's actually very simple:
>> * Change the BasePlugin so that the default configuration no longer extends 
>> archives.
>> * Change the JavaPlugin so that it adds the Jar to both the runtime and 
>> archives configurations.
> 
> Is this going to show up in the pom then? If not, which mechanism excludes it?

A good question. There're a few pieces to this:

* Which dependencies end up in the published pom?

This is determined by $targetRepo.pom.scopeMapping. By default, dependencies 
(not the artifacts) from compile, runtime, testRuntime, testCompile, 
providedCompile and providedRuntime all end up as dependencies in the pom, 
mapped to the appropriate scope. This mapping also considers only the direct 
dependencies, not the inherited ones, which causes problems. This needs fixing, 
but I think we could live with it for a while. I think we should ditch the test 
dependencies mappings too. They're a private concern of the project.

* Which artifacts do we upload when we publish?

This is any artifact in the configuration being published. Which usually means 
the archives configuration. So, we're going to need some way to decide which of 
the jar, war or ear need to be uploaded. More on this below.

* Which packaging ends up in the published pom?

This pretty much hardcoded based on which artifact we decide is the main 
artifact. At the moment, we choose the artifact with no classifier, and blow up 
if there is more than one. So, again, we're going to need some way to choose 
which of the jar, war or ear is the main artifact for the purposes of 
publishing to maven.

So, one tweak to the plan is that we change the War and Ear plugins so they do 
not disable the jar task, but they do continue to remove it from the 'archives' 
configuration. This way, the jar is used locally for project dependencies, but 
the war or ear ends up in the maven publication. I would start with this as a 
first step, I think.

The next step might be to explicitly model the main and attached artifacts for 
a maven publication, with some appropriate convention mappings. Perhaps 
something that ties together MavenPom and MavenDeployment. This way, the 
plugins can nominate the main artifact via a convention, but the build script 
can mess with publication if the convention gets it wrong. We should do the 
same for packaging, which is modelled, but the hardcoded rule deep in the 
publication stuff which blows the value away. We should turn the hardcoded rule 
into a convention mapping, so that the build script can force a particular 
packaging.


> 
>> * Change the WarPlugin so that it no longer disables the Jar task or removes 
>> it from any configuration.
>> * Change the EarPlugin in the same way.
>> 
>> We could stop here, and things would be much improved.
>> 
>> Optionally, to clean things up, we could:
>> * Change the BasePlugin to add an 'artifacts' configuration.
>> * Change the BasePlugin to add a rule so that any artifact added to 
>> 'archives' is also added to 'artifacts'
>> * Change the BasePlugin to spit out a deprecation warning when an artifact 
>> is added to 'archives', or the 'uploadArchives' task is run.
>> * Change the SigningPlugin to either add the signatures to the 'artifacts' 
>> configuration, or have 'artifacts' extend from 'signatures'.
> 
> I wonder if it's worth introducing a "jar" plugin at this point to get people 
> using apply: "jar" now to lessen the break in the future. It would probably 
> simply delegate to the java plugin initially.

Quite possibly. Let's put it on the list for 1.0 planning.

However, I think the problem here is that we don't have a way to distinguish 
between the case where a particular bundle needs to be used only locally in the 
same build, or to be included in the external maven publications of the 
project. That, plus with the fact that it is extremely awkward to produce 
multiple maven publications for a project which produces multiple main 
artifacts.

Some examples:
* I have a standalone Java library that produces a jar. I want the jar to be 
published.
* I have a Java project which a component in a larger project. I want the jar 
to be built so that it can be included in some other bundle produced by the 
same build (eg in an uberjar or a war or an application dist). I do not want 
the jar to be published.
* I have a web application plus some client piece. I want the jar to be built 
so that it can be included the client distribution produced by the same build. 
I want only the war to be published.
* A variation on the above, where I do want the jar to be published as a 
standalone client jar to be used externally.
* I have a web application that is included in an ear produced by the same 
build. I don't want the jar or war published.
* I have a standalone enterprise app, that includes a web app. I want the war 
built and bundled into the ear. I want only the ear published.

So, I think we want a DSL that allows me to declare java libraries, web apps 
and j2ee enterprise apps, but not have that declaration imply anything about 
where those artifacts are published. Instead, I can separately declare that a 
given bundle is published locally and/or externally. Plus some convention over 
the top of this, so that things work well in common situations. I think we have 
a reasonable plan for the DSL, by introducing a model for these bundles, having 
these model objects carry dependency information with themselves, and 
separating local from external publications. What I'm not sure of yet is what a 
reasonable convention might be, and how to partition the behaviours over a set 
of plugins.


> 
> It might be more trouble than it's worth though. It might be better to make 
> such a significant breaking change all at once and make it the focus of a 1.x 
> minor release.
> 
>> 
>> 
>> 
>> On 16/09/2011, at 11:30 PM, Spencer Allain wrote:
>> 
>>> Option 2 with just the additional configurations should be an easier 
>>> shorter-term solution, but you make some great points about future 
>>> flexibility by enriching the model with some additional elements.
>>> 
>>> -Spencer
>>> 
>>> From: Luke Daley <[email protected]>
>>> To: [email protected]
>>> Sent: Friday, September 16, 2011 7:26 AM
>>> Subject: Re: [gradle-dev] [gradle] Adds a restoreJar() method to the War 
>>> Task (#43)
>>> 
>>> 
>>> On 15/09/2011, at 10:07 PM, Adam Murdoch wrote:
>>> 
>>>> So, if we work around the problem for the war plugin, we still have 
>>>> exactly the same problem in the ear plugin, and the c++ plugin, and when 
>>>> you publish a source jar and javadoc jars (and the signing plugin, to some 
>>>> extent).
>>>> 
>>>> There are some simple solutions to this problem, I think:
>>>> 
>>>> Option 1: artifact type filtering
>>>> * Change configurations so that they support filtering on an artifact's 
>>>> type when resolving.
>>>> * Change the various compile and runtime configurations to accept 
>>>> artifacts of type 'jar'.
>>>> * Change the war and ear plugins so that they do not disable and remove 
>>>> the jar.
>>>> * Probably change the signing plugin so that it add the signatures to '*' 
>>>> (ie signatures are cross-cutting).
>>>> 
>>>> Option 2: bust up archives configuration
>>>> * Add 'jars', 'sources', 'javadocs', 'wars', 'ears', etc configurations.
>>>> * Change the 'runtime' configuration to extend from 'jars' instead of 
>>>> 'archives'.
>>>> * Add a 'publications' configuration which extends 'jars', 'sources', 
>>>> 'javadocs', 'wars', 'ears', 'signatures', etc.
>>>> * Change the java plugin to add the jar to the 'jars' configuration.
>>>> * Change the war plugin to add the war to the 'wars' configuration.
>>>> * Change the ear plugin to add the ear to the 'ears' configuration.
>>>> * Change the war and ear plugins so that they do not disable and remove 
>>>> the jar.
>>>> 
>>>> User runs 'gradle uploadPublications' instead of 'gradle uploadArchives'. 
>>>> We might keep the 'archives' configuration, have it extend from 
>>>> 'publications', and deprecate 'archives' and 'uploadArchives'.
>>>> 
>>>> Option 3: artifacts in multiple configurations
>>>> * Change the ArtifactHandler so that it adds artifacts of type 'jar' to 
>>>> both the 'archives' and 'runtime' configurations.
>>>> * Change the 'default' configuration so that it no longer extends from 
>>>> 'archives'.
>>>> * Change the war and ear plugins so that they do not disable and remove 
>>>> the jar.
>>>> 
>>>> We could potentially combine both options 2 and 3. For me, option 3 is the 
>>>> way to go, followed at some point by option 2. Later, we will need option 
>>>> 1, for more sophisticated resolution (eg for fixing how we treat 
>>>> transitive dependencies, and for dealing with native variants).
>>> 
>>> I think the ideal solution is 2 with some extra work.
>>> 
>>> * Rework the java plugin so it does not create a jar, but adds the tools 
>>> for java projects in general
>>> * Add a “jars” plugin that provides a dsl for configuring jars to be built 
>>> (applies “java” plugin)
>>> * Add a “jar” plugin that applies “jars” and preconfigures to create one 
>>> jar. 
>>> * Follow this same pattern for the current war and ear plugins (e.g. “wars” 
>>> plugin adds the capability, “war” plugin preconfigures a single war).
>>> 
>>> * Add a model element for each kind of thing in a container (e.g. 
>>> jars.main, wars.main) 
>>> * Add a top level element that is a synonym for jars.main (e.g. jar {} == 
>>> jars.main {})
>>> * Expose the configurations used by each thing through that element (e.g. 
>>> jars.main.dependencies.runtime instanceof Configuration) 
>>> * Allow assignment of configurations (e.g. jars.main.dependencies.runtime = 
>>> configurations.someConfiguration)
>>> * Expose the publication for wiring into other configurations via some 
>>> interface that Configuration knows about that is implemented by the model 
>>> objects (i.e. jar, war, ear)
>>> 
>>> war { 
>>>     dependencies {
>>>     compile jars.main
>>>     }
>>> }
>>> 
>>> I think that should still give us the flexibility to dig into the jar model 
>>> and do things like just use the class files when compiling instead of using 
>>> the jar I think.
>>> 
>>> 
>>> But, that's probably too much to achieve pre 1.0 and it's breaking as 
>>> applying the java plugin would no longer get you a jar. I would love to get 
>>> this done before 1.0 though as we are going to have to make this breaking 
>>> change at some point so this is my preference.
>>> 
>>> But if we agree that's not possible to get done in time (or not desirable)…
>>> 
>>> Instead of 3 I think we should at least add the model elements for things 
>>> produced during the build and use them for wiring project dependencies 
>>> instead of configurations (like my last “point” above).
>>> 
>>> -- 
>>> Luke Daley
>>> Principal Engineer, Gradleware 
>>> http://gradleware.com
>>> 
>>> 
>>> 
>> 
>> 
>> --
>> Adam Murdoch
>> Gradle Co-founder
>> http://www.gradle.org
>> VP of Engineering, Gradleware Inc. - Gradle Training, Support, Consulting
>> http://www.gradleware.com
>> 


--
Adam Murdoch
Gradle Co-founder
http://www.gradle.org
VP of Engineering, Gradleware Inc. - Gradle Training, Support, Consulting
http://www.gradleware.com

Reply via email to