diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a7580a9..9b73aae 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -18,20 +18,15 @@ jobs: JVM_OPTS: -Xms2048M -Xmx2048M -Xss6M -XX:ReservedCodeCacheSize=256M -Dfile.encoding=UTF-8 steps: - name: Checkout - uses: actions/checkout@v2 - - name: Setup - uses: olafurpg/setup-scala@v10 + uses: actions/checkout@v3 + - name: Setup JDK + uses: actions/setup-java@v3 with: - java-version: "adopt@1.${{ matrix.java }}" - - name: Coursier cache - uses: coursier/cache-action@v6 + distribution: temurin + java-version: "${{ matrix.java }}" + cache: sbt - name: Build and test run: | sbt -v "mimaReportBinaryIssues; scalafmtCheckAll; shadedPackageBin; test;" ci-test/test.sh - rm -rf "$HOME/.ivy2/local" || true - find $HOME/Library/Caches/Coursier/v1 -name "ivydata-*.properties" -delete || true - find $HOME/.ivy2/cache -name "ivydata-*.properties" -delete || true - find $HOME/.cache/coursier/v1 -name "ivydata-*.properties" -delete || true - find $HOME/.sbt -name "*.lock" -delete || true shell: bash diff --git a/build.sbt b/build.sbt index 65d88fa..3419272 100644 --- a/build.sbt +++ b/build.sbt @@ -8,7 +8,7 @@ Global / onChangedBuildSource := ReloadOnSourceChanges ThisBuild / dynverSonatypeSnapshots := true ThisBuild / version := { val orig = (ThisBuild / version).value - if (orig.endsWith("-SNAPSHOT")) "1.2.0-SNAPSHOT" + if (orig.endsWith("-SNAPSHOT")) "1.4.0-SNAPSHOT" else orig } ThisBuild / description := "Standalone launcher for maven/ivy deployed projects" diff --git a/ci-test/test.sh b/ci-test/test.sh index 0734dc5..88c7e17 100755 --- a/ci-test/test.sh +++ b/ci-test/test.sh @@ -1,6 +1,6 @@ #!/bin/bash -e -LAUNCHER="../../launcher-implementation/target/proguard/launcher-implementation-1.2.0-SNAPSHOT-shading.jar" +LAUNCHER="../../launcher-implementation/target/proguard/launcher-implementation-1.4.0-SNAPSHOT-shading.jar" pushd ci-test/app0 COURSIER_CACHE=/tmp/cache/ java -jar $LAUNCHER @sbt.1.3.13.boot.properties exit diff --git a/launcher-implementation/src/main/scala/xsbt/boot/BootConfiguration.scala b/launcher-implementation/src/main/scala/xsbt/boot/BootConfiguration.scala index 489d329..e47c3df 100644 --- a/launcher-implementation/src/main/scala/xsbt/boot/BootConfiguration.scala +++ b/launcher-implementation/src/main/scala/xsbt/boot/BootConfiguration.scala @@ -16,7 +16,9 @@ private[boot] object BootConfiguration { // these are the Scala module identifiers to resolve/retrieve val ScalaOrg = "org.scala-lang" val CompilerModuleName = "scala-compiler" + val Compiler3ModuleName = "scala3-compiler_3" val LibraryModuleName = "scala-library" + val Library3ModuleName = "scala3-library_3" val JUnitName = "junit" val JAnsiVersion = "1.18" @@ -56,7 +58,8 @@ private[boot] object BootConfiguration { * The loader will check that these classes can be loaded and will assume that their presence indicates * the Scala compiler and library have been downloaded. */ - val TestLoadScalaClasses = "scala.Option" :: "scala.tools.nsc.Global" :: Nil + val TestLoadScala2Classes = "scala.Option" :: "scala.tools.nsc.Global" :: Nil + val TestLoadScala3Classes = "scala.Option" :: "dotty.tools.dotc.Driver" :: Nil val ScalaHomeProperty = "scala.home" val UpdateLogName = "update.log" diff --git a/launcher-implementation/src/main/scala/xsbt/boot/CoursierUpdate.scala b/launcher-implementation/src/main/scala/xsbt/boot/CoursierUpdate.scala index 1cd9ab2..62902f3 100644 --- a/launcher-implementation/src/main/scala/xsbt/boot/CoursierUpdate.scala +++ b/launcher-implementation/src/main/scala/xsbt/boot/CoursierUpdate.scala @@ -56,20 +56,40 @@ class CousierUpdate(config: UpdateConfiguration) { Console.err.println( s"[info] [launcher] getting ${scalaOrgString}Scala $scalaVersion ${reason}..." ) - withPublication( - Dependency( - Module(Organization(scalaOrg), ModuleName(CompilerModuleName)), - scalaVersion - ), - u.classifiers - ) ::: - withPublication( - Dependency( - Module(Organization(scalaOrg), ModuleName(LibraryModuleName)), - scalaVersion - ), - u.classifiers - ) + scalaVersion match { + case sv if sv.startsWith("2.") => + withPublication( + Dependency( + Module(Organization(scalaOrg), ModuleName(CompilerModuleName)), + scalaVersion + ), + u.classifiers + ) ::: + withPublication( + Dependency( + Module(Organization(scalaOrg), ModuleName(LibraryModuleName)), + scalaVersion + ), + u.classifiers + ) + case sv if sv.startsWith("3.") => + withPublication( + Dependency( + Module(Organization(scalaOrg), ModuleName(Compiler3ModuleName)), + scalaVersion + ), + u.classifiers + ) ::: + withPublication( + Dependency( + Module(Organization(scalaOrg), ModuleName(Library3ModuleName)), + scalaVersion + ), + u.classifiers + ) + case _ => + sys.error("unsupported Scala version " + scalaVersion) + } case u: UpdateApp => val app = u.id val resolvedName = (app.crossVersioned, scalaVersion) match { @@ -103,6 +123,22 @@ class CousierUpdate(config: UpdateConfiguration) { update(target, deps) } + private def detectScalaVersion(dependencySet: Set[Dependency]): Option[String] = { + def detectScalaVersion3: Option[String] = + (dependencySet collect { + case d: Dependency + if d.module == Module(Organization(scalaOrg), ModuleName(Library3ModuleName)) => + d.version + }).headOption + def detectScalaVersion2: Option[String] = + (dependencySet collect { + case d: Dependency + if d.module == Module(Organization(scalaOrg), ModuleName(LibraryModuleName)) => + d.version + }).headOption + detectScalaVersion3.orElse(detectScalaVersion2) + } + /** Runs the resolve and retrieve for the given moduleID, which has had its dependencies added already. */ private def update( target: UpdateTarget, @@ -115,7 +151,14 @@ class CousierUpdate(config: UpdateConfiguration) { .withScalaVersion(sv) .withForceScalaVersion(true) case _ => - ResolutionParams() + detectScalaVersion(deps.toSet) match { + case Some(sv) => + ResolutionParams() + .withScalaVersion(sv) + .withForceScalaVersion(true) + case _ => + ResolutionParams() + } } val r: Resolution = Resolve() .withCache(coursierCache) @@ -123,12 +166,7 @@ class CousierUpdate(config: UpdateConfiguration) { .withRepositories(repos) .withResolutionParams(params) .run() - val actualScalaVersion = - (r.dependencySet.set collect { - case d: Dependency - if d.module == Module(Organization(scalaOrg), ModuleName(LibraryModuleName)) => - d.version - }).headOption + val actualScalaVersion = detectScalaVersion(r.dependencySet.set) val retrieveDir = target match { case u: UpdateScala => new File(new File(bootDirectory, baseDirectoryName(scalaOrg, scalaVersion)), "lib") diff --git a/launcher-implementation/src/main/scala/xsbt/boot/Launch.scala b/launcher-implementation/src/main/scala/xsbt/boot/Launch.scala index 11b927e..0ff537c 100644 --- a/launcher-implementation/src/main/scala/xsbt/boot/Launch.scala +++ b/launcher-implementation/src/main/scala/xsbt/boot/Launch.scala @@ -195,7 +195,8 @@ import BootConfiguration.{ baseDirectoryName, extractScalaVersion, ScalaDirectoryName, - TestLoadScalaClasses, + TestLoadScala2Classes, + TestLoadScala3Classes, ScalaOrg } class Launch private[xsbt] ( @@ -409,9 +410,12 @@ class Launch private[xsbt] ( val scalaM = scalaModule(scalaOrg, scalaVersion) val (scalaHome, lib) = scalaDirs(scalaM, scalaOrg, scalaVersion) val baseDirs = lib :: Nil + def testLoadScalaClasses = + if (scalaVersion.startsWith("2.")) TestLoadScala2Classes + else TestLoadScala3Classes def provider(retrieved: RetrievedModule): xsbti.ScalaProvider = { val p = scalaProvider(scalaVersion, retrieved, classLoader, lib) - checkLoader(p.loader, retrieved.definition, TestLoadScalaClasses, p) + checkLoader(p.loader, retrieved.definition, testLoadScalaClasses, p) } existing(scalaM, scalaOrg, Some(scalaVersion), _ => baseDirs) flatMap { mod => try Some(provider(mod)) diff --git a/launcher-implementation/src/main/scala/xsbt/boot/Update.scala b/launcher-implementation/src/main/scala/xsbt/boot/Update.scala index 01cc7e0..28dc04a 100644 --- a/launcher-implementation/src/main/scala/xsbt/boot/Update.scala +++ b/launcher-implementation/src/main/scala/xsbt/boot/Update.scala @@ -201,22 +201,44 @@ final class Update(config: UpdateConfiguration) { val dep = target match { case u: UpdateScala => val scalaVersion = getScalaVersion - addDependency( - moduleID, - scalaOrg, - CompilerModuleName, - scalaVersion, - "default;optional(default)", - u.classifiers - ) - val ddesc = addDependency( - moduleID, - scalaOrg, - LibraryModuleName, - scalaVersion, - "default", - u.classifiers - ) + val ddesc = scalaVersion match { + case sv if sv.startsWith("2.") => + addDependency( + moduleID, + scalaOrg, + CompilerModuleName, + scalaVersion, + "default;optional(default)", + u.classifiers + ) + addDependency( + moduleID, + scalaOrg, + LibraryModuleName, + scalaVersion, + "default", + u.classifiers + ) + case sv if sv.startsWith("3.") => + addDependency( + moduleID, + scalaOrg, + Compiler3ModuleName, + scalaVersion, + "default;optional(default)", + u.classifiers + ) + addDependency( + moduleID, + scalaOrg, + Library3ModuleName, + scalaVersion, + "default", + u.classifiers + ) + case _ => + error("unsupported Scala version " + scalaVersion) + } excludeJUnit(moduleID) val scalaOrgString = if (scalaOrg != ScalaOrg) scalaOrg + " " else "" Console.err.println( @@ -324,6 +346,7 @@ final class Update(config: UpdateConfiguration) { rule } val scalaLibraryId = ModuleId.newInstance(ScalaOrg, LibraryModuleName) + val scala3Library3Id = ModuleId.newInstance(ScalaOrg, Library3ModuleName) // Returns the version of the scala library, as well as `dep` (a dependency of `module`) after it's been resolved private def resolve( eventManager: EventManager, @@ -348,8 +371,11 @@ final class Update(config: UpdateConfiguration) { error("error retrieving required libraries") } val modules = moduleRevisionIDs(resolveReport) - extractVersion(modules, scalaLibraryId) -> extractVersion(modules, dep) + val autoScala = + extractVersion(modules, scala3Library3Id).orElse(extractVersion(modules, scalaLibraryId)) + autoScala -> extractVersion(modules, dep) } + private[this] def extractVersion( modules: Seq[ModuleRevisionId], dep: ModuleId diff --git a/project/Deps.scala b/project/Deps.scala index cd67e8f..b629a17 100644 --- a/project/Deps.scala +++ b/project/Deps.scala @@ -10,6 +10,6 @@ object Deps { // TODO - these should be like the above, just ModuleIDs lazy val ivy = "org.scala-sbt.ivy" % "ivy" % "2.3.0-sbt-839fad1cdc07cf6fc81364d74c323867230432ad" - lazy val coursier = "io.get-coursier" %% "coursier" % "2.0.13" + lazy val coursier = "io.get-coursier" %% "coursier" % "2.0.16" lazy val scalaCompiler = Def.setting("org.scala-lang" % "scala-compiler" % scalaVersion.value) }