2012-07-24 8 views
5

मेरे पास एक गेम के लिए एक बहु-परियोजना सेटअप है। 'संसाधन' नामक एक बहुत ही विशिष्ट उप परियोजना है जिसमें केवल जार में पैक होने वाली छवियों, ध्वनियों और टेक्साफ़ाइल जैसी फ़ाइलें शामिल हैं।कस्टम कार्य कैसे करें यदि इनपुट फ़ाइलें अपरिवर्तित हों तो कार्य को फिर से शुरू करने से बचें?

मेरे पास एक कस्टम कार्य है जो छवियों को संसाधित करता है और उन्हें पैक करता है। 'Src/main' के अंदर मैं एक फ़ोल्डर 'preprocess' का उपयोग कर रहा हूं जहां छवियों को जाना चाहिए और एक 'अप्रबंधित' फ़ोल्डर जहां सब कुछ जाता है। मेरे कार्य को चलाकर 'प्रीप्रोसेस' में सभी छवियों को पैक किया जाता है और 'संसाधन' के लिए आउटपुट मिलता है और 'अप्रबंधित' में सब कुछ कॉपी किया जाता है।

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 FAQ कैशिंग का समर्थन करता है लेकिन मुझे समझ में नहीं आता कि इसे मेरे कार्य में कैसे अनुकूलित किया जाए।

अगर मैं फ़ोल्डर्स सूची से सबफ़ोल्डर में फ़ाइलों को संशोधित नहीं किया गया तो मैं अपने कस्टम कार्य को फिर से काम करने से कैसे रोक सकता हूं?

उत्तर

5

समाधान

यहां एक समाधान है जो आपको सुइट कर सकता है। हालांकि, मैं पूरी तरह से समझ में नहीं आता कि कैसे काम करता है 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 संशोधनों के लिए जांचता है, और यह सेट में फ़ाइलों के एक में वास्तविक ऑपरेशन का आह्वान करता है। का सही अर्थinStylecached पर तर्क द्वारा निर्धारित किया गया है।

  • cached पर निर्देशिका को सीधे पास करना अच्छा होगा, जैसे कि वास्तविक निर्देशिका को उस निर्देशिका में परिवर्तित होने पर किया जाता है। हालांकि, मुझे संदेह है कि यह वर्तमान में संभव है।

  • मुझे वास्तविक ऑपरेशन द्वारा लौटाई गई फ़ाइलों के सेट के संबंध में व्यवहार नहीं मिलता है (यहां: Set(outJar))। मुझे लगता है कि outStylecached पर तर्क इस से संबंधित है, और मुझे createJarFromFolder होने की उम्मीद है जब भी JAR मौजूद नहीं है (इनपुट फ़ाइलों में परिवर्तनों के बावजूद), लेकिन ऐसा नहीं लगता है। यही है, यदि आप एक JAR फ़ाइल हटाते हैं लेकिन संबंधित निर्देशिका में फ़ाइलों में से किसी एक को नहीं बदलते हैं, तो JAR को पुनर्निर्मित नहीं किया जाएगा।

  • कोड कुछ हद तक डोडी है, क्योंकि यह उस फ़ोल्डर में परिवर्तन होने पर निर्णय लेने के लिए किसी विशेष फ़ोल्डर के शीर्ष पर मौजूद फ़ाइलों को केवल तभी मानता है। आप शायद उस रिकर्सिव बनाना चाहते हैं।

उपसंहार

मैं एसबीटी की कैशिंग सुविधा का उपयोग कर के लिए एक बेहतर तरीका देखने के लिए अच्छा लगेगा। यदि आपको मेलिंग सूची से अधिक जानकारी मिलती है, तो कृपया उन्हें यहां पोस्ट करें।

+0

मैं अपने सटीक मामले के लिए कोड पुनः काम कर रहा हूं लेकिन अब मुझे यह काम मिल रहा है धन्यवाद। अब केवल तभी जब एक फ़ाइल के अंदर एक फ़ाइल संशोधित की जाती है कि फ़ोल्डर को फिर से संसाधित किया जाता है। मुझे इसे थोड़ा साफ करना है। मैं पूरे कॉन्फ़िगरेशन के बारे में ब्लॉग में लिख सकता हूं। –

+0

यदि आप करते हैं तो कृपया अपनी पोस्ट के लिए एक लिंक पोस्ट करें। –

+1

यहाँ एक काम कर एसबीटी प्लगइन का उपयोग कर कैशिंग है: https://github.com/tlazaro/texture-packer-plugin/blob/71923eab9e4f626a0bdd1dbe8138733a42f474af/src/main/scala/com/starkengine/TexturePackerPlugin.scala#L28 –

संबंधित मुद्दे