'How to trigger recompilation of a dependant project during a SBT build?
Background
I have a complex code generation project called migrationManager with a recursive code generation strategy:
migration1is used to generateschema1.migration2usesschema1to generateschema2.migration3usesschema2to generateschema3.- etc.
In order to compile migrationManager and since the later migration files depend on files which are not generated yet, the files are brought in sequentially via sbt commands like such:
sbt migrationManager/run update -cThis copies the next migration file into themigrationManagerproject.sbt migrationManager/run applyandsbt migrationManager/run codegenproduce the next code-generated schema.
When executing these manually via the terminal, and since we copy over the next migration file or generate the next schema, sbt detects the change in the source code and recompiles the project when the next run command is issued.
One way to automate this is with the watch version of the commands:
~sbt migrationManager/run update -c; migrationManager/run apply; migrationManager/run codegen
which detects source code changes and re-triggers these commands.
Problem
My goal is to automate this within the build process, so I am writing a task which tries to loop through and run these commands.
The issue I'm running into is that when the next sbt run command is run, it does not detect the source code change and thus does not recompile before running the next command:
lazy val generateSchemas = taskKey[Seq[File]]("Generate database schema code based on migration files.")
// Migration manager receives the code changes from update command
lazy val migrationManager = project.settings(...)
lazy val app = project
.dependsOn(migrationManager)
.settings(
libraryDependencies ++= appDependencies,
generateSchemas := {
val cp = (Compile / dependencyClasspath).value
val r = (migrationManager / Compile / runner).value
val s = streams.value
while (migrationsRemain > 0) {
r.run("migrationManager.Application", cp.files, Seq("update", "-c"), s.log)
// What can I do here to incrementally recompile migrationManager with the added source file?
r.run("migrationManager.Application", cp.files, Seq("apply"), s.log)
r.run("migrationManager.Application", cp.files, Seq("codegen"), s.log)
}
Seq(...)
},
Compile / sourceGenerators += generateSchemas.taskValue
)
In the above example, the apply and codegen commands do not work properly because the copied migration file is not compiled into the project.
Question
Is it possible to trigger a recompilation of the subproject migrationManager from within the app project's generateSchemas task I have defined above?
Further Attempts
Looks like I can get hold of migrationManager's compiler via:
val c = (migrationManager / Compile / compilers).value
within the task and from this value I can call compile like so:
c.scalac().compile(...)
which takes in a bunch of parameters:
compile(
VirtualFile[] var1,
VirtualFile[] var2,
FileConverter var3,
DependencyChanges var4,
String[] var5,
Output var6,
AnalysisCallback var7,
Reporter var8,
Optional<CompileProgress> var9,
Logger var10
): Unit;
but I'm not sure what to use as parameters (nor where I can see a trace of previous calls).
Is there a way to copy the values from the previous compilation of migrationManager so I can trigger it again from within my app project task?
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|
