I am currently a
lamer in sbt technology. Sbt stands for Simple build tool. This is a
build system that is highly developed, modern and is the de facto
standard build tool in the Scala world. Currently I'm using sbt for
several job tasks and last week I came across a rather unpleasant
problem that probably is very easy to solve for experienced Scala and
sbt developer. I am writing this article to help people with a
similar problem in the future. Sbt has several global settings. One
of this global settings is
baseDirectory.
Depending on the scope, this is the base directory for the build, the
project, the configuration, or the task. You can easy get value of
project base directory from sbt console. Just type
baseDirectory and
you will get the value of this setting.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
georginaumov@georgi:~/Documents/hello$ sbt | |
[info] Loading project definition from /home/georginaumov/Documents/hello/project | |
[info] Set current project to hello (in build file:/home/georginaumov/Documents/hello/) | |
> baseDirectory | |
[info] /home/georginaumov/Documents/hello | |
> |
You can also use inspect baseDirectory and you will get additional information.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
> inspect baseDirectory | |
[info] Setting: java.io.File = /home/georginaumov/Documents/hello | |
[info] Description: | |
[info] The base directory. Depending on the scope, this is the base directory for the build, project, configuration, or task. | |
[info] Provided by: | |
[info] {file:/home/georginaumov/Documents/hello/}root/*:baseDirectory | |
[info] Defined at: | |
[info] (sbt.Defaults) Defaults.scala:177 | |
[info] Dependencies: | |
[info] *:thisProject | |
[info] Reverse dependencies: | |
[info] *:ivyPaths | |
[info] *:sourceDirectory | |
[info] *:printBaseDirectory | |
[info] *:runner | |
[info] *:unmanagedBase | |
[info] *:target | |
[info] Delegates: | |
[info] *:baseDirectory | |
[info] {.}/*:baseDirectory | |
[info] */*:baseDirectory | |
[info] Related: | |
[info] {.}/*:baseDirectory | |
> |
In sbt is a good practice to isolate long tasks into singleton object and keep build.sbt much shorter. This is very cool but in order to have some global settings into this singleton object there are several tricky things that you must to do. The same thing is true if you want to have streams available to the singleton object. My job task involved to process a certain way all the files that meet certain criteria. For this purpose, I had to have baseDirectory for project. When I tried to pass baseDirectory as a method argument in this way:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
printBaseDirectory <<= streams map Tasks.printBaseDirectory(baseDirectory) |
And this:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def printBaseDirectory(baseDir: sbt.File)(streams: TaskStreams): Unit = { | |
streams.log.info("Here I want to print value of baseDirectory") | |
} |
Every time I got error like this:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
error: type mismatch; | |
[error] Type error in expression | |
found : sbt.SettingKey[java.io.File] | |
required: sbt.File | |
(which expands to) java.io.File |
I tried several things. For example to pass baseDirectory.value in this way:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
printBaseDirectory <<= streams map Tasks.printBaseDirectory(baseDirectory.value) |
But I got errors that .value cannot be used in this way.
In the end, I managed to solve the problem with using ".." into the singleton object, that means "the parent directory". But this solution is not good at all.
What will happen if the location of .scala file is changed? I love stackoverflow. Sometimes you can ask and get valuable help and explanations. Also you can answer questions
and thereby helping others. I asked the question and received a helpful guidance. So If you want to have baseDirectory or similar value into singleton object,
you must define the object like this.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import sbt.Keys.TaskStreams | |
import sbt._ | |
object Tasks { | |
def printBaseDirectory(streams: TaskStreams, dir: File): Unit = { | |
streams.log.info(dir.getAbsolutePath) | |
} | |
} |
And into build.sbt this:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
lazy val printBaseDirectory: TaskKey[Unit] = TaskKey[Unit]("printBaseDirectory", "Print baseDirectory for the project", KeyRanks.ATask) | |
printBaseDirectory <<= (streams, baseDirectory) map Tasks.printBaseDirectory |
Or this:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
lazy val printBaseDirectory: TaskKey[Unit] = TaskKey[Unit]("printBaseDirectory", "Print baseDirectory for the project", KeyRanks.ATask) | |
printBaseDirectory := { | |
Tasks.printBaseDirectory(streams.value, baseDirectory.value) | |
} |
I like second solution because looks much clearer.
Няма коментари:
Публикуване на коментар