Search code examples
scalasbt

Repeated Setting of Scalac Flags in Scala 3


I'm having this build.sbt for one of my projects and this project uses an sbt plugin that I have internally built and published locally. This sbt plugin contains the common shared settings and looks like this:

import sbt._
import Keys._

object SharedSettings {

  // Scala Versions
  val scala3 = "3.4.0"
  val scala2 = "2.13.15"
  val supportedScalaVersions = Seq(scala3, scala2)

  // High-Level Project Details and Configurations
  val projectMetadata = Seq(
    ThisBuild / organization := "com.openelectrons", // Organization name
    ThisBuild / scalaVersion := scala3, // Scala version
    ThisBuild / version := "0.0.1", // Project version
    ThisBuild / name := "open-electrons-sbt-template", // Project name
    ThisBuild / description := "common settings for open-electrons projects", // Description
    ThisBuild / startYear := Some(2022), // Start year
    ThisBuild / homepage := Some(url("https://open-electrons.github.io/home/")), // Homepage URL
    ThisBuild / licenses := Seq("MIT" -> url("https://opensource.org/licenses/MIT")), // License
    ThisBuild / developers := List( // Developers
      Developer(
        id = "joesan",
        name = "Joesan",
        email = "https://bigelectrons.com/",
        url = url("https://github.com/joesan")
      )
    ),
    ThisBuild / scmInfo := Some(
      ScmInfo(
        browseUrl = url("https://github.com/open-electrons/open-electrons-sbt-template"),
        connection = "scm:git:https://github.com/open-electrons/open-electrons-sbt-template.git",
        devConnection = Some("scm:git:https://github.com/open-electrons/open-electrons-sbt-template.git")
      )
    )
  )

  // Dependency resolvers
  ThisBuild / resolvers ++= Seq(
    Resolver.mavenCentral,
    "Typesafe Releases" at "https://repo.typesafe.com/typesafe/releases/",
    "Typesafe Snapshots" at "https://repo.typesafe.com/typesafe/snapshots/"
  ) ++ Resolver.sonatypeOssRepos("snapshots") ++ Resolver.sonatypeOssRepos("releases")

  // Publishing configuration
  val publishingConfig = Seq(
    ThisBuild / publishTo := {
      if (isSnapshot.value)
        Some("Snapshots" at "https://oss.sonatype.org/content/repositories/snapshots")
      else
        Some("Releases" at "https://oss.sonatype.org/service/local/staging/deploy/maven2")
    },
    ThisBuild / publishMavenStyle := true,
    ThisBuild / credentials += Credentials(
      "Sonatype Nexus Repository Manager",
      "oss.sonatype.org",
      "<username>",
      "<password>"
    )
  )

  // Final Shared Settings
  val settings: Seq[Setting[_]] = projectMetadata ++ publishingConfig
}

The build.sbt where I'm using the common shared settings from the plugin looks like this:

import scala.io.Source
// Import shared settings
import SharedSettings._
import org.typelevel.scalacoptions.ScalacOptions

// This is the main build file for the ocpp-gateway-server project
lazy val doobieVersion = "1.0.0-RC6"
lazy val dropWizardMetricsVersion = "4.2.19"
lazy val catsVersion = "2.12.0"

// Build definition for the ocpp-gateway-server project
lazy val ocppGatewayServer = (project in file("."))
  .enablePlugins(PlayScala, DockerPlugin)
  .settings(
    SharedSettings.settings,
    name := """ocpp-gateway-server""",
    version := "1.0-SNAPSHOT",
    scalaVersion := SharedSettings.scala3,
    autoAPIMappings := true,
    dependencyOverrides += "org.slf4j" % "slf4j-api" % "1.7.32",
    libraryDependencies ++= Seq(
      // Add explicit Cats dependencies
      "org.typelevel" %% "cats-core" % catsVersion,
      "org.typelevel" %% "cats-kernel" % catsVersion,
      "org.typelevel" %% "cats-effect" % "3.5.7",

      // Database libraries
      "org.postgresql" %  "postgresql" % "42.3.1",
      "com.h2database" % "h2" % "1.4.199",

      "org.tpolecat" %% "doobie-core"     % doobieVersion exclude ("org.typelevel", "cats-core"),
      "org.tpolecat" %% "doobie-postgres" % doobieVersion,
      "org.tpolecat" %% "doobie-h2"       % doobieVersion,
      "org.tpolecat" %% "doobie-hikari"   % doobieVersion,

      "ch.qos.logback" % "logback-classic" % "1.2.6",

      "org.playframework" %% "play-json" % "3.0.4",
      "com.typesafe.play" %% "play-json-joda" % "2.10.6",

      // For caching and distributed caching
      //"com.github.cb372" %% "scalacache-core" % "0.28.0",
      //"com.github.cb372" %% "scalacache-guava" % "0.28.0",

      // For application Metrics
      "io.dropwizard.metrics" % "metrics-core" % dropWizardMetricsVersion,
      "io.dropwizard.metrics" % "metrics-jvm" % dropWizardMetricsVersion,

      // Threading & Streaming libraries (https://monix.io/docs/current/intro/usage.html)
      //"io.monix" %% "monix-execution" % "3.4.0",
      "co.fs2" %% "fs2-core" % "3.9.1",

      // MQTT client
      "com.hivemq" % "hivemq-mqtt-client" % "1.3.3",

      // OCPP & OCPI Core libraries
      "com.openelectrons" %% "ocpp-j-api" % "0.0.1-SNAPSHOT",
      "com.openelectrons" %% "ocpp-messages" % "0.0.1-SNAPSHOT",
      "com.openelectrons" %% "ocpiv22-messages" % "0.0.1-SNAPSHOT",
      "com.openelectrons" %% "ocpiv22-api" % "0.0.1-SNAPSHOT",

      // Test libraries
      "org.scalatestplus.play" %% "scalatestplus-play" % "7.0.1" % Test exclude ("org.slf4j", "slf4j-simple"),
      "org.specs2" %% "specs2-core" % "4.20.0" % Test,
      "org.scalacheck" %% "scalacheck" % "1.18.1" % Test,
      "org.testcontainers" % "hivemq" % "1.19.7" % Test,
      "com.dimafeng" %% "testcontainers-scala-scalatest" % "0.41.3" % Test,
      "com.dimafeng" %% "testcontainers-scala-postgresql" % "0.41.0" % Test
      // https://github.com/DanielaSfregola/random-data-generator
      //"com.danielasfregola" %% "random-data-generator" % "2.9" % Test
    ),
    Test / fork := true,
    // The command below ignores all tests tagged with IntegrationTest when running: sbt clean test
    Test / testOptions += Tests.Argument("-l", "com.openelectrons.ocpp.gateway.IntegrationTest")
  )

Now when I tried to build my actual project with the build.sbt as above, I run into this error below:

[info] compiling 41 Scala sources and 2 Java sources to /Users/user/Projects/Private/scala-projects/open-electrons/cpo-platform/ocpp-gateway-server/target/scala-3.4.0/classes ...
[error] Flag -deprecation set repeatedly
[error] Flag -unchecked set repeatedly
[error] Flag -encoding set repeatedly
[error] three errors found
[error] (Compile / compileIncremental) Compilation failed
[error] Total time: 2 s, completed Dec 24, 2024, 1:08:34 PM

I'm using this in the plugins.sbt of the ocpp-gateway-server project:

// scalac options for the enlightened @see https://github.com/typelevel/sbt-tpolecat
addSbtPlugin("org.typelevel" % "sbt-tpolecat" % "0.5.2")

I'm not able to see where the duplication is coming from.

EDIT: I printed what scalac options is my project seeing and here it is:

[info] scalacOptions:
-encoding, utf8,
-deprecation,
-feature,
-unchecked,
-language:experimental.macros, 
-language:higherKinds, 
-language:implicitConversions, 
-Ykind-projector, 
-Wvalue-discard, 
-Wnonunit-statement, 
-Wunused:implicits, 
-Wunused:explicits, 
-Wunused:imports, 
-Wunused:locals, 
-Wunused:params, 
-Wunused:privates, 
-Xfatal-warnings, 
-deprecation, 
-unchecked, 
-encoding, utf8

Solution

  • The duplicate options come from the plugins that you enable:

    You enable PlayScala which enables deprecation here and you also enable sbt-tpolecat which also enables deprecation (can't bother to look up the exact line where it does, bt I'm sure it does).

    Edit: A simple fix could be to add something like this within your settings (in build.sbt):

    scalacOptions ~= { options =>
      options.distinct
    },