我有一个游戏的多项目设置.有一个非常具体的子项目叫做"资源",只包含要打包到jar中的图像,声音和texfiles等文件.
我有一个自定义任务来处理图像并打包它们.在'src/main'里面,我正在使用一个文件夹'preprocess',其中图像应该去,而'unmanaged'文件夹,其他一切都在这里.通过运行我的任务,'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"))
}
Run Code Online (Sandbox Code Playgroud)
然后在'资源'项目的设置内:
...
packageBin in Compile <<= packageBin in Compile dependsOn(texturePacker)
...
Run Code Online (Sandbox Code Playgroud)
其他子项目依赖于与其运行相关联的packageBin.这样,每当我运行项目时,我都会获得最新的资源状态.我不希望它是按需的.问题是每次运行需要很长时间才能处理.我知道SBT支持缓存SBT常见问题,但我不明白如何使其适应我的任务.
如果未修改文件夹列表中子文件夹中的文件,如何使我的自定义任务避免重做工作?
这是一个可能适合您的解决方案.但是,我并不完全了解如何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)
}
Run Code Online (Sandbox Code Playgroud)
我的理解cached是,它检查inFiles修改,并且如果集合中的一个文件发生了变化,它会调用实际操作.改变的确切含义由inStyle参数决定cached.
直接传递目录会很好cached,这样如果该目录中的任何内容发生变化,就会执行实际操作.但是,我怀疑它目前是否可行.
我不太明白实际操作返回的文件集的行为是什么(这里:) Set(outJar).我假设outStyle参数cached与此相关,并且我希望createJarFromFolder每当JAR不存在时调用(无论输入文件是否有任何变化),但似乎并非如此.也就是说,如果删除JAR文件但不更改相应目录中的某个文件,则不会重新创建JAR.
代码有点狡猾,因为在决定是否在该文件夹中发生更改时,它只考虑特定文件夹顶部的文件.你可能想要递归.
我很想看到使用SBT缓存功能的更好方法.如果您从邮件列表中获得更多信息,请在此处发布.