How to create a custom task to avoid repeated work if the input files remain unchanged?

I have a multi-project setup for the game. There is a very specific subproject called "resources" that contains only files, such as images, sounds, and tex files that need to be packaged in a jar.

I have a custom task that processes images and packs them. Inside "src / main" I use the "preprocess" folder, where the images should go, and the "unmanaged" folder, where everything else is. By running my task, all the images in the preprocess are packaged and displayed in the "resources", and everything in the "unmanaged" is copied as is.

val texturePacker = TaskKey[Unit]("texture-packer", "Runs libgdx 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"))
}

And then in the 'resources' project settings:

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

packageBin, . , , , . , . , . , SBT SBT, , .

, , ?

+5
1

, . , FileFunction.cached ( ), , , :

val testCache = TaskKey[Unit]("test-cache", "Test SBT 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 , one . inStyle cached.

  • cached, , - . , .

  • , , , (: Set(outJar)). , outStyle cached , , createJarFromFolder , JAR ( ), . , JAR , , JAR .

  • , , , , . , .

SBT. , , , .

+5

All Articles