Skip to content

scala/sbt-scala-module

Repository files navigation

Scala modules sbt plugin

This is an sbt 1.x plugin for building Scala modules.

What modules use it?

Former standard library

For historical reasons, these were originally part of the Scala standard library. They live on as modules since they are in the scala. namespace and keeping them there preserves source compatibility with old source code that uses them. They are now community-maintained and largely frozen in design, though still open to minor improvements.

Standard library adjacent

These modules are maintained by the Scala organization, with community input and participation. They have an especially close relationship with the Scala standard library (or, in the case of scala-async, the Scala 2 compiler).

Future standard library?

Code that could become part of the standard library in the future.

Why this plugin?

Having a shared plugin reduces duplication between the above repositories. Reducing duplication makes maintenance easier and helps ensure consistency.

A major feature of the plugin is automated tag-based publishing using sbt-ci-release. A release is made by pushing a tag to GitHub.

The plugin also brings in

  • sbt-dynver to set the version based on the git history
  • sbt-version-policy to check the versioning policy using MiMa
  • sbt-header to automate copyright header maintenance
  • sbt-osgi, if enabled with scalaModuleOsgiSettings

Usage

Add the plugin to the project/plugins.sbt file:

addSbtPlugin("org.scala-lang.modules" % "sbt-scala-module" % <version>)

Then, in your build.sbt add:

// In a multi-project build, you might want to apply these settings only to the
// main project (see e.g. scala-parallel-collections)
ScalaModulePlugin.scalaModuleSettings

// If making an OSGi bundle
ScalaModulePlugin.scalaModuleOsgiSettings

name         := "<module name>"
repoName     := "<GitHub repo name>" // the repo under github.com/scala/, only required if different from name
organization := "<org>"              // only required if different from "org.scala-lang.modules"

versionPolicyIntention := Compatibility.BinaryAndSourceCompatible // enables MiMa (`Compatibility.None` by default, which disables it)

OsgiKeys.exportPackage := Seq(s"<exported package>;version=${version.value}")

// Other settings

Cross-building with Scala.js and Scala Native is possible. See scala-xml or scala-parser-combinators for examples.

These additional settings are enabled by scalaModuleSettings:

  • Compile / compile / scalacOptions ++= Seq("-feature", "-deprecation", "-unchecked", "-Xlint")
  • A projectName.properties file is generated and packaged
  • Test / fork := true to work around some classpath clashes with scala-xml
  • POM metadata

The following settings are also available:

  • enableOptimizer adds -opt-inline-from:<sources> or -opt:l:project or -optimize to Compile / compile / scalacOptions, depending on the Scala version

Set up tag-based publishing

The instructions here are a summary of the readme in https://github.com/olafurpg/sbt-ci-release and https://github.com/scalacenter/sbt-version-policy

  • Create a fresh GPG key: gpg --gen-key

    • Real name: use "project-name bot"
    • Email: "[email protected]"
    • Passphrase: generate one yourself
  • Get the key LONG_ID from the output and set LONG_ID=6E8ED79B03AD527F1B281169D28FC818985732D9. The output looks like this:

    pub   rsa2048 2018-06-10 [SC] [expires: 2020-06-09]
          $LONG_ID
    
  • Copy the public key to a key server

  • In your repo's Actions settings, define four secret env vars

    • PGP_PASSPHRASE the passphrase you chose above
    • PGP_SECRET the secret key in base64
      • macOS: gpg --armor --export-secret-keys $LONG_ID | base64
      • ubuntu: gpg --armor --export-secret-keys $LONG_ID | base64 -w0
    • SONATYPE_PASSWORD: need that one
    • SONATYPE_USERNAME: that one too
  • Run versionCheck in the publishing process: sbt versionCheck ci-release