Scala 如果输入文件不变,如何使自定义任务避免重做工作?
我有一个游戏的多项目设置。有一个叫做“资源”的非常具体的子项目,它只包含像图像、声音和文本文件这样的文件,这些文件要打包到一个jar中 我有一个自定义任务来处理图像并打包它们。在“src/main”中,我使用了一个文件夹“preprocess”,图像应该放在这个文件夹中,其他所有内容都放在这个“unmanaged”文件夹中。通过运行我的任务,“预处理”中的所有图像都会打包并输出到“资源”,而“非托管”中的所有图像都会按原样复制Scala 如果输入文件不变,如何使自定义任务避免重做工作?,scala,sbt,Scala,Sbt,我有一个游戏的多项目设置。有一个叫做“资源”的非常具体的子项目,它只包含像图像、声音和文本文件这样的文件,这些文件要打包到一个jar中 我有一个自定义任务来处理图像并打包它们。在“src/main”中,我使用了一个文件夹“preprocess”,图像应该放在这个文件夹中,其他所有内容都放在这个“unmanaged”文件夹中。通过运行我的任务,“预处理”中的所有图像都会打包并输出到“资源”,而“非托管”中的所有图像都会按原样复制 val texturePacker = TaskKey[Unit](
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"))
}
val texturePacker=TaskKey[Unit](“纹理打包器”,“运行libgdx的纹理打包器”)
val texturePackerTask=texturePacker:={
println(“包装纹理…”)
val inputDir=file(“resources/src/main/preprocess”)
val outputDir=file(“resources/src/main/resources”)
val folders=inputDir.asFile.listFiles筛选器(u.isDirectory)
println(“子文件夹:+Folders.mkString(“,”))
//下料纹理打包机
用于(子文件夹解决方案)
下面是一个可能适合您的解决方案。但是,我不完全了解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
是否有修改,如果集中的一个文件发生了更改,它将调用实际操作。更改的确切含义由inStyle
参数决定,该参数为cached
- 直接将目录传递给缓存的
会更好,这样,如果目录中的任何内容发生更改,就会执行实际操作。但是,我怀疑目前是否可能这样做
- 我不太了解实际操作返回的文件集的行为(这里:
set(outJar)
)。我假设cached
的outStyle
参数与此相关,我希望在JAR不存在时调用createJarFromFolder
(不管对输入文件的更改如何),但情况似乎并非如此。也就是说,如果您删除了一个JAR文件,但没有更改相应目录中的一个文件,则不会重新创建JAR
- 这段代码有点狡猾,因为在决定某个文件夹中是否发生了更改时,它只考虑位于该文件夹顶部的文件。您可能希望使其递归
后记
我很想找到更好的方法来使用SBT的缓存功能。如果您从邮件列表中获得更多信息,请将其发布到此处。我正在为我的具体情况重新编写代码,但多亏了您,我现在可以正常工作了。现在只有当文件夹中的文件被修改时,该文件夹才能重新处理。我必须稍微清理一下。我可能会在博客中介绍整个配置。如果您这样做,请发布一个链接到您的帖子。下面是一个使用缓存的工作SBT插件:
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)
}