Reputation: 83273
I can make a Makefile that has a target that processes all sources in the directory.
SOURCE_DIR := src
TARGET_DIR := target
SOURCES := $(wildcard $(SOURCE_DIR)/*)
$(TARGET_DIR)/%: $(SOURCE_DIR)/%
md5sum $^ > $@
all: $(SOURCES:$(SOURCE_DIR)/%=$(TARGET_DIR)/%)
A nice advantage here is that each file is a separate target, so they can be processed incrementally, and concurrently. The concurrent part is important in this situation.
I am trying to something similar with SBT, but am finding it surprisingly difficult. The SBT analog of a Make target sees to be a task, so I try creating one task that aggregate a variable number of smaller tasks.
import org.apache.commons.codec.digest.DigestUtils
all <<= Def.task().dependsOn({
file(sourceDir.value).listFiles.map { source =>
val target = rebase(sourceDir.value, targetDir.value)(f)
Def.task {
IO.write(target, DigestUtils.md5Hex(IO.readBytes(source)))
}
}
}: _*)
I get the error
`value` can only be used within a task or setting macro, such as :=, +=, ++=,
Def.task, or Def.setting
How can I make a proper SBT build file that resembles my Makefile, with a dynamic number of concurrent targets/tasks?
Upvotes: 1
Views: 803
Reputation: 83273
I needed flatMap
.
all <<= (sourceDir, targetDir).flatMap { (sourceDir, targetDir) =>
task{}.dependsOn({
file(sourceDir).listFiles.map { source =>
task {
val target = rebase(sourceDir, targetDir)(f)
IO.write(target, DigestUtils.md5Hex(IO.readBytes(source)))
}
}
}: _*)
}
There might be a slicker way to do task{}.dependsOn(...: _*)
, but I don't know what it is.
Upvotes: 1