At the end of the day you need to run some code to generate Scala source files.
Generating files
As you know, sbt has a hook for generating source files called sourceGenerators
, which is documented in Generating files.
You as the plugin author should provide a task that generates Seq[File]
under (sourceManaged in Compile).value / "garfield"
using Slick code generator as the default implementation. Let's call this generateModel
. Your plugin could have the following settings:
sourceGenerators in Compile += generateModel.taskValue,
generateModel := defaultGenerateModel.value,
defaultGenerateModel := { ... }
If your build user wants to rewire generateModel
, he or she could do so like this:
generateModel := {
val file = (sourceManaged in Compile).value / "garfield" / "Foo.scala"
IO.write(file, """case class Foo() {}""")
Seq(file)
}
If the code generation is contained within the sbt plugin, like the above, you don't need to do any dynamic things. Since play-slick-evolutions-codegen-plugin
depends on slick-codegen, this shouldn't be a problem.
Dynamically loading user's code
Since the question is directly on dynamically loading the user's code, I'd also put some pointers of that too.
- One way is to use
sbt.Run
API from an existing configuration. This is equivalent of calling run
task with some customized parameter. If you're generating code for Compile
configuration, using the runner for any configuration that depends on it would not be a good idea.
- Another similar way is to use
sbt.Fork
API. Forking lets you run code outside of the plugin.
Given sbt would automatically order tasks around based on the dependencies among them and runs multiple tasks in parallel, dynamically executing code is fraught with unexpected perils.