librelist archives

« back to archive

Plugins that introduce dependencies for development

Plugins that introduce dependencies for development

From:
James Reeves
Date:
2014-08-28 @ 01:00
I've been mulling over a cljx issue (
https://github.com/lynaghk/cljx/issues/47), and I'm not certain of the most
idiomatic way to solve the problem.

Leiningen plugins sometimes introduce additional dependencies by injecting
them into the project map. In this case, the cljx project injects a
dependency to provide some nrepl middleware.

The problem is that if cljx does this, the dependency gets pulled into
pom.xml as well, unless the plugin is placed within a profile. Perhaps
there should be a way of including dependencies or other configuration
options for development, while keeping them out of deployment?

Leiningen does unmerge the default profile from the project map, so perhaps
the solution is to extend the default profile. The
leiningen.core.project/default-profiles var contains an atom - is that to
allow plugins to extend it? Would it be a good idea to add a :cljx profile
and add it to the composite :default profile?

Any advice or ideas are welcome.

- James

Re: [leiningen] Plugins that introduce dependencies for development

From:
Phil Hagelberg
Date:
2014-08-28 @ 17:29
James Reeves <james@booleanknot.com> writes:

> Leiningen plugins sometimes introduce additional dependencies by injecting
> them into the project map. In this case, the cljx project injects a
> dependency to provide some nrepl middleware.

Yeah... I am really on the fence about whether the whole implicit
middleware thing was a mistake or not. Most of the problems people have
with Leiningen that aren't immediately obvious stem from plugins like
this that use implicit middleware or implict hooks. They are convenient,
but very "magic" and difficult to debug when they go wrong. IMO they
should be deprecated and removed in 3.0.

> The problem is that if cljx does this, the dependency gets pulled into
> pom.xml as well, unless the plugin is placed within a profile. Perhaps
> there should be a way of including dependencies or other configuration
> options for development, while keeping them out of deployment?

The problem here is one of a chicken/egg nature. As I understand it, the
cljx dependency belongs in the :provided profile--it's needed during
development but should not be propagated to downstream dependencies.

But Leiningen must choose either to apply middlewares from plugins
first, or merge in profiles first. The two are mutually exclusive. We
choose to merge profiles first, which I'm fairly confident is the right
choice, but this means it's impossible for plugin middlewares to affect
the profiles that are merged by default, because this merging has
already happened by the time they're loaded.

My suggestion would be to ditch the middleware and encourage users to
include the dependencies they need in the :provided profile so it's
clear what is going on. This is a little more verbose, but a lot less
trouble-prone.

> Leiningen does unmerge the default profile from the project map, so perhaps
> the solution is to extend the default profile. The
> leiningen.core.project/default-profiles var contains an atom - is that to
> allow plugins to extend it? Would it be a good idea to add a :cljx profile
> and add it to the composite :default profile?

There is currently no way to load profiles out of a plugin. I have
wanted to add this for a while though; I think it would be a great idea
and allow a number of weird hacks that some plugins are currently using
to become more declarative, introspectable, and debuggable.

Adding it to default-profiles would be one solution, but I feel like
once plugins can contain profiles it wouldn't be all that big of a deal
to just have users declare something like this:

    :profiles {:provided :plugin.cljx/default
               :dev ...}

I feel like this would have the benefits of implicit middleware without
any of the mysterious magic stuff that has been troublesome in the
past. The only downside is it's one additional line of configuration,
but IMO it's worth it.

-Phil

Re: [leiningen] Plugins that introduce dependencies for development

From:
Chas Emerick
Date:
2014-09-05 @ 16:49
For anyone following along, I believe I've worked out a solution to the 
issue James raised; details can be found in the latest comment/commit 
related to the issue.

That's not to attempt to derail conversation, just FYI.

Cheers,

- Chas

On 08/27/2014 09:00 PM, James Reeves wrote:
> I've been mulling over a cljx issue 
> (https://github.com/lynaghk/cljx/issues/47), and I'm not certain of 
> the most idiomatic way to solve the problem.
>
> Leiningen plugins sometimes introduce additional dependencies by 
> injecting them into the project map. In this case, the cljx project 
> injects a dependency to provide some nrepl middleware.
>
> The problem is that if cljx does this, the dependency gets pulled into 
> pom.xml as well, unless the plugin is placed within a profile. Perhaps 
> there should be a way of including dependencies or other configuration 
> options for development, while keeping them out of deployment?
>
> Leiningen does unmerge the default profile from the project map, so 
> perhaps the solution is to extend the default profile. The 
> leiningen.core.project/default-profiles var contains an atom - is that 
> to allow plugins to extend it? Would it be a good idea to add a :cljx 
> profile and add it to the composite :default profile?
>
> Any advice or ideas are welcome.
>
> - James