Better support for compiler plugins that have dependencies
See original GitHub issueImagine a compiler plugin that has library dependencies other than the native scala ones.
When such a compiler plugin has been added to a project via addCompilerPlugin
, then in order to have it execute during compilation, its dependencies get resolved by sbt, however they do not become available to the compiler plugin when it is called by the compiler. So the compiler plugin crashes over not having access to its own dependencies (java.lang.NoClassDefFoundError
).
The workaround I use is an uberjar, using sbt-assembly. But this leaves in the superfluous byproduct that the plugin’s dependencies are still resolved, which I’ll elaborate about in a minute.
Basically, one way to look at it is that a compiler plugin executes in a configuration that isn’t strictly regular compilation nor run or test, so ivy/maven do not necessarily help sbt here (although maybe in new versions of maven this changes, as I gather java too has a compiler plugin architecture as of java 8).
Using sbt-assembly for an uberjar, as a workaround, isn’t entirely safe:
- Defining a compiler plugin’s dependencies as
provided
means that they will not be resolved in the target project of the plugin (the one it is added to withaddCompilerPlugin
). This could have been in theory ideal, unless it apparently conflicted with how sbt-assembly treatsprovided
- it leaves those dependencies out of the uberjar. So this can’t work. - So the workaround I have found is to define the compiler plugin’s dependencies plainly (no
provided
), which works in an ugly way that is redundantly open to version ambiguity: resolution takes place in the target project, and also the classes are packed into the uberjar thanks to the plugin’s ownpublish
, in order that they can be actually found by the plugin. So it is left a little ambiguous which version of the plugin’s dependencies is being used - at least to a naive plugin user, and it is certainly left generally a little pathological.
My thoughts are that modular compiler plugins should be encouraged, and therefore it may make sense providing out-of-the-box support for this scenario - which excludes this redundancy/ambiguity I have just described - if sbt can drive special handling suited to compiler plugins’ dependency management.
Maybe I’m missing easier ways to accomplish a compiler plugin with dependencies in a clean way, but I thought it would be good to post this ticket, so that an enhancement may be considered, or to learn where I have missed something obvious.
I hope you survived reading this.
Issue Analytics
- State:
- Created 8 years ago
- Reactions:3
- Comments:8 (4 by maintainers)
I just verified it. The Scala compiler supports this. To try, I split scalahost into 2 jars and provided them like this:
Thanks for all the elaborate workarounds and adding some comments to the readme few days ago @SethTisue @eed3si9n