Search code examples
scalajarsbtenvironmentbinary-compatibility

build.sbt does not Work with Different Scala Versions


Learning Scala from the Scala for Data Science book and the companion Github repo, here I am particularly talking about the build file for Chapter 2, copied below (with minor modification) for reference.

name := "Logistic_regression"

organization := "My Organisation"

version := "0.1.0-SNAPSHOT"

scalaVersion := "2.11.7" // 3.2.2 does not work

libraryDependencies ++= Seq(
  "org.scalanlp" %% "breeze" % "0.11.2",
  "org.scalanlp" %% "breeze-natives" % "0.11.2",
  "org.slf4j" % "slf4j-simple" % "1.7.5"
)

Being new to scala from python and C++, the idea of how different scala environments, dependencies etc. work is not entirely clear to me yet, but can I think of the build.sbt as a form of Dockerfile, that can take care of the dependencies on any host by creating its own sandbox?

The repo itself uses scalaVersion := "2.11.7" which works fine. But I wanted to match it to my system scala version (see below for the version details).

della@dell-xps ~/s/l/s/chap02 (master)> scala --version
Scala code runner version 3.2.2 -- Copyright 2002-2023, LAMP/EPFL
della@dell-xps ~/s/l/s/chap02 (master)> sbt --version
sbt version in this project: 1.8.2
sbt script version: 1.8.2

But changing it to 3.2.2 results in the following stack-trace (just the top part).

[warn]  Note: Unresolved dependencies path:
[error] sbt.librarymanagement.ResolveException: Error downloading org.scalanlp:breeze_3:0.11.2
[error]   Not found
[error]   Not found
[error]   not found: /home/della/.ivy2/localorg.scalanlp/breeze_3/0.11.2/ivys/ivy.xml
[error]   not found: https://repo1.maven.org/maven2/org/scalanlp/breeze_3/0.11.2/breeze_3-0.11.2.pom

So why is it that build.sbt cannot resolve the dependencies for a more recent scala version? Or, should it?

Further, if I want to work on the same project with the newer scala version, should I do it without sbt, and somehow installing the dependencies at the system level, available to all projects? How do I go around it?


Solution

  • can I think of the build.sbt as a form of Dockerfile, that can take care of the dependencies on any host by creating its own sandbox?

    There is no sandboxing here in Docker sense, you're not creating an isolated environment (@SethTisue commented that this can be considered as sandboxing in the sense that sbt manages dependencies itself, rather than relies on the ones installed systemwide). This is using a build tool like Sbt, Mill, Fury, Cbt in Scala, Maven or Gradle in Java, Bazel in Java/C++/Go, Pants in Python/Go/Java/Scala/Kotlin, Make in C++, Pip in Python, Cabal or Stack in Haskell etc.

    Scala 2 and Scala 3 are quite different

    https://docs.scala-lang.org/scala3/reference/

    http://dotty.epfl.ch/

    Scala 3 is still quite new version of Scala. Not all dependencies are published for Scala 3. Not all of them can be easily migrated into Scala 3 (because of Scala 2 macros etc.).

    Scala 2.10, 2.11, 2.12, 2.13 are binary incompatible. That's why we use %% for Scala libraries: "org.scalanlp" %% "breeze" % "0.11.2" is "org.scalanlp" % "breeze_2.11" % "0.11.2" while using scalaVersion := "2.11.7". But there is Scala 2.13 - Scala 3 interop

    https://docs.scala-lang.org/scala3/guides/migration/compatibility-intro.html

    There is compatibility mode CrossVersion.for3Use2_13/CrossVersion.for2_13Use3

    https://docs.scala-lang.org/scala3/guides/migration/compatibility-classpath.html

    How to use akka in Scala 3?

    You're using quite old versions of your dependencies. As you can see, Breeze and Breeze-natives 0.11.2 were published for Scala 2.10, 2.11. They are published for Scala 3 since Breeze 2.0

    https://mvnrepository.com/artifact/org.scalanlp/breeze

    https://mvnrepository.com/artifact/org.scalanlp/breeze-natives

    So try the following build.sbt

    scalaVersion := "3.2.2"
    
    libraryDependencies ++= Seq(
      "org.scalanlp" %% "breeze"         % "2.1.0",
      "org.scalanlp" %% "breeze-natives" % "2.1.0",
      "org.slf4j"    %  "slf4j-simple"   % "2.0.7"
    )
    

    For Breeze 1.x there is no Scala-3 version but there is Scala-2.13 version, so you can try compatibility mode

    scalaVersion := "3.2.2"
    
    libraryDependencies ++= Seq(
      "org.scalanlp" %% "breeze"         % "1.0" cross CrossVersion.for3Use2_13,
      "org.scalanlp" %% "breeze-natives" % "1.0" cross CrossVersion.for3Use2_13,
      "org.slf4j"    %  "slf4j-simple"   % "2.0.7"
    )
    

    But before Breeze 1.0 there was no Scala-2.13 version, so you can use only Scala 2.10-2.12 with them

    scalaVersion := "2.12.17"
    
    libraryDependencies ++= Seq(
      "org.scalanlp" %% "breeze"         % "0.13.2",
      "org.scalanlp" %% "breeze-natives" % "0.13.2",
      "org.slf4j"    %  "slf4j-simple"   % "2.0.7"
    )
    

    If you're using sbt, most probably you will not need to install anything in your system (except sbt and Java). Sbt will resolve dependencies itself.

    If you installed something in the system, most probably this is irrelevant for sbt builds.