Run compiler in-process for the sbt 2.0 / Scala 3 plugin#3
Merged
Conversation
The sbt and Mill plugins previously embedded a 24 MB marklit-cli fat jar and drove it as a subprocess (or a long-lived JSON-RPC daemon) because a Scala 2.12 / sbt 1.x plugin could not load the Scala 3 compiler as a library. On sbt 2.0 the plugin compiles against Scala 3, so it can depend on marklit-compiler directly and call it in-process. - Extract the CLI's multi-file orchestration into a side-effect-free MarklitRun facade in the compiler module; the CLI becomes a thin shell over it. Add MarklitError.ResolutionError and MarklitRunSpec. - Publish marklit-compiler-api, marklit-core, marklit-compiler (Scala 3). Bundle the two compiler-shim jars as Compile resources of marklit-compiler so CompilerFactory resolves them off the classpath. - Convert sbt-marklit to an sbt 2.0 / Scala 3 AutoPlugin published as sbt-marklit_sbt2_3. It depends on marklit-compiler and holds one warm CompilerFactory for the sbt session (MarklitSession) instead of a daemon. Handle sbt 2.0 specifics: fileConverter for virtual-file classpaths, Def.uncached for side-effecting tasks, and the new target/out/jvm layout in cross-build classpath discovery. Add a scripted test. - Convert the Mill plugin the same way (warm factory in a Task.Worker); built and tested locally, not published. - Delete the subprocess/daemon/JSON-RPC machinery from both plugins. - Update README and plugin/example docs to match.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
The sbt and Mill plugins previously embedded a 24 MB
marklit-clifat jar and drove it as a subprocess — or a long-lived JSON-RPC daemon — purely because a Scala 2.12 / sbt 1.x plugin couldn't load the Scala 3 compiler as a library. sbt 2.0 plugins compile against Scala 3, which removes that barrier: the plugin can depend onmarklit-compilerand call it in-process.Net: −1797 / +479 lines — the entire subprocess/daemon/JSON-RPC layer is gone.
What changed
Shared facade (Phase A)
MarklitRunfacade in thecompilermodule holds the multi-file orchestration (parse directives → resolve deps once → per-major classpaths → process → render/write) as side-effect-free code returning structured results. Compile failures are data; only file/parse/resolution errors fail the effect.runMarklitbecomes a thin shell over it (theDaemoncontract is preserved). NewMarklitError.ResolutionError+MarklitRunSpec.Publishing (Phase B)
marklit-compiler-api,marklit-core,marklit-compilerare now published. The two compiler-shim jars ride as Compile resources insidemarklit-compiler, soCompilerFactoryresolves them off the classpath wherever the jar lands. CLI stays unpublished (its fat jar still bundles the shims transitively).sbt 2.0 plugin (Phase C)
sbt-marklitis now an sbt 2.0 / Scala 3 AutoPlugin published assbt-marklit_sbt2_3, depending onmarklit-compiler.MarklitSessionholds one warmCompilerFactory+ ZIO runtime for the sbt session (replaces the daemon);MarklitInProcessserializes execution and bridges to sbt logging/failure.fileConverterfor the new virtual-file classpath,Def.uncachedfor the side-effecting tasks, and the newtarget/out/jvm/scala-<ver>/layout in cross-build classpath discovery.marklit/basic): generate writes output; a broken block makesmarklitCompilefail.Mill plugin (Phase D)
CompilerFactoryin aTask.Worker, depending onmarklit-compileras anmvnDep. Built and tested locally; not published this round.Docs
mill-plugin/README.md+examples/mill/README.mdupdated: removed daemon/JSON-RPC/CLI-bundling prose, fixed coordinates (sbt-marklit_sbt2_3), updated the modules table, performance section, and build-from-source steps.Verification
compiler+clitest suites green (63 + 16 tests, incl.MarklitRunSpecand the existingMarklitSpec).plugin/scripted marklit/basicpasses.examples/sbtend-to-end: all 7 files (incl. cross-version 2.13/3.x blocks) render correctly; warm factory drops a 23-block file from ~8s to ~45ms on re-check.examples/millend-to-end on JDK 25:docs.marklitGenerate/marklitCheck/pageDocs.marklitGenerateall pass with the same cross-version output.Notes for reviewers
sbt releasenow publishes all four artifacts (alias updated inbuild.sbt).JAVA_HOME). Documented inexamples/mill/README.md.0.1.0-LOCALto match the localpublishLocalworkflow; docs reference0.1.0(the forthcoming release).