【问题标题】:How to make custom task avoid redoing work if the input files are unchanged?如果输入文件未更改,如何使自定义任务避免重做工作?
【发布时间】:2012-07-25 17:33:59
【问题描述】:

我有一个游戏的多项目设置。有一个名为“resources”的非常具体的子项目,它只包含要打包到 jar 中的图像、声音和 texfiles 等文件。

我有一个自定义任务来处理图像并打包它们。在“src/main”中,我使用了一个文件夹“预处理”,图像应该放在其中,而“非托管”文件夹放在其他所有文件夹中。通过运行我的任务,“preprocess”中的所有图像都被打包并输出到“resources”,“unmanaged”中的所有内容都按原样复制。

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 FAQ,但我不明白如何使其适应我的任务。

如果文件夹列表中子文件夹中的文件未被修改,我如何使我的自定义任务避免重做工作?

【问题讨论】:

    标签: scala sbt


    【解决方案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)
    }
    

    注意事项

    • 我对@9​​87654324@ 的理解是,它会检查inFiles 是否有修改,并且如果集合中的一个 文件发生更改,它会调用实际操作。 changed 的确切含义由 inStylecached 的参数确定。

    • 最好直接将目录传递给cached,这样如果该目录中的任何内容发生更改,就会执行实际操作。但是,我怀疑目前是否可行。

    • 我不太明白实际操作返回的文件集的行为是什么(这里:Set(outJar))。我假设cachedoutStyle 参数与此相关,并且我希望在JAR 不存在时调用createJarFromFolder(不管输入文件的更改),但这似乎不是案子。也就是说,如果您删除了一个 JAR 文件但不更改相应目录中的文件之一,则不会重新创建该 JAR。

    • 代码有点狡猾,因为在决定是否在特定文件夹中发生更改时,它只考虑位于特定文件夹顶部的文件。您可能希望进行递归。

    结语

    我很想看到使用 SBT 缓存功能的更好方法。如果您从邮件列表中获得更多信息,请在此处发布。

    【讨论】:

    • 我正在为我的具体情况重新编写代码,但多亏了你,我现在可以正常工作了。现在,只有在文件夹内修改文件时,才会再次处理该文件夹。我得把它清理一下。我可能会写一篇关于整个配置的博客。
    • 如果你这样做,请发布一个链接到你的帖子。
    • 这是一个使用缓存的工作 SBT 插件:github.com/tlazaro/texture-packer-plugin/blob/…
    猜你喜欢
    • 2019-12-08
    • 1970-01-01
    • 2020-06-12
    • 2017-08-17
    • 2011-08-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多