Плагин SBT: Как вывести список файлов путем инкрементальной перекомпиляции

Я пишу плагин для SBT, который требует список файлов классов, сгенерированных при последнем запуске компилятора Scala.

Этот список файлов классов затем передается в программу, которая выполняет некоторые преобразования байт-кода. Поскольку этот процесс преобразования может быть медленным, мне нужны только файлы классов, записанные при последнем запуске компилятора Scala (то есть те, которые там были изменены), а не все файлы классов в выходном каталоге.

Как я могу получить список файлов, сгенерированных последним compile задача?

1 ответ

Решение

Я думаю, что вы не можете получить эту информацию непосредственно от Analysis объект, возвращаемый compile задача.

Однако, что вы можете сделать, это проверить analysis.relations.allProducts для изменений. Если какой-либо из файлов был изменен, вы можете выполнить свою задачу, которая выполняет преобразования байт-кода.

Вы можете использовать модифицированную версию FileFunction.cached для проверки изменений.

def cached(cacheBaseDirectory: File, inStyle: FilesInfo.Style)(action: Set[File] => Unit): Set[File] => Unit = {
  import Path._
  lazy val inCache = Difference.inputs(cacheBaseDirectory / "in-cache", inStyle)
  inputs => {
    inCache(inputs) { inReport =>
      if(!inReport.modified.isEmpty) action(inReport.modified)
    }   
  }     
}

Функция принимает следующие параметры:

  • cacheBaseDirectory - расположение кеша
  • inStyle - описание того, как изменения должны быть обнаружены (см. sbt.FilesInfo для возможных вариантов)
  • action - функция запускается, когда файлы были изменены. Функция принимает список измененных файлов в качестве аргумента.

Функция возвращает другую функцию, которая запускается только в том случае, если набор файлов, переданных ей в качестве аргумента, изменен.

пример

val transformBytecode = taskKey[Unit]("Transforms bytecode of modified files")

def cached(cacheBaseDirectory: File, inStyle: FilesInfo.Style)(action: Set[File] => Unit): Set[File] => Unit = {
  import Path._
  lazy val inCache = Difference.inputs(cacheBaseDirectory / "in-cache", inStyle)
  inputs => {
    inCache(inputs) { inReport =>
      if(!inReport.modified.isEmpty) action(inReport.modified)
    }   
  }     
}

transformBytecode <<= Def.task {
  val analysis = (compile in Compile).value
  val cachedFunction = cached(streams.value.cacheDirectory / "transform-bytecode", FilesInfo.lastModified) { modified =>
    // here you want to run the bytecode transformations on `modified` files
    println(s"Modified files $modified")
  }
  cachedFunction(analysis.relations.allProducts.toSet)
}.triggeredBy(compile in Compile)
Другие вопросы по тегам