如何使自定义任务避免重做工作,如果输入文件是不变的?(How to make custom task

2019-07-30 14:32发布

我对游戏的多项目设置。 有一个叫“资源”非常具体的子项目只包含文件,如图片,声音和texfiles被包装成一个罐子。

我有一个处理图像,并把它们打包自定义任务。 里面“的src / main”我使用的文件夹“预处理”,其中的图像应该去和“非托管”文件夹中,一切都会。 通过运行我的任务在“预处理”的所有图像被打包并输出到“资源”,一切都在“非托管”原样复制。

val texturePacker = TaskKey[Unit]("texture-packer", "Runs libgdx's Texture Packer")

val texturePackerTask = texturePacker := {
  println("Packaging textures...")
  val inputDir = file("resources/src/main/preprocess")
  val outputDir = file("resources/src/main/resources")

  val folders = inputDir.asFile.listFiles filter (_.isDirectory)

  println("Sub-Folders:" + folders.mkString(", "))

  // Run Texture Packer
  for (subfolder <- folders) {
    println("Building assets for:" + subfolder)
    val args = Array(subfolder.toString, outputDir.toString, subfolder.getName)
    com.badlogic.gdx.tools.imagepacker.TexturePacker2.main(args)
  }

  // Copy unmanaged resources
  IO.copyDirectory(file("resources/src/main/unmanaged"), file("resources/src/main/resources"))
}

然后设置里面的“资源”项目:

...
packageBin in Compile <<= packageBin in Compile dependsOn(texturePacker)
...

其他子项目有自己的运行相关的packageBin的依赖。 每当我运行该项目这样我得到的最先进的资源的最新状态。 我不希望它成为需求。 问题是,它需要很长的时间来每次运行处理。 我知道SBT支持缓存SBT常见问题 ,但我不知道如何使它适应我的任务。

我怎样才能让我的自定义任务避免重做工作,如果从文件夹列表中的子文件夹中的文件没有被修改?

Answer 1:

这里是一个可能适合你的解决方案。 不过,我不完全了解FileFunction.cached作品(代码后的详细信息),所以这可能不是最佳的解决方案:

val testCache = TaskKey[Unit]("test-cache", "Test SBT's cache")

val testCacheTask = testCache := {
  println("Testing cache ...")

  val inputDir = file("test/src")   /* Take direct subdirectories from here */
  val outputDir = file("test/dest") /* Create archives here */
  val cacheDir = file("test/cache") /* Store cache information here */

  /* Get all direct subdirectories of inputDir */
  val folders = inputDir.asFile.listFiles.filter{_.isDirectory}

  folders.foreach{folder =>
    /* Get all files in the folder (not recursively) */
    val files = folder.listFiles.toSet

    /* Wrap actual function in a function that provides basic caching
     * functionalities.
     */
    val cachedFun =
      FileFunction.cached(cacheDir / folder.name,
                          FilesInfo.lastModified, /* inStyle */
                          FilesInfo.exists)       /* outStyle */
                         {(inFiles: Set[File]) =>

        createJarFromFolder(folder,
                            inFiles,
                            outputDir / (folder.name + ".jar"))
      }

    /* Call wrapped function with files in the current folder */
    cachedFun(files)
  }
}

/* Creates a JAR archive with all files (this time recursively) in
 * the given folder.
 */
val createJarFromFolder = (folder: File, inFiles: Set[File], outJar: File) => {
  println("At least one of the %d files in %s have changed. Creating %s."
          .format(inFiles.size, folder, outJar))

  /* Replace this by your actual operation */
  val cmdSeq = Seq("jar", "cf", outJar.toString, "-C" , folder + "/", ".")
  println("cmdSeq = " + cmdSeq)
  println("jar: " + cmdSeq.!!)

  Set(outJar)
}

笔记

  • 我的理解cached是,它会检查inFiles进行修改,而如果改变了设置文件的一个调用它的实际运行情况。 而改变的确切含义是由确定inStyle参数cached

  • 这将是很好直接传递一个目录cached ,使得实际操作中,如果进行任何在该目录中的变化。 不过,我怀疑这是目前可能。

  • 我不完全得到相对于一组由实际操作返回文件的行为(在这里:什么Set(outJar) 我假设outStyle参数cached是与此相关的,和我的预期createJarFromFolder每当JAR不存在(无论更改输入文件)被调用,但是这似乎并不如此。 也就是说,如果你删除一个JAR文件,但不能更改文件的一个在相应的目录,JAR将不会重新创建。

  • 该代码是有点狡猾,因为它只能认为是在一个特定的文件夹的顶部,当谈到决定是否发生改变该文件夹中的文件。 你可能想使递归。

结语

我很乐意看到使用SBT的缓存功能的更好的方法。 如果你获得更多的信息,例如,从邮件列表,请在这里发表他们。



文章来源: How to make custom task avoid redoing work if the input files are unchanged?
标签: scala sbt