Question

How can you redefine a key in SBT (as opposed to extend or define)?

I currently have the following in my build script (project/build.scala):

fullClasspath in Runtime <<= (fullClasspath in Runtime, classDirectory in Compile) map { (cp, classes) => (cp.files map {
  f: File =>
    if (f.getName == classes.getName) {
      val result = new File(f.getParent + File.separator + "transformed-" + f.getName)
      if (result.exists) result else f
    } else f
}).classpath }

It extends the classpath in Runtime by adding, for each directory in Compile, a new directory with the same name but with transformed- prepended to the front.

(If you are wondering why, I have a plugin which performs program transformation on the bytecode after compilation but before packaging, and selective recompilation gets very confused if you overwrite the original files.)

My problem is the following: This extends the original key, and therefore the classpath contains the original directories from Compile, plus the renamed copies, but I only want the renamed ones from Compile.

I tried to do something along the lines of

fullClasspath in Runtime := ...

but I don't know what to put on the right-hand side.


I've marked the answer since it lead me directly to the solution, but my final solution was to modify the above code snippet to the following

fullClasspath in Runtime := (fullClasspath in Runtime).value.files.map {
  f: File =>
    if (f.getName == (classDirectory in Compile).value.getName) {
      val result = new File(f.getParent + File.separator + "transformed-" + f.getName)
      if (result.exists) result else f
    } else f
}.classpath

which does exactly what I wanted, and is slightly better style.

Was it helpful?

Solution

Here's a little experiment I did just now at the sbt command line showing that it's definitely possible to remove something unwanted from fullClasspath:

% sbt
> show runtime:fullClasspath
[info] List(Attributed(.../target/classes),
            Attributed(.../jars/scala-library-2.10.4.jar),
            Attributed(.../jars/asm-all-3.3.1.jar))
> set fullClasspath in Runtime := (fullClasspath in Runtime).value.files.filterNot(_.getName.containsSlice("asm")).classpath
> show runtime:fullClasspath
[info] List(Attributed(.../target/classes),
            Attributed(.../jars/scala-library-2.10.4.jar))

Voila — the "asm-all-3.3.1" entry is gone.

Note that this isn't about <<= vs :=. The latter is just macro-based sugar for the former. The experiment turns out the same if I avoid := and do this instead:

set fullClasspath in Runtime <<= (fullClasspath in Runtime) map
  {_.files.filterNot(_.getName.containsSlice("asm")).classpath}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top