Building/publishing scala compiler plugin

Hi,

I am trying to publish a scala compiler plugin and then use it in another local project but it doesn’t seem to be working.
On the plugin side I have build.sbt with:
ThisBuild / organization := “org.me

ThisBuild / version := "0.2-SNAPSHOT"

name := "Scala-Mungo-Prototype"

And used sbt publishLocal

On the other local project side I have build.sbt as:
name := “TestPlugin”

version := "0.1"

scalaVersion := "2.13.3"
autoCompilerPlugins := true
addCompilerPlugin("org.me" %% "Scala-Mungo-Prototype" % "0.2-SNAPSHOT")

scalacOptions ++= Seq(
  "-Xplugin"
)

I also tried importing the jar file directly and using
scalacOptions ++= Seq(
“-Xplugin:Scala-Mungo-Prototype_2.13.jar src\main\scala\Orava.scala”
)
But if I try running code the plugin does not do anything/doesn’t seem to be added.
Is there something I am missing about building the plugin?

If you use addCompilerPlugin, then you don’t need to do anything with scalacOptions. Try removing that part.

Hi, I did try that but nothing different happened.

the plugin does not do anything/doesn’t seem to be added

Either it isn’t active at all, or it is active but isn’t operating as you expected it to. I think the next step here is to try to distinguish these completely different possible situations from each other.

I don’t see anything unusual in the code you’ve posted so far, other than what I pointed out already.

You can add -Xplugin-require:<name> to Compile / scalacOptions to make the compiler bail if the plugin named isn’t loaded. You can show libraryDependencies and check that you see a line like this:

[info] * com.lightbend:scala-fortify:1.0.17:plugin->default(compile)

with your own org and name, of course.

You can add printlns to your plugin to see whether it’s being classloaded and instantiated.

Ok, I added
Compile / scalacOptions ++= Seq( "-Xplugin-require:Scala-Mungo-Prototype" )
And checked show libraryDependencies which did give me
[info] * org.me:Scala-Mungo-Prototype:0.2-SNAPSHOT:plugin->default(compile)
And there are print statements in the apply function of the plugin yet there is still nothing happening when I run a program in the project.

If you run scalac -Xplugin:... -Xplugin-require:... -Xshow-phases, does your plugin’s phase appear on the list that is printed…?

there are print statements in the apply function of the plugin yet there is still nothing happening

I can’t tell from your phrasing whether the print statements print anything or not.

If I do:
scalac -Xplugin:jarName myFilePath
or scalac -Xplugin:name src\main\scala\Orava.scala (name being what is in the name field of my plugin class)
or scalac -Xplugin:Scala-Mungo-Prototype src\main\scala\Orava.scala

then there is no error but absolutely nothing happens (nothing is printed). I also added the jar file manually into the external libraries but that didn’t help.

-Xplugin-require:name
says I am missing the required plugin. The name is meant to be what I have as the name field in my plugin class right?

And my plugin doesn’t show up in the phases.

For the printing I meant that nothing is being printed.

By the way, if I copy in the jar file into the project directory, then scalac jar filePath does work so the jar file seems fine.

-Xplugin-require:name says I am missing the required plugin. The name is meant to be what I have as the name field in my plugin class right?

Correct.

If -Xplugin-require is failing, then it’s expected that nothing else after that is working, either.

Perhaps your JAR is missing a manifest, or has a defective manifest?

By the way, if I copy in the jar file into the project directory, then scalac jar filePath does work so the jar file seems fine.

I can’t figure out what you’re saying here — can you expand? What was the command line here, exactly (the one you’ve shown doesn’t seem to make sense), and what “works” and is “fine” here?

Seth

The command line I used was:
scalac -Xplugin:Scala-Mungo-Prototype_2.13.jar src\main\scala\Orava.scala

And I meant that with that command it does execute the plugin and things get printed as expected. So I meant that the problem is probably not from the jar file itself.

I didn’t do anything about the manifest, would the default one not work?
It looks like this at the moment:
Manifest-Version: 1.0
Created-By: 11.0.7 (AdoptOpenJDK)

Never mind about the manifest, what I should have said was scalac-plugin.xml. But you must have that right if the plugin works fine with command-line scalac.

I’m having trouble following your descriptions of what you’ve tried and what works and what doesn’t. It sounds like everything is fine if you use command-line scalac but not if you use the plugin from an sbt build…? Do I understand correctly?

If you run sbt with the -debug flag (or issue the debug command in the sbt shell), sbt will show you the exact scalac invocation it’s doing.

1 Like

Hi,

I have tried publishing the project and using addCompilerPlugin in another local project.
Using scalac then did not work in terms of the compiler invoking the plugin.

So I added the jar manually to the project and then scalac did work.

Is it actually necessary to add the jar to the project for the compiler plugin to work?

In debug mode, with the jar file in the directory and no scalacOptions I get:

The Scala compiler is invoked with:
    [debug]         -bootclasspath
    [debug]         C:\Program Files\Java\jdk1.8.0_60\jre\lib\resources.jar;C:\Program Files\Java\jdk1.8.0_60\jre\lib\rt.jar;C:\Program Files\Java\jdk1.8.0_60\jre\lib\sunrsasign.jar;C:\Program Files\Java\jdk1.8.0_60\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_60\jre\lib\jce.jar;C:\Program Files\Java\jdk1.8.0_60\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_60\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.8.0_60\jre\classes;C:\Users\Alice\AppData\Local\Coursier\cache\v1\https\repo1.maven.org\maven2\org\scala-lan


[debug]         C:\Program Files\Java\jdk1.8.0_60\jre\lib\resources.jar;C:\Program Files\Java\jdk1.8.0_60\jre\lib\rt.jar;C:\Program Files\Java\jdk1.8.0_60\jre\lib\sunrsasign.jar;C:\Program Files\Java\jdk1.8.0_60\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_60\jre\lib\jce.jar;C:\Program Files\Java\jdk1.8.0_60\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_60\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.8.0_60\jre\classes;C:\Users\Alice\AppData\Local\Coursier\cache\v1\https\repo1.maven.org\maven2\org\scala-lang\scala-library\2.13.3\scala-library-2.13.3.jar
[debug]         -classpath

And the plugin is not executed.

With the jar file present and scalacOptions as:
Compile / scalacOptions ++= Seq("-Xplugin:Scala-Mungo-Prototype_2.13.jar")

I get:

The Scala compiler is invoked with:
[debug]         -Xplugin:Scala-Mungo-Prototype_2.13.jar
[debug]         -bootclasspath
[debug]         C:\Program Files\Java\jdk1.8.0_60\jre\lib\resources.jar;C:\Program Files\Java\jdk1.8.0_60\jre\lib\rt.jar;C:\Program Files\Java\jdk1.8.0_60\jre\lib\sunrsasign.jar;C:\Program Files\Java\jdk1.8.0_60\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_60\jre\lib\jce.jar;C:\Program Files\Java\jdk1.8.0_60\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_60\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.8.0_60\jre\classes;C:\Users\Alice\AppData\Local\Coursier\cache\v1\https\repo1.maven.org\maven2\org\scala-lang\scala-library\2.13.3\scala-library-2.13.3.jar
[debug]         -classpath
[debug]         C:\Year five\Project\TestPlugin\target\scala-2.13\classes

And this does execute the plugin.

Without the jar file, the plugin is not executed, regardless of what is in the scalacOptions

Is it actually necessary to add the jar to the project for the compiler plugin to work?

I don’t know what “add the jar to the project” means.

Using addCompilerPlugin is sufficient; you don’t have to do anything else. (You can verify this yourself by making a test project that uses a well-known plugin such as kind-projector. You should find that only addCompilerPlugin is necessary. Once you’ve verified that for yourself, you could try swapping in your own plugin.)

If you can push the whole thing to GitHub along with precise instructions on how to reproduce the problem (ideally, just a single script I could run), I could have a look. The devil is in the details, so I can’t really tell what’s wrong based on your approximate verbal summaries of what you’re doing.

I meant copy pasting the jar file from one project to the other.

I am not entirely sure what you mean by a script you could run. Would you not need to clone my plugin and then publish it locally and then try to use it in another project on your machine with
addCompilerPlugin("org.me" %% "GetFileFromAnnotation" % "0.2-SNAPSHOT")
?

I don’t know how I could write a script to automate that :sweat_smile:

The github is https://github.com/Aliceravier/Scala-Mungo
and there are instructions in the readme. Let me know if those aren’t clear enough. Thanks for helping out!

I don’t know what that means.

Yes, precisely. But instead of supplying an approximate verbal description of the steps involved, I’m suggesting you supply exact commands I can run verbatim, so I don’t have to wonder if what you’re doing and what I’m doing differ in some subtle way that might be crucial.

I was able to clone your repo and do cd Scala-Mungo-Prototype followed sbt publishLocal. But then if I do:

scalac -Xplugin:/Users/tisue/.ivy2/local/org.me/scala-mungo-prototype_2.13/0.2-SNAPSHOT/jars/scala-mungo-prototype_2.13.jar -Xplugin-require:GetFileFromAnnotation S.scala

I get:

error: Missing required plugin: GetFileFromAnnotation

If I look at the JAR, there is no scalac-plugin.xml at the root level. There’s one inside a subdirectory, but that’s not correct, it must be at the root level. I strongly suspect that’s the problem.

1 Like

Hi,

If I use
jar xf Scala-Mungo-Prototype_2.13.jar
in the directory with the jar in it, and then run
dir
I get:

compilerPlugin
META-INF
ProtocolDSL
Scala-Mungo-Prototype_2.13.jar
scalac-plugin.xml

Doesn’t that mean the scalac-plugin.xml is at root level?

I meant that if you have projects Original and Test respectively containing:

Orginal
----> Scala-Mungo-Prototype_2.13.jar

Test

Then you can copy the jar file manually such that you get:

Original
----> Scala-Mungo-Prototype_2.13.jar

Test
----> Scala-Mungo-Prototype_2.13.jar

And then the
scalac -Xplugin:Scala-Mungo-Prototype_2.13.jar file.scala
command works in the Test project.

When I ran publishLocal, the resulting JAR doesn’t have scalac-plugin.xml at the top level, but only inside a directory:

% jar tf ~/.ivy2/local/org.me/scala-mungo-prototype_2.13/0.2-SNAPSHOT/jars/*.jar | grep scalac-plugin
compilerPlugin/scalac-plugin.xml

Note the nesting inside compilerPlugin/.

It sounds like you have different JARs with different contents in different locations on your machine and are getting confused between the different ones.

2 Likes

Thanks that was the problem!

1 Like