question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Better support for compiler plugins that have dependencies

See original GitHub issue

Imagine 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 with addCompilerPlugin). This could have been in theory ideal, unless it apparently conflicted with how sbt-assembly treats provided - 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 own publish, 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:open
  • Created 8 years ago
  • Reactions:3
  • Comments:8 (4 by maintainers)

github_iconTop GitHub Comments

1reaction
cvogtcommented, Mar 26, 2017

I just verified it. The Scala compiler supports this. To try, I split scalahost into 2 jars and provided them like this:

scalac Main.scala -Yrangepos -Xplugin-require:scalahost -Xplugin:/Users/chris/Downloads/scalahost_2.12.1-1.6.0/scalahost.jar:/Users/chris/Downloads/scalahost_2.12.1-1.6.0/deps.jar
0reactions
matanstercommented, Oct 7, 2017

Thanks for all the elaborate workarounds and adding some comments to the readme few days ago @SethTisue @eed3si9n

Read more comments on GitHub >

github_iconTop Results From Across the Web

Guide to Configuring Plug-ins - Apache Maven
A good practice is to specify each build plugin's version in a ... Most Maven plugins have a help goal that prints a...
Read more >
Support for excluding dependencies (eg, compiler plugins) #13
I had a go at fixing sbt-scapegoat to only add the dependency in the Scapegoat configuration, but sbt has me stumped as usual....
Read more >
What is the difference in Maven between dependency and ...
Both plugins and dependencies are Jar files. But the difference between them is, most of the work in maven is done using plugins; ......
Read more >
The Java Plugin - Gradle User Manual
The Java plugin adds a number of dependency configurations to your project, as shown below. Tasks such as compileJava and test then use...
Read more >
Managing dependencies - Atlassian Developer
You will follow the same process every time you decide to use another piece of code in your plugin: "Where will I get...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found