2012-07-24 4 views
5

Ich habe ein Multi-Projekt-Setup für ein Spiel. Es gibt ein sehr spezifisches Unterprojekt namens "Ressourcen", das nur Dateien wie Bilder, Sounds und Textdateien enthält, die in ein Glas gepackt werden sollen.Wie kann eine benutzerdefinierte Aufgabe vermieden werden, wenn die Eingabedateien unverändert bleiben?

Ich habe eine benutzerdefinierte Aufgabe, die Bilder verarbeitet und packt sie. Innerhalb 'src/main' benutze ich einen Ordner 'Vorverarbeitung', wo Bilder gehen und einen 'nicht verwalteten' Ordner, wo alles andere geht. Durch Ausführen meiner Aufgabe werden alle Bilder in 'Vorverarbeitung' gepackt und an 'Ressourcen' ausgegeben und alles in 'Nicht verwaltet' wird kopiert, wie es ist.

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")) 
} 

Und dann in den Einstellungen der ‚Ressourcen‘ Projekt:

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

Die anderen Teilprojekte haben eine Abhängigkeit von packageBin mit ihrem Laufe verbunden. Auf diese Weise erhalte ich jedes Mal, wenn ich das Projekt leite, den aktuellsten Stand der Ressourcen. Ich will nicht, dass es auf Nachfrage ist. Das Problem ist, dass die Verarbeitung für jeden Lauf sehr lange dauert. Ich weiß, SBT unterstützt Caching SBT FAQ, aber ich verstehe nicht, wie ich es an meine Aufgabe anpassen soll.

Wie kann ich meine benutzerdefinierte Aufgabe vermeiden, die Arbeit zu wiederholen, wenn die Dateien in einem Unterordner aus der Ordnerliste nicht geändert wurden?

Antwort

5

Lösung

Hier ist eine Lösung, die Ihnen möglicherweise entspricht. Aber ich verstehe nicht ganz, wie FileFunction.cached Werke (weitere Informationen nach dem Code), so ist dies wahrscheinlich nicht die beste mögliche Lösung:

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) 
} 

Hinweise

  • Mein Verständnis von cached ist, dass es die inFiles auf Änderungen überprüft, und dass es die tatsächliche Operation aufruft, wenn eine der Dateien in dem Satz geändert wird. Die genaue Bedeutung von geändert wird durch das inStyle Argument cached bestimmt.

  • Es wäre schön, ein Verzeichnis direkt an cached zu übergeben, so dass die eigentliche Operation ausgeführt wird, wenn sich irgendetwas in diesem Verzeichnis ändert. Ich bezweifle jedoch, dass dies derzeit möglich ist.

  • Ich verstehe nicht ganz, was das Verhalten in Bezug auf die Menge der Dateien von der tatsächlichen Operation zurückgegeben wird (hier: Set(outJar)). Ich gehe davon aus, dass das outStyle Argument zu cached damit verbunden ist, und ich erwartete createJarFromFolder aufgerufen werden, wenn die JAR nicht existiert (unabhängig von Änderungen an den Eingabedateien), aber das scheint nicht der Fall zu sein. Das heißt, wenn Sie eine JAR-Datei löschen, aber keine der Dateien im entsprechenden Verzeichnis ändern, wird die JAR-Datei nicht erneut erstellt.

  • Der Code ist etwas vertrackt, weil sie der Auffassung ist nur die Dateien, die an der Spitze eines bestimmten Ordners sind, wenn es um die Entscheidung geht, ob Änderungen in diesem Ordner aufgetreten. Wahrscheinlich möchten Sie das rekursiv machen.

Epilog

Ich würde gerne eine bessere Art und Weise der Verwendung von SBT Caching-Funktion zu sehen. Sollten Sie weitere Informationen erhalten, z. B. von der Mailingliste, senden Sie diese bitte hier.

+0

Ich überarbeite den Code für meinen genauen Fall, aber ich habe es jetzt funktioniert dank Ihnen. Jetzt nur, wenn eine Datei in einem Ordner geändert wird, wird dieser Ordner allein erneut verarbeitet. Ich muss es ein bisschen aufräumen. Ich kann in einem Blog über die gesamte Konfiguration schreiben. –

+0

Bitte poste einen Link zu deinem Beitrag, wenn du es tust. Hier –

+1

ist ein funktionierendes SBT-Plugin-Caching: https://github.com/tlazaro/texture-packer-plugin/blob/71923eab9e4f626a0bdd1dbe8138733a42f474af/src/main/scala/com/starkengine/TexturePackerPlugin.scala#L28 –