matt.wilbur (1) [Avatar] Offline
#1
Hi Josh and Matt

I found adding makeVersionProperties to the task list resourceGenerators with += didn't work.
After some digging, <+= seems to do the trick. I've convinced myself why, I think, but any explanation you could give would be great. I had to reason it out with the types.

Also, I'm assume you or your editors will change it, but

1. The reference to jUnit is no longer relevant with the current Chapter 1 using Specs2
2. makeProperitesFile should change to makeVersionsProperties in Figure 2.11
joshua.suereth (60) [Avatar] Offline
#2
Re: resourceGenerators in Chapter 2
Hi, you are correct about Chapter 2 and += vs. <+=.

The reason is a bit convoluted, and will be enlightened more in Chapter 9. Details further below.

As far as the jUnit reference + figure 2.11, I'm currently merging all our source changes from the latest MEAP into master of our examples, and bumping to sbt 0.13.0 release (yay!). I'll sweep through and update references as I go. Thanks much for the feedback.


Now as to why you need to use <+=, the reason is in the types.

All setting are pairings of AttributeKey[T] & Initialize[T] & some scope (in the underlying API). SettingKey[T] is equivalent to AttributeKey[T]. TaskKey[T] is equivalent to AttributeKey[Task[T]], that is: The value inside the key is a "Task" object which can be executed dynamically by sbt.

The sourceGenerators key is a SettingKey[Seq[Task[T]]. That is, a sequence of Task objects which sbt can use to generate sources. It's not a TaskKey, it's a SettingKey containing tasks. This is where some of the magic of the front-level API starts to disappear.

SO, under the covers there is no difference between a SettingKey[Task[T]] and a TaskKey[T]. They both accept an Initialize[Task[T]] as their input when configuring.

So, now let's look at what <+= does. <+= is part of the old API. If you saw the following:

val xmlLibrary = settingKey[ModuleID]("The scala xml ibrary module")

xmlLibrary := "org.scala-lang" % "scala-xml" % scalaVersion.value

libraryDependencies += xmlLibrary.value

That is equivalent to

libraryDependencies <+= xmlLibary

The reason why is that sbt can take any AttributeKey[T] and turn it into an Initialize[T]. The <+= is the old, lower-level API where we had to construct Initialize directly, rather than via a macro.

SO, now for the complication. In the new API the .value "unwraps" the task. For example,

resourceGenerators += makeVersionProperties.value

Does not work, because .value returns a *File* not a Task[File]. We need to access the task from this key. I originally proposed the following for the macro syntax:

resourceGenerators += makeVersionProperties.task


However, the .task method was already taken. Instead, we leverage the old API:

resourceGenerators <+= makeVersionProperties

That's a bit long-winded and entirely not clear, but hopefully it cements some information.


Note: This will be explained, in depth, in Chapter's 9 and 10: Getting Dirty with your Build. This is where we dive into the execution engine and the core abstractions that are "beneath the macro layer". This level of detail is required if you wish to do truly advanced things.

Also note: The fact that you need <+= here is unfortunate. I think there may have been a mechanism I missed in 0.13, I'll see what I can do.
Jacek Laskowski (29) [Avatar] Offline
#3
Re: resourceGenerators in Chapter 2
Hi Josh,

I was about to copy the entire response until after I read that this is going to be part of the upcoming chapters. I'm now looking forward to reading these even more enthusiastically. I'm hoping you won't let us wait too long.

Jacek
eloots (3) [Avatar] Offline
#4
Re: resourceGenerators in Chapter 2
Can you clarify;

I'm reading version 8 of the MEAP and figure 3.13 lists:

resourceGenerators in Compile += makePropertiesFile

makePropertiesFile has not been defined, instead, the code should read:

resourceGenerators in Compile += makeVersionProperties

When adding this modification to the build, it generates an error:

No implicit for Append.Value[Seq[sbt.Task[Seq[java.io.File]]], sbt.TaskKey[Seq[sbt.File]]] found,
so sbt.TaskKey[Seq[sbt.File]] cannot be appended to Seq[sbt.Task[Seq[java.io.File]]]
resourceGenerators in Compile += makeVersionProperties


Changing += to <+= solves this problem as described in the original post.

So, my question: is it your intention to have a reader being able to execute listed code in sequence, and the above is just a mistake, or is the reader supposed to either resolve the issues or wait until he/she has read subsequent chapters that shed more light on this?
Jacek Laskowski (29) [Avatar] Offline
#5
Re: resourceGenerators in Chapter 2
Hi,

I'm sure the authors explain it better, but the answer is surely going to be along the lines that...it's a typo (missing '<') and at least Josh is looking for a better way to express adding a new resourceGenerator without exposing people to the old, lower-level <+= operator. It was in fact already mentioned in the other chapters in the book that the only operators a user should learn are - :=, += and ++=. No other operators are needed to learn about and *all* can be expressed with :=.

Jacek
316326 (1) [Avatar] Offline
#6
j-keck (1) [Avatar] Offline
#7
the syntax for sbt >= 0.13.13 is:

resourceGenerators in Compile += makeVersionProperties.taskValue