name: main-template layout: true class: left, top, inverse --- class: center
# Pragmatic SBT
### © 2019 Hermann Hueck
https://github.com/hermannhueck/pragmatic-sbt --- # Abstract This presentation gives a pragmatic introduction to sbt in several examples. Each example is a build in it's own root directory: ./example??. Beginning with very simple sbt examples the later examples are becoming more structured and more complex showing multi-project builds, cross version builds, packaging and publishing, custom *Setting*s and *Task*s and the integration of the Ammonite REPL into your build. We also look at *InputTask*s, *Command*s and plugin development. (This presentation has been developed with sbt 1.2.8 in July 2019. sbt 1.3.0 was RC3 at that time and Scala 2.13.0 was released a few weeks ago.)
Recommended bootstrap tutorial for sbt: - https://www.scala-sbt.org/1.x/docs/sbt-by-example.html To understand the sbt core concepts see this talk by Eugene Yokota: - https://www.youtube.com/watch?v=-shamsTC7rQ --- ## Agenda 1. [sbt without build file](#sbt_without_buildfile) 1. [sbt new](#sbt_new) 1. [Creating an application from the template](#create_application) 1. [Scala REPL](#scala_repl) 1. [Aliases](#aliases) 1. [Plugins](#plugins) 1. [Multi-project Builds](#multi_project_builds) 1. [Cross Builds](#cross_builds) 1. [Version specific source code](#version_specific_source_code) 1. [Library Dependencies](#library_dependencies) 1. [Packaging](#packaging) 1. [Publishing](#publishing) 1. [Installable Packages with *sbt-native-packager*](#installable_packages) 1. [Predefined Settings and Tasks](#predefined_settings_tasks) 1. [Custom Settings and Tasks](#custom_settings_tasks) 1. [Global Settings](#global_settings) 1. [Ammonite REPL](#ammonite_repl) 1. [Input Tasks](#input_tasks) 1. [Commands](#commands) 1. [Plugin Development](#plugin_development) 1. [References](#references) --- class: middle, center name: sbt_without_buildfile # 1. sbt without build file
.footnote[ *.../example01* ] --- ## No build file
sbt uses the same kind of directory structure like Maven and Gradle. We have a Scala/Java source structure in our root directory but no *build.sbt*. ```html example01 $ tree . └── src ├── main │ └── scala │ └── example │ └── HelloApp.scala └── test └── scala └── example └── HelloSpec.scala ``` --
sbt provides a sensible default for every setting. Hence you can use sbt with an empty *build.sbt* or even without *build.sbt* ... --- ## No build file (check versions) ```html example01 $ sbt [warn] No sbt.version set ... [info] Loading settings ... [info] Set current project to example01 ... [info] sbt server started at ... ``` -- ```html sbt:example01> sbtVersion [info] 1.2.8 ``` ```html sbt:example01> scalaVersion [info] 2.12.7 ``` ```html sbt:example01> name [info] example01 ``` ```html sbt:example01> projects [info] In file:.../example01/ [info] * example01 ``` ```html sbt:example01> version [info] 0.1.0-SNAPSHOT ``` --- ## No build file Compile, run, test ... -- ```html sbt:example01> compile [info] Compiling 1 Scala source to .../example01/target/scala-2.12/classes ... [info] Done compiling. [success] Total time: ... ``` ```html sbt:example01> run [info] Packaging .../example01/target/scala-2.12/example01_2.12-0.1.0-SNAPSHOT.jar ... [info] Done packaging. [info] Running example.HelloApp Hello World! ``` ```html sbt:example01> test:compile [info] Compiling 1 Scala source to .../example01/target/scala-2.12/test-classes ... [error] .../example01/src/test/scala/example/HelloSpec.scala:3:12: object scalatest is not a member of package org [error] import org.scalatest._ [error] ^ ``` Test code doesn't compile. The test library is missing. --- ## No build file Add *scalatest* to *libraryDependencies* and test again. -- ```html sbt:example01> set libraryDependencies += "org.scalatest" %% "scalatest" % "3.0.8" % Test [info] Defining libraryDependencies [info] The new value will be used by allDependencies, dependencyPositions, dependencyUpdatesData [info] Reapplying settings... [info] Set current project to example01 (in build file:.../example01/) ``` ```html sbt:example01> test:compile [info] Compiling 1 Scala source to .../example01/target/scala-2.12/test-classes ... [info] Done compiling. ``` ```html sbt:example01> test [info] HelloSpec: [info] The HelloApp object [info] - should say 'Hello World!' [info] Run completed in 368 milliseconds. [info] Total number of tests run: 1 [info] Suites: completed 1, aborted 0 [info] Tests: succeeded 1, failed 0, canceled 0, ignored 0, pending 0 [info] All tests passed. [success] Total time: ... ``` --- ## No build file The '*save session*' command writes manually set settings to a minimal *build.sbt*. -- ```html sbt:example01> session save [info] Reapplying settings... [info] Set current project to example01 (in build file:.../example01/) ``` ```html sbt:example01> exit [info] shutting down server ``` ```html example01 $ cat build.sbt libraryDependencies += "org.scalatest" %% "scalatest" % "3.0.8" % Test ``` ```html example01 $ cat project/build.properties sbt.version=1.2.8 ``` --
###This is a possible but not the usual way to set up an sbt project. --- class: middle, center name: sbt_new # 2. sbt new
.footnote[ *.../example02* ] ---
## sbt new [ gitter8-template ]
quickly sets up a new sbt project using the specified gitter8 template.
Many useful templates for different purposes can be found here: https://github.com/foundweekends/giter8/wiki/giter8-templates --
### *scala/scala-seed.g8* ... a useful template for a simple project setup. --- ```html pragmatic-sbt $ sbt new scala/scala-seed.g8 [info] Set current project to ... A minimal Scala project. name [Scala Seed Project]: example02 Template applied in .../example02 ``` -- ```html pragmatic-sbt $ cd example02 example02 $ tree . ├── build.sbt ├── project │ ├── Dependencies.scala │ └── build.properties └── src ├── main │ └── scala │ └── example │ └── Hello.scala └── test └── scala └── example └── HelloSpec.scala 8 directories, 5 files ``` --- ## Generated files ```scala // project/build.properties sbt.version=1.2.8 ``` ```scala // project/Dependencies.scala import sbt._ object Dependencies { lazy val scalaTest = "org.scalatest" %% "scalatest" % "3.0.8" } ``` ```scala // build.sbt import Dependencies._ ThisBuild / scalaVersion := "2.13.0" ThisBuild / version := "0.1.0-SNAPSHOT" ThisBuild / organization := "com.example" ThisBuild / organizationName := "example" lazy val root = (project in file(".")) .settings( name := "example02", libraryDependencies += scalaTest % Test ) ``` ---
## ThisBuild
Settings in *ThisBuild* are the default settings for subprojects. This saves us from specifying the settings repeatedly in different subprojects.
A subproject can redefine any setting specified in *ThisBuild*. --- class: middle, center name: create_application # 3. Creating an application from the template project
.footnote[ *.../example03* ] --- ## Weather Application The app queries the weather from https://www.metaweather.com/api/ using gigahorse-okhttp as HTTP client and play-json to parse the JSON response. -- ```html example03 $ tree . ├── build.sbt ├── project │ ├── Dependencies.scala │ └── build.properties └── src ├── main │ └── scala │ ├── weather │ │ ├── Weather.scala │ │ └── WeatherApp.scala │ └── weather.sc └── test └── scala └── weather └── WeatherSpec.scala ``` --- ### project/Dependencies.scala ```scala import sbt._ object Dependencies { lazy val playJson = "com.typesafe.play" %% "play-json" % "2.7.3" lazy val okHttp = "com.eed3si9n" %% "gigahorse-okhttp" % "0.5.0" lazy val scalaTest = "org.scalatest" %% "scalatest" % "3.0.5" } ``` ### build.sbt ```scala import Dependencies._ ThisBuild / scalaVersion := "2.12.8" ThisBuild / version := "0.1.0" ThisBuild / organization := "com.example" ThisBuild / organizationName := "example" lazy val root = (project in file(".")) .settings( name := "Example03", libraryDependencies ++= Seq(okHttp, playJson, scalaTest % Test) ) ``` --- ### src/main/scala/weather/WeatherLib.scala ```scala object WeatherLib { def weatherOf(locationName: String, longFormat: Boolean = false) (implicit ec: ExecutionContext): Future[String] = { ??? // some impl } } ``` (tested by: *src/test/scala/weather/WeatherSpec.scala*) ### src/main/scala/weather/WeatherApp.scala ```scala object WeatherApp extends App { import WeatherLib._ implicit val ec: ExecutionContext = ExecutionContext.global def showWeatherOf(location: String): String = { val weather = Await.result(weatherOf(location), 10.seconds) s"\nThe weather in $location is: $weather\n" } println(showWeatherOf("Berlin")) } ``` --- class: middle, center name: scala_repl # 4. Scala REPL
.footnote[ *.../example03* ] --- The **console** command starts a Scala REPL from the sbt prompt with the project dependencies and classes on the classpath. The **initialCommands** setting in *build.sbt* initializes the REPL session - typically used for the imports you need in every session of this project. -- ```scala ThisBuild / initialCommands := """ |import scala.concurrent._ |import scala.concurrent.duration._ |import scala.concurrent.ExecutionContext.Implicits.global |import weather.WeatherLib._ |""".stripMargin ``` -- ```html sbt:Example03> console [info] Starting scala interpreter... Welcome to Scala 2.12.8 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_212). Type in expressions for evaluation. Or try :help. import scala.concurrent._ import scala.concurrent.duration._ import scala.concurrent.ExecutionContext.Implicits.global import weather.WeatherLib._ scala> weatherOf("Berlin") res0: scala.concurrent.Future[String] = Future(
) scala> Await.result(res0, 10.seconds) res1: String = showers ``` --- class: middle, center name: aliases # 5. Aliases
.footnote[ *.../example03* ] --- ## .sbtrc
- Project specific aliases are defined in
**[project_baseDirectory]/.sbtrc**. - User specific aliases (valid in all projects of this user) are defined in
**~/.sbtrc**. --
```scala alias a = alias alias r = reload alias c = compile alias dl = dependencyList ``` ---
```html sbt:Example03> a a = alias r = reload c = compile dl = dependencyList ``` ```html sbt:Example03> r [info] Loading ... [info] Set current project to Example03 (in build file:.../example03/) ``` ```html sbt:Example03> c [info] Compiling 2 Scala sources to .../example03/target/scala-2.12/classes ... [info] Done compiling. [success] Total time: ... ``` ```html sbt:Example03> dl [info] Updating ProjectRef(uri("file:.../example03/"), "root")... [info] Done updating. [warn] There may be incompatibilities among your library dependencies; run 'evicted' to see detailed eviction warnings. [info] com.eed3si9n:gigahorse-core_2.12:0.5.0 [info] com.eed3si9n:gigahorse-okhttp_2.12:0.5.0 [info] com.example:example03_2.12:0.1.0 [info] com.fasterxml.jackson.core:jackson-annotations:2.9.8 [info] com.fasterxml.jackson.core:jackson-core:2.9.8 ... ``` --- class: middle, center name: plugins # 6. Plugins
.footnote[ *.../example03* ] .footnote2[ *https://www.scala-sbt.org/release/docs/Using-Plugins.html* ] ---
## Preinstalled Plugins
Some plugins are already installed and enabled in sbt. The **plugins** command lists the currently installed plugins. --
```html sbt:Example03> plugins In file:.../example03/ sbt.plugins.IvyPlugin: enabled in root sbt.plugins.JvmPlugin: enabled in root sbt.plugins.CorePlugin: enabled in root sbt.ScriptedPlugin sbt.plugins.SbtPlugin sbt.plugins.JUnitXmlReportPlugin: enabled in root sbt.plugins.Giter8TemplatePlugin: enabled in root ``` ---
## User-installed Plugins
- Project specific plugins are installed in
**project/plugins.sbt**. -- - User specific plugins (valid in all projects of this user) are installed in
**~/.sbt/1.0/plugins/plugins.sbt**. --- ## Plugin: *sbt-updates*
shows possible library dependency updates. (This possibly saves you from looking up the latest versions of libraries on mvnrepository.com.) Source code: https://github.com/rtimush/sbt-updates -- ### plugins.sbt ```scala addSbtPlugin("com.timushev.sbt" % "sbt-updates" % "0.4.1") ``` ```html sbt:Example03> dependencyUpdates [info] Found 3 dependency updates for example03 [info] com.typesafe.play:play-json : 2.7.3 -> 2.7.4 [info] org.scala-lang:scala-library : 2.12.8 -> 2.13.0 [info] org.scalatest:scalatest:test : 3.0.5 -> 3.0.8 ``` --- ## Plugin: *sbt-dependency-graph* shows a tree of library dependencies. Source code: https://github.com/jrudolph/sbt-dependency-graph -- ### plugins.sbt ```scala addSbtPlugin("net.virtual-void" % "sbt-dependency-graph" % "0.9.2") ``` ```html sbt:Example03> dependencyTree [info] com.example:example03_2.12:0.1.0 [S] [info] +-com.eed3si9n:gigahorse-okhttp_2.12:0.5.0 [S] [info] | +-com.eed3si9n:gigahorse-core_2.12:0.5.0 [S] [info] | | +-com.typesafe:ssl-config-core_2.12:0.4.0 [S] [info] | | | +-com.typesafe:config:1.3.3 [info] | | | +-org.scala-lang.modules:scala-parser-combinators_2.12:1.1.2 [S] [info] | | | [info] | | +-org.reactivestreams:reactive-streams:1.0.2 [info] | | +-org.slf4j:slf4j-api:1.7.26 [info] | | [info] | +-com.squareup.okhttp3:okhttp:3.14.2 [info] | +-com.squareup.okio:okio:1.17.2 [info] | [info] ... // more dependencies ``` --- ## Plugin: *sbt-sh* enables shell commands from the sbt prompt. Source code: https://github.com/melezov/sbt-sh -- ### plugins.sbt ```scala addSbtPlugin("com.oradian.sbt" % "sbt-sh" % "0.3.0") ``` ```html sbt:Example03> sh ls -l total 8 -rw-r--r-- 1 hermann staff 367 1 Jul 15:55 build.sbt drwxr-xr-x 6 hermann staff 192 2 Jul 12:22 project drwxr-xr-x 4 hermann staff 128 30 Jun 23:04 src drwxr-xr-x 6 hermann staff 192 2 Jul 12:25 target ``` --- ## Plugin: *sbt-git* enables git commands from the sbt prompt.
Fetches dependency jars in parallel. As of sbt 1.3.0 the need to install this plugin disappears.
Coursier will become the default dependency manager already built into sbt. Web site: https://get-coursier.io/docs/sbt-coursier
Source code: https://github.com/coursier/coursier -- ### plugins.sbt ```scala addSbtPlugin("io.get-coursier" % "sbt-coursier" % "1.1.0-M14-4") ``` --- ## Plugin: *sbt-native-packager* enables Java/Scala app packaging in different package formats: zip, dmg (macOS), msi (Windows), deb and rpm (Linux) and docker etc. Sie Chapter 11: [App Packaging](#app_packaging) Web site: https://sbt-native-packager.readthedocs.io/en/stable/
Source code: https://github.com/sbt/sbt-native-packager -- ### project/plugins.sbt ```scala addSbtPlugin("com.typesafe.sbt" % "sbt-native-packager" % "1.3.24") ``` ### build.sbt ```scala enablePlugin(JavaAppPackaging) ``` Unlike many other plugins this one must be enabled explicitly in *build.sbt*.
See: [11. Packaging](#packaging) --- class: middle Having installed all these plugins our plugin list becomes somewhat longer: ```html sbt:Example03> plugins In file:.../example03/ sbt.plugins.IvyPlugin: enabled in root sbt.plugins.JvmPlugin: enabled in root sbt.plugins.CorePlugin: enabled in root sbt.ScriptedPlugin sbt.plugins.SbtPlugin sbt.plugins.JUnitXmlReportPlugin: enabled in root sbt.plugins.Giter8TemplatePlugin: enabled in root coursier.sbtcoursier.CoursierPlugin: enabled in root coursier.sbtcoursiershared.SbtCoursierShared: enabled in root net.vonbuchholtz.sbt.dependencycheck.DependencyCheckPlugin: enabled in root com.typesafe.sbt.GitBranchPrompt com.typesafe.sbt.GitPlugin: enabled in root com.typesafe.sbt.GitVersioning com.timushev.sbt.updates.UpdatesPlugin: enabled in root com.oradian.sbt.SbtShPlugin: enabled in root net.virtualvoid.sbt.graph.DependencyGraphPlugin: enabled in root ``` This list is without *sbt-native-packager*.
This plugin bundle adds a lot more plugins, one for each package format. --- ## Some other useful plugins ### sbt-assembly - create fat JARs - https://github.com/sbt/sbt-assembly ### sbt-scalariform - code formatting using Scalariform - https://github.com/sbt/sbt-scalariform ### new-sbt-scalafmt - code formatting using Scalafmt - https://github.com/lucidsoftware/neo-sbt-scalafmt --
Many more to find at:
https://www.scala-sbt.org/1.x/docs/Community-Plugins.html --- class: middle, center name: multi_project_builds # 7. Multi-project Builds
.footnote[ *.../example04* ] .footnote2[ *https://www.scala-sbt.org/release/docs/Multi-Project.html* ] --- ## Multi-project Build
In *example03* we kept all source code in one sbt project, the "root" project. The *src* directory was located directly under the root directory of the build.
Now we split the code into subprojects - "WeatherLib" and "WeatherApp" - with their own project directories "lib" and "app". The third subproject "root" does not have and does not need a "src" folder of its own. It is the over-arching project which controls the other two. --
Subprojects are (if not specified otherwise) completely independent of each other, i.e: tasks can be executed in parallel.
The subprojects have completely unrelated settings. If a setting is undefined in a subproject, the default setting from *ThisBuild* is used. --- ### Directory tree ```html example04 $ tree . ├── app │ └── src │ └── main │ └── scala │ └── app │ └── WeatherApp.scala ├── lib │ └── src │ ├── main │ │ └── scala │ │ └── libWeather │ │ └── Weather.scala │ └── test │ └── scala │ └── libWeather │ └── WeatherSpec.scala ├── build.sbt └── project ├── Dependencies.scala └── build.properties ``` --- class: middle ### build.sbt (with three subprojects: root, app, lib) ```scala import Dependencies._ ThisBuild / scalaVersion := "2.12.8" ThisBuild / version := "0.1.0" ThisBuild / organization := "com.example" ThisBuild / organizationName := "example" lazy val root = (project in file(".")) .aggregate(app, lib) .settings( name := "Example04", ) lazy val app = (project in file("app")) .dependsOn(lib) .settings( name := "WeatherApp", initialCommands := """ ... // imports """.stripMargin, ) lazy val lib = (project in file("lib")) .settings( name := "WeatherLib", libraryDependencies ++= Seq(okHttp, playJson, scalaTest % Test) ) ``` --- ### .aggregate(...) *root.aggregate(app, lib)* : - Every command issued in "root" is propagated to "app" and "lib". - e.g.: *compile* in "root" triggers *app/compile* and "lib/compile" - *app/compile* and "lib/compile" could be executed in parallel if the subprojects do not depend on each other. -- ### .dependsOn(...) *app.dependsOn(lib)* : - "lib" is part of the classpath of "app". - "lib must be updated and successfully compiled before "app" can be compiled (prevents parallel compilation). -- ### project specific sbt commands: - **projects** lists the projects in the current build. - **project [name]** switches the current project. --- ```html sbt:Example04> projects [info] In file:.../example04/ [info] app [info] lib [info] * root ``` ```html sbt:Example04> project lib [info] Set current project to WeatherLib (in build file:.../example04/) ``` ```html sbt:WeatherLib> projects [info] In file:.../example04/ [info] app [info] * lib [info] root ``` ```html sbt:WeatherLib> compile [info] Compiling 1 Scala source to .../example04/lib/target/scala-2.12/classes ... [info] Done compiling. ``` ```html sbt:WeatherLib> project root [info] Set current project to Example04 (in build file:.../example04/) ``` ```html sbt:Example04> compile [info] Compiling 1 Scala source to .../example04/app/target/scala-2.12/classes ... [info] Done compiling. ``` --- class: middle, center name: cross_builds # 8. Cross Builds
.footnote[ *.../example05* ] .footnote2[ *https://www.scala-sbt.org/release/docs/Cross-Build.html* ] ---
## Using cross-built libraries
We already used cross-built libraries when specifying the *libraryDependencies* with **%%** between group id and artefact id. -- ```scala libraryDependencies += "com.typesafe.play" %% "play-json" % "2.7.4" ``` This automatically appends the current *scalaVersion* to the artefact id.
E.g.: *play-json* becomes *play-json_2.13*. ---
## Creating cross-built libraries
The following *example05* shows how to create cross-built libraries. Cross-building is controlled by the setting **crossScalaVersions**. --- ```scala import Dependencies._ val scala213 = "2.13.0" val scala212 = "2.12.8" val supportedScalaVersions = List(scala213, scala212) ThisBuild / scalaVersion := scala213 ThisBuild / version := "0.1.0" ThisBuild / organization := "com.example" ThisBuild / organizationName := "example" lazy val root = (project in file(".")) .aggregate(app, lib) .settings( name := "Example05", publish / skip := true, // nothing to publish crossScalaVersions := Nil, // set to Nil on the aggregating project ) lazy val app = (project in file("app")) .dependsOn(lib) .settings( name := "WeatherApp", publish / skip := true, // only libraries must be published crossScalaVersions := supportedScalaVersions, initialCommands := """ ... // imports """.stripMargin, ) lazy val lib = (project in file("lib")) .settings( name := "WeatherLib", crossScalaVersions := supportedScalaVersions, libraryDependencies ++= Seq(okHttp, playJson, scalaTest % Test), ) ``` --- ## crossScalaVersions - *crossScalaVersions* is the setting to achive cross-building our source code to different binary Scala versions. - It's value is a Seq of Strings, each containg a valid Scala version like "2.12.8" or "2.13.0". - Skip cross-building in the overarching "root" project which has no source code. (Set *crossScalaVersions* to Nil.) -- ## + and ++ commands - The Scala version can be selected at the sbt prompt with the ++ command, e.g. *++2.12.8* - If the ++ command is followed by a ! you can also switch to a Scala version not listed in *build.sbt*, e.g. *++2.11.12!* - To build against all versions listed in crossScalaVersions, prefix the action to run with +, e.g. *+compile* or *+test*. ---
```html sbt:Example05> scalaVersion [info] app / scalaVersion [info] 2.13.0 [info] lib / scalaVersion [info] 2.13.0 [info] scalaVersion [info] 2.13.0 ``` ```html sbt:Example05> compile [info] Compiling 1 Scala source to .../example05/lib/target/scala-2.13/classes ... [info] Done compiling. [info] Compiling 1 Scala source to .../example05/app/target/scala-2.13/classes ... [info] Done compiling. [success] Total time: ... ``` ```html sbt:Example05> ++2.12.8 -v [info] Setting Scala version to 2.12.8 on 2 projects. [info] Switching Scala version on: [info] lib (2.12.8, 2.13.0) [info] app (2.12.8, 2.13.0) [info] Excluding projects: [info] * root () [info] Reapplying settings... [info] Set current project to Example05 (in build file:.../example05/) ``` ---
```html sbt:Example05> compile [info] Compiling 1 Scala source to .../example05/lib/target/scala-2.12/classes ... [info] Done compiling. [info] Compiling 1 Scala source to .../example05/app/target/scala-2.12/classes ... [info] Done compiling. ``` ```html sbt:Example05> clean ``` ```html sbt:Example05> +compile [info] Setting Scala version to 2.13.0 on 2 projects. [info] ... [info] Compiling 1 Scala source to .../example05/lib/target/scala-2.13/classes ... [info] Done compiling. [info] Compiling 1 Scala source to .../example05/app/target/scala-2.13/classes ... [info] Done compiling. ... [info] Setting Scala version to 2.12.8 on 2 projects. [info] ... [info] Compiling 1 Scala source to .../example05/lib/target/scala-2.12/classes ... [info] Done compiling. [info] Compiling 1 Scala source to .../example05/app/target/scala-2.12/classes ... [info] Done compiling. ... ``` --- ```html sbt:Example05> project lib [info] Set current project to WeatherLib (in build file:.../example05/) ``` ```html sbt:WeatherLib> ++2.11.12! compile [info] Forcing Scala version to 2.11.12 on all projects. [info] Reapplying settings... [info] Set current project to WeatherLib (in build file:.../example05/) [info] Compiling 1 Scala source to .../example05/lib/target/scala-2.11/classes ... [info] Done compiling. [success] Total time: ... ``` -- The class files are compiled to version specific subdirectories of the *target* directories. ```html example05 $ tree lib/target/scala-* lib/target/scala-2.11 └── classes └── libWeather └── *.class lib/target/scala-2.12 └── classes └── libWeather └── *.class lib/target/scala-2.13 └── classes └── libWeather └── *.class ``` --- class: middle, center name: version_specific_source_code # 9. Version specific source code
.footnote[ *.../example06* ] --- ## Version specific code locations
If you have source files for different Scala versions, place them into different versions specific source directories, e.g.: - *src/main/scala* for code common to all Scala versions - *src/main/scala-2.12* for code specific to Scala 2.12.x - *src/main/scala-2.13* for code specific to Scala 2.13.x -- ```html example06 $ tree app/src app/src └── main ├── scala │ └── app │ └── WeatherBase.scala ├── scala-2.12 │ └── app │ └── WeatherApp.scala └── scala-2.13 └── app └── WeatherApp.scala ``` --- *src/main/scala/app/WeatherBase.scala* ```scala class WeatherBase { import libWeather.Weather._ implicit val ec: ExecutionContext = ExecutionContext.global def showWeatherOf(location: String): String = { val scalaVersion = util.Properties.versionString val weather = Await.result(weatherOf(location), 10.seconds) s"\nScala $scalaVersion:\nThe weather in $location is: $weather\n" } } ```
*src/main/scala-2.12/app/WeatherApp.scala* ```scala object WeatherApp extends WeatherBase with App { println(showWeatherOf("Berlin")) } ```
*src/main/scala-2.13/app/WeatherApp.scala* ```scala object WeatherApp extends WeatherBase with App { import scala.util.chaining._ showWeatherOf("Berlin") tap println } ``` --- class: middle, center name: library_dependencies # 10. Library Dependencies
.footnote[ *.../example07* ] .footnote2[ *https://www.scala-sbt.org/release/docs/Library-Dependencies.html* ] ---
## Unmanaged dependencies
Create a directory named ***lib*** under your subproject's root and put the jars you need into it. sbt will add these jars to your subproject's classpath. This way of adding library dependencies is very uncommon, but may be useful in some situations. --- ## Managed dependencies
This is the usual way to define dependencies. We used it already in the first example. You have to specify the setting **libraryDependencies** which takes a *Seq[ModuleId]*. Each *ModuleId* consists of a groupId, artefactId and revision joined with the %-operator and optionally followed by a configuration such as *"test"* or *Test* (the type-safe way). When using the %%-operator between groupId and artefactId sbt automatically detects the right binary Scala version of the library from the current setting of ***scalaVersion***. --
```scala // gigahorse-okhttp for binary Scala version 2.12.x libraryDependencies += "com.eed3si9n" % "gigahorse-okhttp_2.12" % "0.5.0" ``` ```scala // gigahorse-okhttp using the current scalaVersion setting libraryDependencies += "com.eed3si9n" %% "gigahorse-okhttp" % "0.5.0" ``` --- ## Flexible Ivy revisions
Ending the revision number with a + selects the latest available subrevision of a library. ```scala // gigahorse-okhttp using the latest 0.5.x revision for the current scalaVersion libraryDependencies += "com.eed3si9n" %% "gigahorse-okhttp" % "0.5.+" ``` --
You may also specifiy *"latest.release"*, *"latest.milestone"* or *"latest.integration"* instead of a revision number. ```scala // depend on the latest avilable release of the gigahorse-okhttp module libraryDependencies += "com.eed3si9n" %% "gigahorse-okhttp" % "latest.release" ``` ```scala // depend on the latest avilable integration (release or milestone) of the gigahorse-okhttp module libraryDependencies += "com.eed3si9n" %% "gigahorse-okhttp" % "latest.integration" ``` --
See also: https://ant.apache.org/ivy/history/2.3.0/ivyfile/dependency.html#revision --- ## Resolvers Resolvers is a Seq of (local or remote) locations looked up by sbt when resolving library dependencies. -- ## Default Resolvers Some resolvers are predefined by default. (Hence we don't need to define resolvers in many cases.) - the Maven2 repository at *https://repo1.maven.org/maven2/* - the local sbt cache at **~/.sbt/preloaded** - jars published locally to Ivy at **~/.ivy/local** - the project resolver which resolves inter-project dependencies, e.g. the dependency between the *app* and *lib* subprojects The default resolvers can be listed in a quite weird format with
**show externalResolvers** To change or remove the default resolvers, you would need to override **externalResolvers**. --- ## User-defined Resolvers To add your own resolvers to the default ones, use the setting **resolvers**. To add an additional repository, use ```html resolvers += "name" at "location" ``` -- ### Examples ```html resolvers += "Local Maven Repository" at "file://"+Path.userHome.absolutePath+"/.m2/repository" ``` ```html resolvers += "Sonatype OSS Public" at "https://oss.sonatype.org/content/repositories/public" ``` ```scala // using a predefined shortcut for the "Sonatype public" repo resolvers += Resolver.sonatypeRepo("public") ``` ```html resolvers += "Typesafe Releases" at "https://repo.typesafe.com/typesafe/releases" ``` ```scala // using a predefined shortcut for the "Typesafe releases" repo resolvers += Resolver.typesafeRepo("releases") ``` --- class: middle, center name: packaging # 11. Packaging
.footnote[ *.../example07* ] ---
## Commands for package generation
sbt comes with some commands for the generation of packages (jar files). - *packageBin* Produces a binary jar. - *packageSrc* Produces a jar containing sources and resources. - *packageDoc* Produces a jar containing API documentation. - *package* Is an alias for *packageBin*. These commands generate jar files under
**[subproject_root]/target/scala-[scalaVersion]** In a cross build project all commands can be prefixed with **+** in order to package jars for all supported scala versions of the build. ---
```html sbt:Example07> project lib [info] Set current project to WeatherLib (in build file:.../example07/) ``` ```html sbt:WeatherLib> packageBin [info] Packaging .../example07/lib/target/scala-2.13/weatherlib_2.13-0.1.0.jar ... [info] Done packaging. ``` ```html sbt:WeatherLib> packageSrc [info] Packaging .../example07/lib/target/scala-2.13/weatherlib_2.13-0.1.0-sources.jar ... [info] Done packaging. ``` ```html sbt:WeatherLib> packageDoc [info] Main Scala API documentation to .../example07/lib/target/scala-2.13/api... model contains 3 documentable templates [info] Main Scala API documentation successful. [info] Packaging .../example07/lib/target/scala-2.13/weatherlib_2.13-0.1.0-javadoc.jar ... [info] Done packaging. ``` ```html example07 $ ls -1 lib/target/scala-2.13/*.jar lib/target/scala-2.13/weatherlib_2.13-0.1.0-javadoc.jar lib/target/scala-2.13/weatherlib_2.13-0.1.0-sources.jar lib/target/scala-2.13/weatherlib_2.13-0.1.0.jar ``` --- class: middle, center name: publishing # 12. Publishing
.footnote[ *.../example07* ] .footnote2[ *https://www.scala-sbt.org/1.x/docs/Publishing.html* ] ---
## Local Publishing
- Using the command **publishLocal** you can publish a jar (typically a library jar) to the local Ivy repository under **~/.ivy2/local**. - Using the command **publishM2** you can publish a jar (typically a library jar) to the local Maven2 repository under **~/.m2/repository**. - **publishMavenStyle** is *true* (default) if the jars are published in Maven style (with a pom file) or *false* if the Ivy style is used. ---
```html sbt:Example07> project lib [info] Set current project to WeatherLib (in build file:.../example07/) ``` ```html sbt:WeatherLib> publishMavenStyle [info] true ``` ```html sbt:WeatherLib> publishLocal [info] Writing Ivy file .../example07/lib/target/scala-2.13/resolution-cache/com.example/weatherlib_2.13/0.1.0/resolved.xml.xml [info] Wrote .../example07/lib/target/scala-2.13/weatherlib_2.13-0.1.0.pom [info] :: delivering :: com.example#weatherlib_2.13;0.1.0 :: 0.1.0 :: release :: Fri Jul 05 19:38:22 CEST 2019 [info] delivering ivy file to .../example07/lib/target/scala-2.13/ivy-0.1.0.xml [info] published weatherlib_2.13 to ~/.ivy2/local/com.example/weatherlib_2.13/0.1.0/poms/weatherlib_2.13.pom [info] published weatherlib_2.13 to ~/.ivy2/local/com.example/weatherlib_2.13/0.1.0/jars/weatherlib_2.13.jar [info] published weatherlib_2.13 to ~/.ivy2/local/com.example/weatherlib_2.13/0.1.0/srcs/weatherlib_2.13-sources.jar [info] published weatherlib_2.13 to ~/.ivy2/local/com.example/weatherlib_2.13/0.1.0/docs/weatherlib_2.13-javadoc.jar [info] published ivy to ~/.ivy2/local/com.example/weatherlib_2.13/0.1.0/ivys/ivy.xml ``` --- class: middle ## Publishing to a resolver (ie.e to a remote repo)
To publish a jar to a remote repo (in Maven style or in Ivy style) ... - define the resolver (the destination to publish to) with the **publishTo** setting - add the credentials for that resolver to the **credentials** setting - (or alternatively and preferably - load the credentials from a properties file) - run the **publish** command --- ## What to publish? Publishing makes only sense for libraries, not for applications. To prevent a subproject from being published add the setting:
**publish / skip := true** -- ```scala ... lazy val root = (project in file(".")) .aggregate(app, lib) .settings( name := "Example05", publish / skip := true, // no code to publish ... ) lazy val app = (project in file("app")) .dependsOn(lib) .settings( name := "WeatherApp", publish / skip := true, // no need to publish the app ... ) lazy val lib = (project in file("lib")) .settings( name := "WeatherLib", // the library project should be published ... ) ``` --- class: middle, center name: installable_packages # 13. Installable Packages # with *sbt-native-packager*
.footnote[ *.../example08* ] .footnote2[ *https://sbt-native-packager.readthedocs.io/* ] ---
## Library or App?
If you write a library you have to publish it to a public repo so that others can use it as a library dependency. This can be done with sbt without additional plugin. --
If you write an application you have to generate a installable package in the format of the intended destination system, e.g. a Debian package for Debian or Ubuntu Linux or an MSI package for Windows or a Docker image or some other installable format. The **sbt-native-packager** plugin allows you to create a software distribution of an application and supports many formats. --- class: middle ## Enable JavaAppPackaging
### project/plugins.sbt ```scala addSbtPlugin("com.typesafe.sbt" % "sbt-native-packager" % "1.3.24") ``` ### build.sbt ```scala lazy val app = (project in file("app")) .dependsOn(lib) .enablePlugins(JavaAppPackaging) .settings( ... ) ``` The plugin must be enabled for the project you want to package. --- ## Staging The **stage** command creates a local directory ( *.../target/universal/stage* ) with all the files laid out as required in the final distribution. -- ```html sbt:Example08> project app [info] Set current project to WeatherApp (in build file:.../example08/) ``` ```html sbt:WeatherApp> stage [info] Packaging ... ``` -- ```html example08 $ tree app/target/universal/stage app/target/universal/stage ├── bin │ ├── weatherapp │ └── weatherapp.bat └── lib ├── com.eed3si9n.gigahorse-core_2.13-0.5.0.jar ├── com.eed3si9n.gigahorse-okhttp_2.13-0.5.0.jar ├── com.example.weatherapp-0.1.0.jar ├── com.example.weatherlib-0.1.0.jar ├── com.fasterxml.jackson.core.jackson-annotations-2.9.8.jar ├── ... └── org.slf4j.slf4j-api-1.7.26.jar ``` ---
## Start Scripts *bin/weatherapp* can start the application on Mac and Linux.
*bin/weatherapp.bat* can start the application on Windows. ```html example08 $ app/target/universal/stage/bin/weatherapp Scala version 2.13.0: The weather in Berlin is: light rain example08 $ ``` -- ## Setting: maintainer The following packaging commands require a **maintainer** setting in the build.
Otherwise sbt would issue a warning: "The maintainer is empty" ```scala maintainer :=<EMAIL_ADDRESS>``` --- ## Zip distribution The **universal:packageBin** command creates a zip file containg all staged files. The **dist** command achieves the same. -- ```html sbt:WeatherApp> universal:packageBin [info] ... [info] Your package is ready in .../example08/app/target/universal/weatherapp-0.1.0.zip ``` -- ```html example08 $ unzip -l app/target/universal/weatherapp-0.1.0.zip Archive: app/target/universal/weatherapp-0.1.0.zip Length Date Time Name --------- ---------- ----- ---- 5007 07-06-2019 00:16 weatherapp-0.1.0/lib/com.example.weatherapp-0.1.0.jar 6357 07-05-2019 23:22 weatherapp-0.1.0/lib/com.example.weatherlib-0.1.0.jar 33391 12-16-2018 00:06 weatherapp-0.1.0/lib/com.fasterxml.jackson.datatype.jackson-datatype-jdk8-2.9.8.jar 42704 06-19-2019 02:15 weatherapp-0.1.0/lib/com.eed3si9n.gigahorse-okhttp_2.13-0.5.0.jar 160144 06-19-2019 02:15 weatherapp-0.1.0/lib/com.eed3si9n.gigahorse-core_2.13-0.5.0.jar 425763 05-19-2019 19:38 weatherapp-0.1.0/lib/com.squareup.okhttp3.okhttp-3.14.2.jar ... 726698 06-12-2019 12:45 weatherapp-0.1.0/lib/com.typesafe.play.play-json_2.13-2.7.4.jar 10567 07-06-2019 00:33 weatherapp-0.1.0/bin/weatherapp 6317 07-06-2019 00:33 weatherapp-0.1.0/bin/weatherapp.bat --------- ------- 14304396 23 files ``` --- ## Gzipped tarball distribution The **universal:packageZipTarball** command creates a tgz file containg all the files staged. -- ```html sbt:WeatherApp> universal:packageZipTarball [info] ... Making /var/folders/.../weatherapp-0.1.0/bin/weatherapp executable Making /var/folders/.../weatherapp-0.1.0/bin/weatherapp.bat executable Running with tar -pcvf /var/folders/zg/1y5syxvj0mb5v3v0p0m8mhnc0000gn/T/sbt_68ba81f2/weatherapp-0.1.0.tar weatherapp-0.1.0 a weatherapp-0.1.0 a weatherapp-0.1.0/bin a weatherapp-0.1.0/lib a weatherapp-0.1.0/lib/com.squareup.okio.okio-1.17.2.jar ... a weatherapp-0.1.0/bin/weatherapp a weatherapp-0.1.0/bin/weatherapp.bat [success] Total time: ... ``` -- ```html example08 $ unzip -l app/target/universal/weatherapp-0.1.0.zip HermannMBP:example08 hermann$ tar -tzf app/target/universal/weatherapp-0.1.0.tgz weatherapp-0.1.0/ weatherapp-0.1.0/bin/ weatherapp-0.1.0/lib/ weatherapp-0.1.0/lib/com.squareup.okio.okio-1.17.2.jar ... weatherapp-0.1.0/bin/weatherapp weatherapp-0.1.0/bin/weatherapp.bat ``` --- ## OSX DMG distribution The **universal:packageOsxDmg** command creates a dmg file for macOS. -- ```html sbt:WeatherApp> universal:packageOsxDmg [info] ... created: .../example08/app/target/universal/weatherapp-0.1.0.dmg /dev/disk3 GUID_partition_scheme /dev/disk3s1 Apple_HFS .../example08/app/target/universal/dmg/weatherapp-0.1.0 "disk3" ejected. [success] Total time: ... ``` -- ```html example08 $ hdiutil mount app/target/universal/weatherapp-0.1.0.dmg /dev/disk3 GUID_partition_scheme /dev/disk3s1 Apple_HFS /Volumes/weatherapp-0.1.0 ``` ```html example08 $ tree /Volumes/weatherapp-0.1.0 /Volumes/weatherapp-0.1.0 ├── bin │ ├── weatherapp │ └── weatherapp.bat └── lib ├── com.eed3si9n.gigahorse-okhttp_2.13-0.5.0.jar ├── com.example.weatherapp-0.1.0.jar ├── com.example.weatherlib-0.1.0.jar ├── ... ``` --- ## Dockerize the App The command **docker:publishLocal** creates a docker image with the app. -- ```html sbt:WeatherApp> docker:publishLocal ... [info] Sending build context to Docker daemon 14.33MB [info] Step 1/15 : FROM openjdk:8 as stage0 [info] ---> b8d3f94869bb ... [info] Step 15/15 : CMD [] [info] ---> Running in a1e6517b25a4 [info] Removing intermediate container a1e6517b25a4 [info] ---> 96d21665e894 [info] Successfully built 96d21665e894 [info] Successfully tagged weatherapp:0.1.0 [info] Built image weatherapp with tags [0.1.0] [success] Total time: ... ``` -- ```html example08 $ docker run weatherapp:0.1.0 Scala version 2.13.0: The weather in Berlin is: light rain ``` ---
## Archetypes sbt-native-packager supports many more archetypes and formats. - These examples used the *JavaAppPackaging* archtype. - For Java server apps you shold use the *JavaServerAppPackaging* archtype. -- ## General idea The general idea is "native packaging".  Predefined Settings and Tasks
.footnote[ *.../example08* ] .footnote2[ *https://www.scala-sbt.org/release/docs/Basic-Def.html* ] --- ## Keys There are three flavours of keys reflected in three different key types: - **SettingKey[T]**: a key for a value computed once (the value is computed when loading the subproject and kept around until *reload*). - **TaskKey[T]**: a key for a value, called a task, that has to be recomputed each time, potentially with side effects. - **InputKey[T]**: a key for a task that has command line arguments as input.  ---
## Display predefined Settings
A setting can be displayed by just invoking the setting's name at the sbt prompt. (You can also precede the settings name with the **show** command.) --
```html sbt:Example08> project lib [info] Set current project to WeatherLib (in build file:.../example08/) ``` ```html sbt:WeatherLib> show name [info] WeatherLib ``` ```html sbt:WeatherLib> libraryDependencies [info] * org.scala-lang:scala-library:2.13.0 [info] * com.eed3si9n:gigahorse-okhttp:0.5.+ [info] * com.typesafe.play:play-json:2.7.+ [info] * org.scalatest:scalatest:3.0.+:test ``` ---
## Maniplulating the value of a setting
Values of settings are typically defined in the build file (*build.sbt*). They can also be set at the command prompt with the **set** command. --
```html sbt:WeatherLib> set libraryDependencies += "org.typelevel" %% "cats-core" % "1.6.1" [info] Defining libraryDependencies [info] The new value will be used by allDependencies, dependencyPositions, dependencyUpdatesData [info] Reapplying settings... [info] Set current project to WeatherLib (in build file:.../example08/) ``` ```html sbt:WeatherLib> libraryDependencies [info] * org.scala-lang:scala-library:2.13.0 [info] * com.eed3si9n:gigahorse-okhttp:0.5.+ [info] * com.typesafe.play:play-json:2.7.+ [info] * org.scalatest:scalatest:3.0.+:test [info] * org.typelevel:cats-core:1.6.1 ``` ---
## List available settings
- **settings**: shows a list of the most common predefined settings - **settings -v**: extends that list - **settings -vv**: extends that list further - **settings -vvv**: extends that list even more - **settings -V**: displays all available settings ---
## Predefined Tasks
Tasks (like *compile*, *test* or *packageBin*) are mostly predefined in sbt. But they can be redefined in the build file (*build.sbt*). A task containes executable code. To display its result you have to run it. Just running a task does not show it#s result. To run it and to see the result invoke it with **show**. --
```html sbt:WeatherLib> compile [success] Total time: ... ``` ```html sbt:WeatherLib> show compile [info] Analysis: 1 Scala source, 3 classes, 5 binary dependencies [success] Total time: ... ``` ---
## List available tasks
- **tasks**: shows a list of the most common predefined tasks - **tasks -v**: extends that list - **tasks -vv**: extends that list further - **tasks -vvv**: extends that list even more - **tasks -V**: displays all available tasks --- class: middle, center name: custom_settings_tasks # 15. Custom Settings and Tasks
.footnote[ *.../example09* ] .footnote2[ *https://www.scala-sbt.org/release/docs/Custom-Settings.html* ] --- ## Custom Settings Define your own setting with **settingKey[T]**. ```scala val sampleStringSetting: SettingKey[String] = settingKey[String]("A sample string setting.") val sampleIntSetting: SettingKey[Int] = settingKey[Int]("A sample int setting.") ThisBuild / organization := "com.example" ThisBuild / version := "0.1.0-SNAPSHOT" ThisBuild / scalaVersion := "2.13.0" lazy val root = (project in file(".")) .settings( name := "Example9a", sampleStringSetting := { println(">>> Executing sampleStringSetting ...") System.getProperty("java.home") }, sampleIntSetting := { println(">>> Executing sampleIntSetting ...") val sum = 1 + 2 println("sum: " + sum) sum }, ) ``` ---
```html example09aCustomSettings $ sbt ... [success] Total time: ... [info] Loading settings for project root from build.sbt ... >>> Executing sampleStringSetting ... >>> Executing sampleIntSetting ... sum: 3 [info] Set current project to Example9a (in build file:.../ex09aCustomSettings/) ``` ```html sbt:Example9a> sampleStringSetting [info] /Library/Java/JavaVirtualMachines/jdk1.8.0_212.jdk/Contents/Home/jre ``` ```html sbt:Example9a> sampleIntSetting [info] 3 ``` --- ## Custom Tasks Define your own task with **taskKey[T]**. ```scala val sampleStringTask: TaskKey[String] = taskKey[String]("A sample string task.") val sampleIntTask: TaskKey[Int] = taskKey[Int]("A sample int task.") ThisBuild / organization := "com.example" ThisBuild / version := "0.1.0-SNAPSHOT" ThisBuild / scalaVersion := "2.12.8" lazy val root = (project in file(".")) .settings( name := "Example9b", sampleStringTask := { println(">>> Executing sampleStringTask ...") System.getProperty("java.home") }, sampleIntTask := { println(">>> Executing sampleIntTask ...") val sum = 1 + 2 println("sum: " + sum) sum }, )``` ---
```html example09bCustomTasks $ sbt ... [success] Total time: ... [info] Loading settings for project root from build.sbt ... [info] Set current project to Example9b (in build file:.../example09bCustomTasks/) ``` ```html sbt:Example9b> sampleStringTask >>> Executing sampleStringTask ... [success] Total time: ... ``` ```html sbt:Example9b> show sampleStringTask >>> Executing sampleStringTask ... [info] /Library/Java/JavaVirtualMachines/jdk1.8.0_212.jdk/Contents/Home/jre [success] Total time: ... ``` ```html sbt:Example9b> sampleIntTask >>> Executing sampleIntTask ... sum: 3 [success] Total time: ... ``` ```html sbt:Example9b> show sampleIntTask >>> Executing sampleIntTask ... sum: 3 [info] 3 [success] Total time: ... ``` --- ## Execution semantics of tasks
If you do **not** invoke **.value** on another task all lines inside the task implementation will be invoked sequentially, e.g. in the *sampleIntTask* from the previous example. ```scala sampleIntTask := { println(">>> Executing sampleIntTask ...") val sum = 1 + 2 println("sum: " + sum) sum } ``` --
This is no longer true if you invoke **.value** on another task. - **.value** expresses a **task dependency**. - *x := y.value* means: Task *x* depends on task (or setting) *y*. - If Task *A* depends on the Tasks *B* and *C*, *B* and *C* are executed **in parallel**, but Task *A* is executed when *B* and *C* have finished. - Dependent tasks are **deduplicated**. ---
## Rules
- A task may depend on a task or a setting. - A setting may depend on another setting. - A setting never depends on a task. --- ```scala val startServer = taskKey[Unit]("start server") val stopServer = taskKey[Unit]("stop server") val sampleIntTask = taskKey[Int]("A sample int task.") val sampleStringTask = taskKey[String]("A sample string task.") ... lazy val root = (project in file(".")) .settings( name := "Example9c", startServer := { println("starting...") Thread.sleep(500) }, stopServer := { println("stopping...") Thread.sleep(500) }, sampleIntTask := { startServer.value // This line is invoked BEFORE the other statements val sum = 1 + 2 println("sum: " + sum) stopServer.value // !!! This line is invoked BEFORE the other statements sum }, sampleStringTask := { startServer.value // This line is invoked BEFORE the other statements val s = sampleIntTask.value.toString // This line is invoked BEFORE the other statements println("s: " + s) s } ) ``` --- ```html example09cExecutionSemanticsOfTasks $ sbt ... [info] Set current project to Example9c (in build file:.../example09cExecutionSemanticsOfTasks/) ``` ```html sbt:Example9c> sampleIntTask stopping... starting... sum: 3 [success] Total time: ... ``` ```html sbt:Example9c> sampleStringTask stopping... starting... sum: 3 s: 3 [success] Total time: ... ``` -- - *startServer* and *stopServer* are invoked before any other statement of *sampleIntTask*, because *sampleIntTask* depends on those other tasks. - *startServer* and *stopServer* are executed in parallel as these tasks do not depend on each other. Hence you might see the output of *startServer* before the output *stopServer* or vice versa. - *sampleStringTask* depends 2 x on *startServer* (once directly and once via *simpleIntTask*). But *startServer* is executed only once. sbt deduplicates task execution. --- ## Visualize dependencies with *inspect* ```html sbt:Example9c> inspect sampleIntTask [info] Task: Int ... [info] Dependencies: [info] stopServer [info] startServer ... ``` ```html sbt:Example9c> inspect sampleStringTask [info] Task: java.lang.String ... [info] Dependencies: [info] sampleIntTask [info] startServer ... ``` ```html sbt:Example9c> inspect tree sampleStringTask [info] sampleStringTask = Task[java.lang.String] [info] +-sampleIntTask = Task[Int] [info] | +-startServer = Task[Unit] [info] | +-stopServer = Task[Unit] [info] | [info] +-startServer = Task[Unit] ``` ---
## Task Graph
All tasks of a build form a **task graph** that doesn't allow cycles - a directed acyclic graph (DAG) of tasks where the edges denote a **happens-before** relationship . More examples illustrate this in: https://www.scala-sbt.org/release/docs/Task-Graph.html --- class: middle, center name: global_settings # 16. Global Settings
.footnote[ *https://www.scala-sbt.org/release/docs/Global-Settings.html* ] ---
### build.sbt (or any other file suffixed with *.sbt*) - Local settings go into **./build.sbt** in the project's base directory. - Global settings used in all projects are located in **~/.sbt/1.0/global.sbt**. - *build.sbt* and *global.sbt* are just naming conventions. Any other name suffixed with *.sbt* is allowed. -- ### Plugins - Local plugins are defined in **./project/plugins.sbt**. - Global plugins are defined in **~/.sbt/1.0/plugins/plugins.sbt**. -- ### Startup commands (like alias definitions) - Local startup commands go into **.sbtrc** in the project's base directory. - Global startup commands go into **~/.sbtrc**. --- ## Unifying sbt history
- With the **!:** command you can display sbt's command history. - By default every subproject (*root*, *app*, *lib*) has it's own history
(saved in it's own history file). --
- To unify the history of all files let **historyPath** point to the same file. - To have this feature available in all projects we do this globally in ... --
### ~/.sbt/1.0/global.sbt ```scala historyPath := Some( (target in LocalRootProject).value / ".history") cleanKeepFiles -= (target in LocalRootProject).value / ".history" ``` --- class: middle, center name: ammonite_repl # 17. Ammonite REPL
.footnote[ *http://ammonite.io/#SBTIntegration* ] --- Ammonite is a very powerful Scala REPL. Let's make it available in sbt (like the Scala console) in all our projects... -- ### ~/.sbt/1.0/global.sbt ```scala libraryDependencies += "com.lihaoyi" % "ammonite" % "1.6.9" % "test" cross CrossVersion.full Test / sourceGenerators += Def.task { val file = (Test / sourceManaged).value / "amm.scala" IO.write(file, """object amm extends App { ammonite.Main.main(args) }""") Seq(file) }.taskValue addCommandAlias("amm", "Test/runMain amm") ``` -- ```html sbt:Example08> amm [info] Running amm Loading... Compiling (synthetic)/ammonite/predef/interpBridge.sc Compiling (synthetic)/ammonite/predef/replBridge.sc Compiling (synthetic)/ammonite/predef/sourceBridge.sc Compiling (synthetic)/ammonite/predef/frontEndBridge.sc Compiling (synthetic)/ammonite/predef/DefaultPredef.sc Welcome to the Ammonite Repl 1.6.9 (Scala 2.13.0 Java 1.8.0_212) If you like Ammonite, please support our development at www.patreon.com/lihaoyi @ val x = 2 + 3 x: Int = 5 ``` --- class: middle, center name: input_tasks # 18. Input Tasks
.footnote[ *example10a*, *example10b* ] .footnote2[ *https://www.scala-sbt.org/release/docs/Input-Tasks.html* ] ---
## InputTask Input Tasks take command line arguments as input. They parse user input and produce a task to run. -- ## Overview of Keys There are three flavours of keys reflected in three key types: - **SettingKey[T]**: a key for a value computed once (the value is computed when loading the subproject and kept around until reload). - **TaskKey[T]**: a key for a value, called a task, that has to be recomputed each time, potentially with side effects. - **InputKey[T]**: a key for a task that has command line arguments as input. --- ```scala // build.sbt ... val demo = inputKey[Unit]("A demo input task.") demo := { import complete.DefaultParsers._ println(">>> Current Scala version:") println(scalaVersion.value) // access a setting val args: Seq[String] = spaceDelimited("
").parsed // get parsed result println(">>> Arguments to demo:") args foreach println } ``` --
```html sbt:Example10a> demo these are the args ! >>> Current Scala version: 2.12.8 >>> Arguments to demo: these are the args ! ``` --- ## Shell commands implemented with InputTask ```scala // build.sbt ... lazy val shellTask = inputKey[Int]("Execute a shell command") shellTask := { import complete.DefaultParsers._ import scala.language.postfixOps import scala.sys.process._ val args: Seq[String] = spaceDelimited("
").parsed val commandLine = args.mkString(" ") Process(Seq("/bin/sh", "-c", commandLine)) ! } addCommandAlias("sh", "shellTask") ``` --
```html sbt:Example10b> sh find . -name *.class | wc -l 14 ``` --- class: middle, center name: commands # 19. Commands
.footnote[ *example11a*, *example11b* ] .footnote2[ *https://www.scala-sbt.org/release/docs/Commands.html* ] ---
## What is a “command”?
The docs say: A “command” looks similar to a task: it’s a named operation that can be executed from the sbt console. However, a command’s implementation takes as its parameter the entire state of the build (represented by *State*) and computes a new state. This means that a command can look at or modify other sbt settings, for example. Typically, you would resort to a command when you need to do something that’s impossible in a regular task. --
The most general command takes ... - a name: the name with wich the command is to be invoked - a parser: used to parse the user input after the command name - an action to be executed which takes the current build state and turns it to the next state: *(State, T) => State* --- ```scala // project/DemoCommand.scala import sbt._, Keys._ object DemoCommand { // A simple, multiple-argument command that prints "Hi, " followed // by the arguments. It leaves the current state unchanged. // The args are already parsed into a Seq[String]. def demoCommand = Command.args("demo", "
") { (state, args) => println("Hi, " + args.mkString(" ")) state } // This is just one of several ways to construct a command. } ``` ```scala // build.sbt ... import DemoCommand._ lazy val root = (project in file(".")) .settings( name := "Example11a", commands += demoCommand, ) ``` --
```html sbt:Example11a> demo here comes the sun! Hi, here comes the sun! ``` --- ## Shell command implemented as sbt command ```scala // project/ShellCommand.scala import sbt._ import scala.sys.process._ import scala.language.postfixOps object ShellCommand { def shellCommand = Command.single("sh") { (state, commandLine) => Process(Seq("/bin/sh", "-c", commandLine)) !; state } } ``` ```scala // build.sbt ... lazy val root = (project in file(".")) .settings( name := "Example11b", commands += ShellCommand.shellCommand, ) ``` --
```html sbt:Example11b> sh find . -name *.class | wc -l 14 ``` ---
The *DemoCommand* and the *ShellCommand* examples were quite simple. *DemoCommand* created the command with the factory method *Command.args*, where the user input was already parsed into *Seq[String]* - a sequence of white space delimited words. *ShellCommand* created the command with the factory method *Command.single*, where the user input was parsed into a *String* - i.e the user input was unchanged (which was sufficient for our shell use case). In both cases the action function *(State, T) => State* passed the state back unchanged. --
For more complex parsing use cases, where parsing also supports tab completion, see: https://www.scala-sbt.org/release/docs/Parsing-Input.html For State changes inside the action function of a command see: https://www.scala-sbt.org/release/docs/Commands.html ---
## Command vs. InputTask
- Both can parse user input (and support tab completion). - A *Command* can change the build state, but *InputTask* cannot. - If you don't need to change the build state, prefer *InputTask*. - A description can be defined for settings, tasks and input tasks, but not for commands. - In the next chapter we will implement a ShellPlugin, once with a *Command*, once with an *InputTask* and compare both solutions. --- class: middle, center name: plugin_development # 20. Plugin Development
.footnote[ *example12a*, *example12b*, *example12c*, *example12d*, *example12e* ] .footnote2[ *https://www.scala-sbt.org/release/docs/Plugins.html* ] --- ## AutoPlugin An AutoPlugin defines a group of settings and the conditions where the settings are automatically added to a build (called "activation"). -- In your meta-project (i.e. in directory *project*) ... - create a Scala object extending *sbt.AutoPlugin* - override def *requires* = ...
to define the plugins this plugin is depending on - override def *trigger* = *noTrigger* | *allRequirements*
to specify whether to enable the plugin manually or automatically - override lazy val *buildSettings* = ...
to change settings at the build level as needed (or use *projectSettings* or *globalSettings* to change settings at project or global level as needed) -- In *build.sbt* - enable your plugin with *enablePlugins*, if *trigger* was *noTrigger* - Nothing to do, if *trigger* was *allRequirements* --- ## Plugin enabled manually ```scala // project/src/main/scala/shell/ShellCommand.scala package shell import sbt._, Keys._ import scala.language.postfixOps import scala.sys.process._ object ShellPlugin extends AutoPlugin { override def requires: Plugins = empty // other plugins this plugin depends on override def trigger: PluginTrigger = noTrigger // enable manually in build.sbt override lazy val buildSettings = Seq(commands += shellCommand) // add build level settings lazy val shellCommand: Command = Command.single("sh") { (state, commandLine) => Process(Seq("/bin/sh", "-c", commandLine)) !; state } } ``` ```scala // build.sbt ... lazy val root = (project in file(".")) .enablePlugins(ShellPlugin) .settings( name := "Example12a", ) ``` ---
```html sbt:Example12a> sh find . -name *.class | wc -l 14 ``` ```html sbt:Example12a> plugins In file:.../example12a/ sbt.plugins.IvyPlugin: enabled in root sbt.plugins.JvmPlugin: enabled in root sbt.plugins.CorePlugin: enabled in root sbt.ScriptedPlugin sbt.plugins.SbtPlugin ... shell.ShellPlugin: enabled in root ``` --- ## Plugin enabled automatically ```scala // project/src/main/scala/shell/ShellCommand.scala package shell import sbt._, Keys._ import scala.language.postfixOps import scala.sys.process._ object ShellPlugin extends AutoPlugin { override def requires: Plugins = empty // other plugins this plugin depends on override def trigger: PluginTrigger = allRequirements // enable automatically override lazy val buildSettings = Seq(commands += shellCommand) // add build level settings lazy val shellCommand: Command = Command.single("sh") { (state, commandLine) => Process(Seq("/bin/sh", "-c", commandLine)) !; state } } ``` ```scala // build.sbt ... lazy val root = (project in file(".")) // no need to enable ShellPlugin .settings( name := "Example12b", ) ``` ---
```html sbt:Example12b> sh find . -name *.class | wc -l 14 ``` ```html sbt:Example12b> plugins In file:.../example12b/ sbt.plugins.IvyPlugin: enabled in root sbt.plugins.JvmPlugin: enabled in root sbt.plugins.CorePlugin: enabled in root sbt.ScriptedPlugin sbt.plugins.SbtPlugin ... shell.ShellPlugin: enabled in root ``` --- ## Settings and Tasks in Plugins ```scala // project/HelloPlugin import sbt._ import Keys._ object HelloPlugin extends AutoPlugin { object autoImport { val greeting = settingKey[String]("greeting") val hello = taskKey[Unit]("say hello") } import autoImport._ override def trigger = allRequirements override lazy val buildSettings = Seq(greeting := "Hi!", hello := helloTask.value) lazy val helloTask = Def.task { println(greeting.value) } } ``` ```scala // build.sbt - UNCHANGED!!! *HelloPlugin* is enabled automatically! ``` --
```html sbt:Example12c> hello Hi! ``` --- ## ShellPlugin implemented with InputTask ```scala // project/src/main/scala/shell/ShellPlugin package shell import sbt._, Keys._ import complete.DefaultParsers._ import scala.sys.process.Process import scala.language.postfixOps object ShellPlugin extends AutoPlugin { object autoImport { lazy val sh = inputKey[Int]("Execute a shell command") } import autoImport._ override def requires: Plugins = empty // other plugins this plugin depends on override def trigger: PluginTrigger = allRequirements // enable automatically override lazy val buildSettings = Seq(sh := shellTask.evaluated) lazy val shellTask = Def.inputTask { val args: Seq[String] = spaceDelimited("
").parsed val commandLine = args.mkString(" ") Process(Seq("/bin/sh", "-c", commandLine)) ! } } ``` ---
```scala // build.sbt - doesn't know about the automatically enabled plugins ... lazy val root = (project in file(".")) .settings( name := "Example12d", ) ``` --
```html sbt:Example12d> sh find . -name *.class | wc -l 15 ``` ---
## Pubishing the ShellPlugin Before we publish our new sbt-ShellPlugin to the local Ivy2 repository we have to set sensible values to the setting **name** and **organisation** in the meta-project.
- **reload plugins** brings us to the meta-project, i.e. the project defined in the *project* directory. - **reload return** brings us back again. --- ```html sbt:Example12d> reload plugins ... ``` ```html sbt:project> organization [info] default ``` ```html sbt:project> name [info] project ``` ```html sbt:project> set organization := "com.example.myplugins" [info] Defining organization ... [success] Total time: ... ``` ```html sbt:project> set name := "sbt-myshell" [info] Defining name ... [success] Total time: ... ``` ```html sbt:sbt-myshell> organization [info] com.example.myplugins ``` ```html sbt:sbt-myshell> name [info] sbt-myshell ``` --- ```html sbt:sbt-myshell> publishLocal ... [info] published sbt-myshell to ~/.ivy2/local/com.example.myplugins/sbt-myshell/scala_2.12/sbt_1.0/0.1.0-SNAPSHOT/poms/sbt-myshell.pom [info] published sbt-myshell to ~/.ivy2/local/com.example.myplugins/sbt-myshell/scala_2.12/sbt_1.0/0.1.0-SNAPSHOT/jars/sbt-myshell.jar [info] published sbt-myshell to ~/.ivy2/local/com.example.myplugins/sbt-myshell/scala_2.12/sbt_1.0/0.1.0-SNAPSHOT/srcs/sbt-myshell-sources.jar [info] published sbt-myshell to ~/.ivy2/local/com.example.myplugins/sbt-myshell/scala_2.12/sbt_1.0/0.1.0-SNAPSHOT/docs/sbt-myshell-javadoc.jar [info] published ivy to ~/.ivy2/local/com.example.myplugins/sbt-myshell/scala_2.12/sbt_1.0/0.1.0-SNAPSHOT/ivys/ivy.xml [success] Total time: ... ``` -- Let's save these settings permanently. - **session save** writes these settings permanently to *project/build.sbt*. -- ```html sbt:sbt-myshell> session save [info] Reapplying settings... ... ``` ```html sbt:sbt-myshell> reload return ... [info] Set current project to Example12d (in build file:.../example12d/) ``` ```html sbt:Example12d> sh cat project/build.sbt organization := "com.example.myplugins" name := "sbt-myshell" ``` --- ```html sbt:Example12d> sh tree ~/.ivy2/local/* ~/.ivy2/local/com.example.myplugins └── sbt-myshell └── scala_2.12 └── sbt_1.0 └── 0.1.0-SNAPSHOT ├── docs │ ├── sbt-myshell-javadoc.jar │ ├── sbt-myshell-javadoc.jar.md5 │ └── sbt-myshell-javadoc.jar.sha1 ├── ivys │ ├── ivy.xml │ ├── ivy.xml.md5 │ └── ivy.xml.sha1 ├── jars │ ├── sbt-myshell.jar │ ├── sbt-myshell.jar.md5 │ └── sbt-myshell.jar.sha1 ├── poms │ ├── sbt-myshell.pom │ ├── sbt-myshell.pom.md5 │ └── sbt-myshell.pom.sha1 └── srcs ├── sbt-myshell-sources.jar ├── sbt-myshell-sources.jar.md5 └── sbt-myshell-sources.jar.sha1 ``` ---
## Using the locally published Plugin
In any other sbt project we can use the plugin we just published in the previous section. As we do with any other plugin, we import it into some sbt file in the meta-project, usually in *project/plugins.sbt*. --
```scala addSbtPlugin("com.example.myplugins" % "sbt-myshell" % "0.1.0-SNAPSHOT") ``` ---
```html sbt:Example12e> plugins In file:.../example12e/ sbt.plugins.IvyPlugin: enabled in root sbt.plugins.JvmPlugin: enabled in root sbt.plugins.CorePlugin: enabled in root ... shell.ShellPlugin: enabled in root ``` ```html sbt:Example12e> sh find . -name *.class | wc -l 17 ``` ```html sbt:Example12e> sh cat project/plugins.sbt addSbtPlugin("com.example.myplugins" % "sbt-myshell" % "0.1.0-SNAPSHOT") ``` ```html sbt:Example12e> inspect sh [info] Input task: Int [info] Description: [info] Execute a shell command [info] Provided by: [info] {file:.../example12e/} / sh [info] Defined at: [info] (shell.ShellPlugin.buildSettings) ShellPlugin.scala:39 ... ``` ---
## Publish Plugin to Bintray
To make the plugin availabe to the Scala community, publish it to Bintray. -- First go to https://bintray.com/signup/oss to create an Open Source Distribution Bintray Account. The detailed procedure how to publish is described in: - https://www.scala-sbt.org/release/docs/Bintray-For-Plugins.html - https://www.scala-sbt.org/release/docs/Publishing.html -- Plugins best practices can be found here: - https://www.scala-sbt.org/release/docs/Plugins-Best-Practices.html -- We already mentioned one of them: - Use settings and tasks. Avoid commands if possible. --- class: middle, center name: references # 21. References
--- ### References - Code and Slides of this Talk:
https://github.com/hermannhueck/pragmatic-sbt - sbt Reference Manual
https://www.scala-sbt.org/1.x/docs/index.html - sbt Native Packager Docs
https://www.scala-sbt.org/1.x/docs/index.html - gitter8 templates for sbt
https://github.com/foundweekends/giter8/wiki/giter8-templates - sbt Community Plugins
https://www.scala-sbt.org/release/docs/Community-Plugins.html - sbt core concepts
Talk by Eugene Yokota at Scala Days Lausanne 2019
https://www.youtube.com/watch?v=-shamsTC7rQ
https://portal.klewel.com/watch/webcast/scala-days-2019/talk/15/ - sbt-native-packager - package all the things
Talk by Nepomuk Seiler at Scala Days Berlin 2018
https://www.youtube.com/watch?v=ID-EqTOgwKY --- class: middle, center # Thank You
# Q & A
https://github.com/hermannhueck/pragmatic-sbt


QQmlIncubationController Class
QQmlIncubationController instances drive the progress of QQmlIncubators More...
| Header: | #include <QQmlIncubationController> |
| qmake: | QT += qml |
Public Functions
| QQmlIncubationController() | |
| QQmlEngine * | engine() const |
| void | incubateFor(int msecs) |
| void | incubateWhile(volatile bool *flag, int msecs = 0) |
| int | incubatingObjectCount() const |
Protected Functions
| virtual void | incubatingObjectCountChanged(int incubatingObjectCount) |
Detailed Description
QQmlIncubationController instances drive the progress of QQmlIncubators
In order to behave asynchronously and not introduce stutters or freezes in an application, the process of creating objects a QQmlIncubators must be driven only during the application's idle time. QQmlIncubationController allows the application to control exactly when, how often and for how long this processing occurs.
A QQmlIncubationController derived instance should be created and set on a QQmlEngine by calling the QQmlEngine::setIncubationController() method. Processing is then controlled by calling the QQmlIncubationController::incubateFor() or QQmlIncubationController::incubateWhile() methods as dictated by the application's requirements.
For example, this is an example of a incubation controller that will incubate for a maximum of 5 milliseconds out of every 16 milliseconds.
class PeriodicIncubationController : public QObject, public QQmlIncubationController { public: PeriodicIncubationController() { startTimer(16); } protected: void timerEvent(QTimerEvent *) override { incubateFor(5); } };
Although the previous example would work, it is not optimal. Real world incubation controllers should try and maximize the amount of idle time they consume - rather than a static amount like 5 milliseconds - while not disturbing the application.
Member Function Documentation
QQmlIncubationController::QQmlIncubationController()
Create a new incubation controller.
QQmlEngine *QQmlIncubationController::engine() const
Return the QQmlEngine this incubation controller is set on, or 0 if it has not been set on any engine.
void QQmlIncubationController::incubateFor(int msecs)
Incubate objects for msecs, or until there are no more objects to incubate.
void QQmlIncubationController::incubateWhile(volatile bool *flag, int msecs = 0)
Incubate objects while the bool pointed to by flag is true, or until there are no more objects to incubate, or up to msecs if msecs is not zero.
Generally this method is used in conjunction with a thread or a UNIX signal that sets the bool pointed to by flag to false when it wants incubation to be interrupted.
int QQmlIncubationController::incubatingObjectCount() const
Return the number of objects currently incubating.
[virtual protected]
void QQmlIncubationController::incubatingObjectCountChanged(int incubatingObjectCount)
Called when the number of incubating objects changes. incubatingObjectCount is the new number of incubating objects.
The default implementation does nothing.


Hostname and Fully Qualified Domain Name Configuration¶
Hostname and Fully Qualified Domain Name Configuration
In order to make sure that the Apache server correctly determines
the Fully Qualified Domain Name (FQDN) of the server and that the
virtual hosts use the correct server URL, the hostname should be
configured correctly. This is preferred instead of modifying the
Apache server name configuration so that all the software looks to
the same source for determining FQDNs. If the command
hostname -f
returns the correct FQDN hostname then the system
is correctly configured to run Open GEE. If not the following
instructions may help.
Ideally the network where GEE is installed has a DNS set up to
resolve hostnames so that IP traffic can be routed appropriately.
However in cases where there is no DNS, static hostnames can be
used as well. With static hostnames the hostname
or
hostnamectl
command should be used to set the hostname to its
FQDN. The /etc/hostname
file should be updated to match as
well so the name stays after reboots. If setting the hostname to
the FQDN is not possible, then setting the FQDN in the
/etc/hosts
file is necessary. When using a static hostname,
some operating systems may still give a warning on Apache startup
even if it correctly determined the FQDN. Adding the FQDN to
/etc/hosts
would fix this as well. If adding the FQDN to
/etc/hosts
is needed, then the FQDN followed by just the host
portion should be added to the line that contains the IP address
the server will be listening on. This should be the first line of
the file:
<IP_ADDRESS> myserver.mydomainname.com myserver localhost
If GEE is not using DNS other clients that connect to the server non-locally would need to have the same static mapping set up in their hosts files since the server hostname would not be resolved dynamically.
When determining where to look for the correct FQDN Apache calls
hostname
which will use a resolver. The system configuration
determines what the order is for resolving the FQDN. If the
/etc/nsswitch.conf
file is being used there is a line like
this that defines the order:
hosts: dns myhostname files
This example shows that the DNS on the network would be queried
first. If that does not define the FQDN then the hostname would be
queried. If the FQDN is still not defined then configuration files
would be queried, mainly /etc/hosts
.
If the /etc/host.conf
file is being used to resolve the
hostname, then there is a line like this that defines the order:
order hosts,bind
In this example hosts refers to the /etc/hosts
file and is
checked first, and bind refers to the DNS.
Here is another note on the server hostname.


My PortFolio
Home
About
contact
EBENEZER NOBLE
I built the Andriod replica...
Feel the beautiful web-development environment,Nigerian Times 2015
Quality css grid and flexbox..
Experience great coding structures..
We love web-development..
Making Lives Better with AI..
Radar project..
Classic Image Logo..
Developing a useful environment..
Efficiency of Softwares..
Develope your own portfolio by contacting the Exquisite Coding
We offer you an Exquisite Experience..


Trilogy is a compilation album released on 13 November 2012. It is composed of re-mixed and remastered versions of mixtapes House of Balloons, Thursday, and Echoes of Silence, and three previously-unreleased songs.
Trilogy charted at number five on the Canadian Albums Chart. In the United States, it debuted at number four on the Billboard 200, with first-week sales of 86,000 copies. On 22 May 2013, the album was certified Double Platinum by Music Canada.
In September 2012, The Weeknd signed with Republic Records in a joint venture with his own imprint label XO. The mixtapes were subsequently remastered and compiled for Trilogy, along with three previously unreleased songs, which were recorded at Liberty Studios in Toronto.
Kiss Land is the debut studio album by Canadian singer The Weeknd. It was released on September 10, 2013, by XO and Republic Records.
Trilogy charted at number five on the Canadian Albums Chart. In the United States, it debuted at number four on the Billboard 200, with first-week sales of 86,000 copies. On 22 May 2013, the album was certified Double Platinum by Music Canada.
In September 2012, The Weeknd signed with Republic Records in a joint venture with his own imprint label XO. The mixtapes were subsequently remastered and compiled for Trilogy, along with three previously unreleased songs, which were recorded at Liberty Studios in Toronto.


--- layout: post title: In The Cloud custom_css: true custom_js: true date: 2018-03-23 12:00:00 -5000 ---
I didn't specifically work on anything regarding the website this week. It has been all hands on deck trying to get to get AWS up and running for next week. We are able to connect these AWS Workspaces up to our virtual private cloud (VPC) and get access to a windows 10 box with SQL Management Studio. This will streamline the process of getting people connected and workspaces even support accessing the instance via a web browser, Chromebook, IOS, and Andriod. I managed to get everything up and running in a few days and now it is up to the database team to get me a backup I can work with so I can load the SQL instance with some data.
Group had already completed all the labs until number 10. I think we will be helping other folks complete their deliverables and try to get this project done in the next couple weeks. Quiet week for software engineering.
The fair was split up to the auditorium in Watson Hall and the gymnasium. I started with the auditorium first. I first took care of my LinkedIn photo because I figured the longer I waited the less good I would look. The first couple booths were awkward but I got the hang of it once I transitioned to the gym. It wasn't until halfway through the fair I noticed that the colors under the company logos matched our name tags. Each major had their own color and you can just quickly look to figure out what each employer was looking for.
I stopped by the FBI booth and noticed that they were packed with students. I started to stand with a group but got quickly bored because all the person was talking about was drugs and what would immediately disqualify you from the FBI. Starry seamed like a cool place to work, they were interested in any experience in Golang. I only got to talk to the guy who handles the networking side of things. I talked to some folks from Moviri and they were super psyched to talk to me. I will probably have an interview sometime next week. One of the companies I didn't do any research on impressed me the most.
Fast Enterprises is doing work with local government agencies around the country offering their technical expertise and tax product. Currently, they were working with the RMV to update their systems. They are working with the department of revenue to migrate them to their tax system. They are currently looking for a technical team member that would be able to work with the clients directly building out solutions for them. The most attractive opportunity is the relocation services provided. I wouldn't be guaranteed a spot in Boston, but I can submit to HR 3 places in the US I would want to live in, and 3 places I would not. I told my wife right after I went home and she was more than onboard to relocate somewhere warmer. I had a formal interview with the company Friday. I think it went well. I only had 30 minutes to take the informal test and I went with a rather unoptimized IsPrime() function. I was testing every number every number less than the parameter starting at 1 and continuing upwards until either the current iteration is a multiple or I ran out of numbers. This method doesn't scale well with large numbers and I was grilled on it. I answered all their questions and besides the inefficient method, I feel I did well. I hope they answer back because this company looks seriously promising.


Old photographs help understand what life used to be like. But a few — a select few — are so captivating that they transport us into the past.  September 1907, specifically, when photographers climbed atop City Hall to take a series of pictures of downtown Minneapolis that would ultimately require 21st-century technology to be fully appreciated.
Now the images can be uploaded at high resolution and stitched into one panorama — like you'll see below — allowing viewers to zoom from the skyline to intimate details. This is perhaps the most tantalizing slice-of-life picture of our bygone city.
To pan: Click and drag anywhere on the photo
To add: Click anywhere and add a note or ask a question
To read: Click a marker to read more about it
“It reveals things that essentially nobody ever saw before, because nobody would look at it in that way,” said Mike Evangelist, a historic-photo enthusiast who created a version of the panorama. “It’s so immersive.”
Most photos of this magnitude were commissioned to celebrate the completion of a building, or capture a postcard view. This panorama didn’t cater to a client. It didn’t aim for a flattering angle. It simply recorded the world as it was.
When the light hit the plate that day in 1907, it engraved unvarnished details no one ever thought to capture, because they seemed unimportant — laundry drying on a rooftop, men mingling outside a bar, horses lined up in a stable.
The photographers captured all that detail because they shot the images with a large-format camera onto 8-by-10-inch glass negatives. Compare that with the 35 millimeter (1.3 inch) negatives that became prevalent later in the 20th century. The lens of the camera also could be tilted so both far and near objects were in focus.
The photograph was made by the Detroit Publishing Co., a photographic powerhouse of the era that earned its reputation by shooting postcards and panoramas of scenes across America.
“They were selling those panoramas to anybody who wanted it,” said Cynthia Read Miller, a former curator at the Henry Ford Museum, which once owned the glass negatives and still maintains a large Detroit Publishing collection. “I’m sure they locally were trying to sell it to the city of Minneapolis.”
It is unclear if this panorama was widely viewed again before the 10 glass negatives were digitized by the Library of Congress. There is no record of it being reproduced or displayed.
The city had several utility companies in 1907. Consolidation wouldn’t begin until 1909, when H.M. Byllesby, an apprentice of Thomas Edison, would begin to buy up companies to form the firm later known as NSP. There were few utility poles in downtown, however. The lines had been run under the street at the end of the 19th century. But some buildings were connected by wires that ran from rooftop to rooftop, draped on sawhorses.
The Burlington Route railway was one of the country’s largest. At the time this ad was created, James J. Hill’s Great Northern railway was one of its owners, along with the Northern Pacific. Two popular destinations are noted in the ad: Chicago and St. Louis, which could be reached on the Bee Line. The original name survives in the BNSF Railway (Burlington-Northern-Santa-Fe).
In 1907, a Donaldsons addition — the city’s tallest retail structure — was almost complete. It was on the other end of the block from Donaldsons’ gleaming white Glass Block, whose alabaster dome can be seen in the panorama, to the right. (The dome would be removed during World War II, and the metal used for the war effort.)
The bank opened just months before this photo was taken. Considered the best equipped bank in the city at the time, thousands came to marvel at its interior, which was decorated in a cream-and-gold scheme. Despite its lavish look, the bank didn’t last. It was demolished in 1914 to make way for the First National Soo Line Building, making it “perhaps the shortest-lived bank in Twin Cities history,” according to the book “Twin Cities: Then and Now.”
The Panorama Building went up in 1886 and instantly drew crowds with a massive 360-degree panorama showing the Civil War’s Battle of Atlanta. “The spectator does not see walls of canvas and paint, but seems actually to gaze for miles in every direction upon an animated landscape,” the Minneapolis Tribune reported. By 1907, the building no longer housed a panorama. It was a furniture showroom, which it remained until the 1920s.
The marquee of the Bijou, at 20 Washington Av. N., helped date this panorama. The play, “A Fighting Chance,” was on stage in September 1907. The reviewer for the Minneapolis Morning Tribune did not approve of the production, which included a fake marriage, prison breaks and a bloody shootout. The theater remained open until 1959, and was razed the next year.
Luxe lodging arrived when the West Hotel opened in 1884. Its famously large and opulent lobby became a gathering place for local boldface names and visiting celebs of the era, including Mark Twain and a young Winston Churchill. The distinctive brick-and-marble striping on its lower floors makes it easy to spot in old photos. In 1907, that exterior appears marred by soot from coal smoke.
Why is there a statue of a man on top of this building? We don’t know the answer, but we do know the building — it’s the Palace Clothiers. It was the second location for Maurice Rothschild’s store. Rothschild was building a new eight-story headquarters next to the Palace. It’s almost finished in this photo. Both buildings were demolished in 1960 for the Sheraton-Ritz Hotel.
Soot may have obscured the 1894 nameplate carving, but this was indeed Minneapolis’ grand Metropolitan Opera house. The Romanesque Revival theater was designed by a local architect who specialized in entertainment venues, including a few brothels. “In its heyday the Metropolitan was the center of theater activity in the northwest,” the Minneapolis Star reported in 1937, the year the building was demolished.
The Church of the Immaculate Conception, built in 1868, was home to the city’s Catholics, who were raising money for much grander future digs, the Basilica of St. Mary. (The Basilica opened in 1914.) The peculiar structure in the 3rd Street roadway is an “underway” passage leading to the freight houses and tracks below street level, according to architectural historian Larry Millett. The underway remained until at least the 1970s.
The Minneapolis Institute of Art has a painting called “On a Roof Garden,” by W.A. Rogers. It depicts swells enjoying drinks on a roof garden, high above the noisy world. It’s not just any old roof garden, it’s the Metropolitan Building (aka Northwestern Guaranty Loan Building), the enormous office building whose demolition in 1961 is still lamented. Newspaper accounts of the building’s opening day in 1890 reference the roof garden, so we know Rogers’ tableau wasn’t fanciful.
When built in 1873, the old City Hall was in the Gateway District, then the center of commercial activity. Minneapolis had joined with St. Anthony the previous year, and needed a place to consolidate its management. City Hall was a slender structure, just four stories tall, but still had room for a post office and the Minneapolis Tribune. The distinctive mansard roof was a hallmark of the Second Empire Style, which we associate today with haunted houses. It was demolished in 1912.
Real estate developer Edmund Walton foretold the city’s population reaching 400,000 by 1910 on this sign. He missed the mark by 100,000, although the city had grown a whopping 48% when it barely passed 300,000 people in the 1910 census. That would happen to be the same year Walton wrote the first racial covenant into a deed in the city, blocking homeowners from selling their property to members of minority groups, according to researchers at the Mapping Prejudice project.
This sales pitch for cigars came from a speech by Henry George, a liberal economist who ran for mayor of New York City in the 1890s. The union ally briefly silenced the crowd when he said he wouldn’t do special favors for “the laboring man.” “I am for men,” George said. “The equal rights of all men. Let us be done with asking privileges for the laboring man.” The crowd went wild. But he never became mayor. He died hours after the speech.
Before it was leveled to make way for parkland, Nicollet Island was densely packed with commercial and industrial buildings. A sliver of the building called the William Bros. Boiler Works lives on as Nicollet Island Pavilion. Another building nearby became Nicollet Island Inn. The Minnesota Bee-Supply Co., shown in the photo, is what you might expect. An ad from the time says it sold “everything used by beekeepers.”
The painted ad for a cheroot bears the name of Anna Held, an actress and singer who was famous for singing racy songs and revealing her legs on stage. When she died in 1918, Carl Sandburg wrote a poem about her. Her longtime partner was the famous impresario Flo Ziegfeld, but the two never married. Flo went on to marry Billie Burke, the actress who played Glinda, the Good Witch of the North, in “The Wizard of Oz.”
Local photo enthusiast Mike Evangelist, who connected the images and shared a version of panorama a few years ago, spotted this detail in a building near the river. Those are the rear ends of horses lined up at Harwood Manufacturing Company’s livery stable. Harwood made barrels and later sacks for the city’s flour industry. The building, which now houses offices, was recently rebranded as the Barrel House.
The center was the city’s attempt to outdo the State Fair. Its first expo featured fine art and what was then high-tech industry — brickmaking and milling machines. The Grand Old Party nominated President Benjamin Harrison for re-election here in the 1892 Republican National Convention. In 1903, the building was taken over by International Stock Foods Co., run by Marion Savage, who owned one of the era’s most famous racehorses — Dan Patch
Designed by the local firm of Long & Kees, the 1885 Corn Exchange was torn down in 1965. It wasn’t as showy as the firm’s riotously ornamented Masonic Temple on Hennepin Avenue (now known as the Hennepin Center for the Arts), but the exchange had a sober dignity.
“It reveals things that essentially nobody ever saw before, because nobody would look at it in that way,” said Mike Evangelist, a historic-photo enthusiast who created a version of the panorama. “It’s so immersive.”
Most photos of this magnitude were commissioned to celebrate the completion of a building, or capture a postcard view. This panorama didn’t cater to a client. It didn’t aim for a flattering angle. It simply recorded the world as it was.
When the light hit the plate that day in 1907, it engraved unvarnished details no one ever thought to capture, because they seemed unimportant — laundry drying on a rooftop, men mingling outside a bar, horses lined up in a stable.
The photographers captured all that detail because they shot the images with a large-format camera onto 8-by-10-inch glass negatives. Compare that with the 35 millimeter (1.3 inch) negatives that became prevalent later in the 20th century. The lens of the camera also could be tilted so both far and near objects were in focus.
The photograph was made by the Detroit Publishing Co., a photographic powerhouse of the era that earned its reputation by shooting postcards and panoramas of scenes across America.
“They were selling those panoramas to anybody who wanted it,” said Cynthia Read Miller, a former curator at the Henry Ford Museum, which once owned the glass negatives and still maintains a large Detroit Publishing collection. “I’m sure they locally were trying to sell it to the city of Minneapolis.”
It is unclear if this panorama was widely viewed again before the 10 glass negatives were digitized by the Library of Congress. There is no record of it being reproduced or displayed.


Pystol was created to demonstrate the correlation between the execution of a fault injection action and the change in the Kubernetes based cluster behavior.
Improving system's resiliency
As long as we test our production environments we can improve their resiliency, in a simple definition, the ability to absorb disturbances.
Its also defined as the capacity of the infrastructure, communities and their related systems to mitigate, adapt, or positively respond to chronic and acute stresses, transforming in ways that restore, maintain and even improve their essential functions.
“Everything fails, all the time
Werner Vogels - CTO - Amazon
How can fault injection tests help developers and companies?
The first question is, why should a developer or a company consider using Pystol?
Implementing a strategy based on testing systems in Production we will improve its resiliency.
This would require a “chaosification” of the platform in a controlled manner, which could consist of actions of the following type: killing random pods in the cluster, evacuating nodes, injecting latency in the applications and many other tests.
Thanks to this platform and its strategy, a deeper visibility of the consequences of different kind of infrastructure or application issues can be achieved with the intention of improving defenses. This, in the long run, is the basis of a more mature and reliable system, capable of recovering from attacks and reducing losses in the face of a serious security incident, something that should be mandatory for any high availability service.


Kick Ass - Mr. 1000 Edition Drag this button to your bookmarks bar! And and activate it on another page (Or right click → Add to bookmarks)


Weather Report Fetch
Request Horsens data
Request Aarhus data
Request Copenhagen data
Load last five days
minimum and maximum temperature for the last 5 days
Total precipitation for the last 5 days
Average wind speed for last 5 days
Dominant wind direction last 5 days
Average cloud coverage for last 5 days
Forecast for next 24 hours


--- layout: page title: About image: /assets/images/geometry.jpg ---
My name is Biwash Shrestha and this is Anityam. Anityam is a learning blog sphere for data visualization where I will be analyzing data about youtube creators of Nepal. Data is collected through youtube api and will be using data visualization libraries like D3.js for creating the visualization contents. The platform should not be treated as a definitive source of information generation as data visualizations are only point of views with a certain perspective of the creators. With that in mind I do intend to learn and curate data while creating some authentic visualization for fun. So enjoy!!! Biwash


Result
public enum Result<V>
Wraps result of throwing code and allows to map embedded value
-
Resulted in error
Declaration
Swift
case error(Error)
-
Successfully aquired a value
Declaration
Swift
case value(V)
-
Init with unsafe code
let result = Result<V> { // Your unsafe code, that results either in value of type V or in error }
Declaration
Swift
public init(_ unsafe: () throws -> V)
-
Convinience init with unsafe code
let result = Result<V> ( // Your unsafe code, that results either in value of type V or in error )
Declaration
Swift
public init(_ unsafe: @autoclosure () throws -> V)
-
Wraps value in Result
Declaration
Swift
public static func pure(_ value: V) -> Result<V>
-
Wrap some throwing function from
U -> V
inU -> Result<V>
functionDeclaration
Swift
public static func wrap<U>(_ function: @escaping (U) throws -> V) -> ((U) -> Result)
-
Get unsafe execution back, in case if you want to use do … catch after all
Declaration
Swift
public func unwrap() throws -> V
-
Unwrap value as optional
Declaration
Swift
public var value: V?
-
Unwrap error as optional
Declaration
Swift
public var error: Error?
-
If there’s no error, perform function with value and return wrapped result
Declaration
Swift
public func map<U>(_ transform: (V) -> U) -> Result<U>
-
Performs transformation over value of Result.
Declaration
Swift
public func forEach(_ transform: (V) -> Void)
-
If there’s no error, perform function that may yield Result with value and return wrapped result
Declaration
Swift
public func flatMap<U>(_ transform: (V) -> Result<U>) -> Result<U>


C# is a modern, general-purpose, object-oriented programming language developed by Microsoft and approved by European Computer Manufacturers Association (ECMA) and International Standards Organization (ISO).
C# was developed by Anders Hejlsberg and his team during the development of .Net Framework.
C# is designed for Common Language Infrastructure (CLI), which consists of the executable code and runtime environment that allows use of various high-level languages on different computer platforms and architectures.
The following reasons make C# a widely used professional language −
- It is a modern, general-purpose programming language.
- It is object oriented.
- It is component oriented.
- It is easy to learn.
- It is a structured language.
- It produces efficient programs.
- It can be compiled on a variety of computer platforms.
- It is a part of .Net Framework.
Strong Programming Features of C#
Although C# constructs closely follow traditional high-level languages, C and C++ and being an object-oriented programming language. It has strong resemblance with Java, it has numerous strong programming features that make it endearing to a number of programmers worldwide.
Following is the list of few important features of C# −
- Boolean Conditions
- Automatic Garbage Collection
- Standard Library
- Assembly Versioning
- Properties and Events
- Delegates and Events Management
- Easy-to-use Generics
- Indexers
- Conditional Compilation
- Simple Multithreading
- LINQ and Lambda Expressions
- Integration with Windows


{% extends "base.html" %} {% block content %} Server Error Something went wrong. If it should not have gone wrong, please file an issue. {% endblock %}
Something went wrong. If it should not have gone wrong, please file an issue.


Education
- Ph.D, Computer Science, University of Southern California, 2019-2023 (expected)
- M.S., Computer Science - Analytics, University of Southern California, 2019-2021 (expected)
- B.S., Electrical Engineering and Computer System Engineering, Rensselaer Polytechnic Institute, 2015-2019
Major
- Computer Science
- Electrical Engineering
- Computer System Engineering
Concentration
- Augmented Reality
- Computer Vision
- Computer Graphics
GPA
- Graduate: 3.85 / 4.00
- Undergraduate: 3.95 / 4.00
Augmented, Virtual and Mixed Reality (2020 Spring)
University of Southern California, CSCI 538
- Project XR Interaction Toolkit
- We built tools for VR interaction: adjustable pointer, punch typing, 3D folder, virtual equipment, human skeleton calibration and reposition UIs.
- We investigated gesture detection and built basic function of virtual human skeleton to map in Unity.
Deep Learning and Its Applications (2019 Fall)
University of Southern California, CSCI 566
- Project Food Generation From Ingredients and Cooking Method
- We proved that cooking method extracted from instruction is useful and efficient for food image generation task.
- We provided qualitative and quantitative results which demonstrate that our model outperforms previous work.
- Supervised Learning, reinforcement learning, CNN, RNN, GAN, VAE
3-D Graphics and Rendering (2019 Fall)
University of Southern California, CSCI 580
- Project Water Freezing Simulation
- Full pipeline of conventional rasterization and rendering
RCOS (2017 Fall)
Rensselaer Center for Open Source, CSCI 2941
(Current) 2020 Fall
- Advanced Computer Vision (CSCI 677)
2020 Spring
- Augmented, Virtual and Mixed Reality (CSCI 538)
- Advanced Analysis of Algorithms (CSCI 670)
- Seminar in Computer Science Research, 2/2 (CSCI 697)
2019 Fall
- Deep Learning and Its Applications (CSCI 566)
- 3-D Graphics and Rendering (CSCI 580)
- Seminar in Computer Science Research, 1/2 (CSCI 697)
2019 Spring
- Introduction to Electronics (ECSE 2050)
- Engineering Probability (ECSE 2500)
- Multidisciplinary Capstone Design (ECSE 4900)
2018 Fall
- Computational Vison (CSCI 4270)
- VLSI Design (ECSE 4220)
- Digital Signal Processing (ECSE 4530)
- PD 3: Professional Development III (ENGR 4010)
- Machine Learning From Data (CSCI 4100)
2018 Spring
- Communication Theory And Practice (COMM 1510)
- Introduction To Algorithms (CSCI 2300)
- Signals And Systems (ECSE 2410)
- Introduction To Logic (PHIL 2140)
- PD 2: Tech Issues & Solutions (STSS 4967)
2017 Fall
- Foundations Of Computer Science (CSCI 2200)
- RCOS-Google Cardboard VR/AR (CSCI 2941)
- Money & Banking (ECON 4130)
- Microelectronics Technology (ECSE 2210)
- Computer Graphics (ECSE 4750)
- Linear Algebra (MATH 4100)
2017 Summer
- Introduction to Engineering Design (ENGR 2050)
2017 Spring
- Data Structures (CSCI 1200)
- Intermediate Microeconomic Theory (ECON 2010)
- Fields and Waves I (ECSE 2100)
- Electrical Energy Systems (ECSE 2210)
- Computer Architecture, Network and Operating System (ECSE 2660)
- ECSE Enrichment Seminar (ECSE 2900)
2016 Fall
- Electric Circuits (ECSE 2010)
- Computer Components & Operations (ECSE 2610)
- Engineering Dynamics (ENGR 2090)
- Multivariable Calculus & Matrix Algebra (MATH 2010)
2016 Spring
- Chemistry I (CHEM 1100)
- Engineering Communications (ENGR 1400)
- Embedded Control (ENGR 2350)
- Introduction to Differential Equations (MATH 2400)
2015 Fall
- Computer Science I (CSCI 1100)
- Introductory Economics (ECON 1200)
- Introduction to Engineering Analysis (ENGR 1100)
- Calculus II (MATH 1020)
- Physics I (PHYS 1100)


About Jakkur Lake
The Jakkur Lake is in the north-eastern part of the city and is one of the largest and cleanest water bodies in Bangalore. It is the main lake in the chain of lakes comprising of the Yelahanka Lake upstream and the Rachenahalli Lake downstream. It is about 140 acres large and has recently been rejuvenated by the Bangalore Development Authority (BDA).