I haven't done quite this, but I've done two things that are pretty similar which if combined might solve this issue.
1) I've created multiple compile steps in sbt using configurations.
So in my Build.scala I did the following:
lazy val Precompile = config("precompile")
//and then when I created my settings for my project, I appended the following::
inConfig(Precompile)(Defaults.defaultSettings ++ Defaults.configSettings ++ Defaults.configTasks)
then in my build.sbt I did:
sourceDirectories in Precompile <<= sourceDirectory apply ( (src) => {
Seq[File](src / "precompile/scala")
})
compile in Compile <<= (compile in Compile) dependsOn (compile in RK.Precompile)
// Set the compile classpath to include the output of the Precompile step.
unmanagedClasspath in Compile <<= (unmanagedClasspath in Compile,
classDirectory in Precompile) map ( (path, f) => {
path :+ Attributed.blank(f)
})
obviously that isn't exactly what you want to do. You'd probably want to make the task that runs
the generator depend on the precompile and then you'd want to add that task as a
sourceGenerator in Compile, so it gets called before compile automatically.
To handle the second part (when I want to call into code that is being generated as part of a compile),
I just shell out to java/scala and run a main method.
Pick the classpath that you want to use. In this case it should be whatever your Precompile classpath was
plus the classDirectory from classpath. You can probably get away just using the dependencyClasspath.in(Compile).
That's what I'm using.
So I pass that into my task that runs my generator as an argument
def runGenerator(log: Logger, cpath: Seq[Attributed[File]], ....): Seq[File] =
{
val myClasspath = (cpath map { path => path.data.toString}).mkString(":")
val cmd = "java -cp %s package.path.to.Generator %s".format(myClasspath, args.mkString(" "))
val returnVal = <x>{cmd}</x> ! log
if (returnVal != 0) {
throw new IllegalStateException("The generator failed.")
}
//return whatever was generated.
}
And my task looks something like
lazy val generatorImpl =
generator.in(Compile) <<= (
streams, dependencyClasspath.in(Compile), ...) map
{ (streams, cpath, ...) =>
runGenerator(streams.log, cpath, . . . ) }
May not be the 'most correct' way, but it works. Happy to answer questions if you've got any.