I am working on a sbt plugin that generates Scala models given a database using Slick code generator
I would ofcourse want users to override the code generator so my plugin needs to support this:
Anyway I can dynamically load a Scala class given a path to it in the build.sbt plugin keys? For example, in the user's parent build.sbt, she would provide something like codegen.override=com.company.project.CustomCodegenerator
which looks like this
Related to above; the custom codegen may use some other libraries so a simple dynamic class load may not suffice. Anyway an sbt plugin can inherit the dependencies of the project using that plugin?
Here is the full discussion about this: https://github.com/papauschek/play-slick-evolutions-plugin/issues/1
At the end of the day you need to run some code to generate Scala source 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.
Since the question is directly on dynamically loading the user's code, I'd also put some pointers of that too.
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.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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With