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 thisRelated 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.
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 generatesSeq[File]
under(sourceManaged in Compile).value / "garfield"
using Slick code generator as the default implementation. Let's call thisgenerateModel
. Your plugin could have the following settings:If your build user wants to rewire
generateModel
, he or she could do so like this: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.
sbt.Run
API from an existing configuration. This is equivalent of callingrun
task with some customized parameter. If you're generating code forCompile
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.