diff --git a/.github/workflows/stdlib.yaml b/.github/workflows/stdlib.yaml index e8ebfdffc1cc..7ceec21f500c 100644 --- a/.github/workflows/stdlib.yaml +++ b/.github/workflows/stdlib.yaml @@ -79,3 +79,37 @@ jobs: - uses: sbt/setup-sbt@v1 - name: Compile `scala3-library-bootstrapped` run: ./project/scripts/sbt scala3-library-bootstrapped-new/compile + + tasty-core-nonbootstrapped: + runs-on: ubuntu-latest + ##needs: [scala3-library-nonbootstrapped] Add when we add support for caching here + steps: + - name: Git Checkout + uses: actions/checkout@v4 + + - name: Set up JDK 17 + uses: actions/setup-java@v4 + with: + distribution: 'temurin' + java-version: 17 + cache: 'sbt' + - uses: sbt/setup-sbt@v1 + - name: Compile `tasty-core-nonbootstrapped` + run: ./project/scripts/sbt tasty-core-nonbootstrapped/compile + + scala3-compiler-nonbootstrapped: + runs-on: ubuntu-latest + ##needs: [tasty-core-nonbootstrapped, scala3-library-nonbootstrapped] Add when we add support for caching here + steps: + - name: Git Checkout + uses: actions/checkout@v4 + + - name: Set up JDK 17 + uses: actions/setup-java@v4 + with: + distribution: 'temurin' + java-version: 17 + cache: 'sbt' + - uses: sbt/setup-sbt@v1 + - name: Compile `scala3-compiler-nonbootstrapped` + run: ./project/scripts/sbt scala3-compiler-nonbootstrapped/compile diff --git a/build.sbt b/build.sbt index 986b2102e16f..28620eb1d964 100644 --- a/build.sbt +++ b/build.sbt @@ -2,6 +2,7 @@ val scala3 = Build.scala3 val `scala3-bootstrapped` = Build.`scala3-bootstrapped` val `scala3-interfaces` = Build.`scala3-interfaces` val `scala3-compiler` = Build.`scala3-compiler` +val `scala3-compiler-nonbootstrapped` = Build.`scala3-compiler-nonbootstrapped` val `scala3-compiler-bootstrapped` = Build.`scala3-compiler-bootstrapped` val `scala-library-nonbootstrapped` = Build.`scala-library-nonbootstrapped` val `scala3-library-nonbootstrapped` = Build.`scala3-library-nonbootstrapped` @@ -23,6 +24,7 @@ val `scala2-library-tasty` = Build.`scala2-library-tasty` val `scala2-library-cc` = Build.`scala2-library-cc` val `scala2-library-cc-tasty` = Build.`scala2-library-cc-tasty` val `tasty-core` = Build.`tasty-core` +val `tasty-core-nonbootstrapped` = Build.`tasty-core-nonbootstrapped` val `tasty-core-bootstrapped` = Build.`tasty-core-bootstrapped` val `tasty-core-scala2` = Build.`tasty-core-scala2` val scaladoc = Build.scaladoc diff --git a/project/Build.scala b/project/Build.scala index ebacda4dbb80..55f41a512290 100644 --- a/project/Build.scala +++ b/project/Build.scala @@ -1540,6 +1540,176 @@ object Build { target := target.value / "scala3-library-bootstrapped", ) + // ============================================================================================== + // ===================================== TASTY CORE LIBRARY ===================================== + // ============================================================================================== + + /* Configuration of the org.scala-lang:tasty-core_3:*.**.**-nonbootstrapped project */ + lazy val `tasty-core-nonbootstrapped` = project.in(file("tasty")) + .dependsOn(`scala3-library-nonbootstrapped`) + .settings( + name := "tasty-core-nonbootstrapped", + moduleName := "tasty-core", + version := dottyNonBootstrappedVersion, + versionScheme := Some("semver-spec"), + scalaVersion := referenceVersion, // nonbootstrapped artifacts are compiled with the reference compiler (already officially published) + crossPaths := true, // org.scala-lang:tasty-core has a crosspath + // sbt shouldn't add stdlib automatically, we depend on `scala3-library-nonbootstrapped` + autoScalaLibrary := false, + // Add the source directories for the stdlib (non-boostrapped) + Compile / unmanagedSourceDirectories := Seq(baseDirectory.value / "src"), + Compile / unmanagedSourceDirectories += baseDirectory.value / "src-non-bootstrapped", + // Make sure that the produced artifacts have the minimum JVM version in the bytecode + Compile / javacOptions ++= Seq("--target", Versions.minimumJVMVersion), + Compile / scalacOptions ++= Seq("--java-output-version", Versions.minimumJVMVersion), + // Only publish compilation artifacts, no test artifacts + Compile / publishArtifact := true, + Test / publishArtifact := false, + // Do not allow to publish this project for now + publish / skip := true, + // Project specific target folder. sbt doesn't like having two projects using the same target folder + target := target.value / "tasty-core-nonbootstrapped", + // sbt adds all the projects to scala-tool config which breaks building the scalaInstance + // as a workaround, I build it manually by only adding the compiler + scalaInstance := { + val lm = dependencyResolution.value + val log = streams.value.log + val retrieveDir = streams.value.cacheDirectory / "scala3-compiler" / scalaVersion.value + val comp = lm.retrieve("org.scala-lang" % "scala3-compiler_3" % + scalaVersion.value, scalaModuleInfo = None, retrieveDir, log) + .fold(w => throw w.resolveException, identity) + Defaults.makeScalaInstance( + scalaVersion.value, + Array.empty, + comp.toSeq, + Seq.empty, + state.value, + scalaInstanceTopLoader.value, + )}, + ) + + // ============================================================================================== + // ======================================= SCALA COMPILER ======================================= + // ============================================================================================== + + /* Configuration of the org.scala-lang:scala3-compiler_3:*.**.**-nonbootstrapped project */ + lazy val `scala3-compiler-nonbootstrapped` = project.in(file("compiler")) + .dependsOn(`scala3-interfaces`, `tasty-core-nonbootstrapped`, `scala3-library-nonbootstrapped`) + .settings( + name := "scala3-compiler-nonbootstrapped", + moduleName := "scala3-compiler", + version := dottyNonBootstrappedVersion, + versionScheme := Some("semver-spec"), + scalaVersion := referenceVersion, // nonbootstrapped artifacts are compiled with the reference compiler (already officially published) + crossPaths := true, // org.scala-lang:scala3-compiler has a crosspath + // sbt shouldn't add stdlib automatically, we depend on `scala3-library-nonbootstrapped` + autoScalaLibrary := false, + // Add the source directories for the stdlib (non-boostrapped) + Compile / unmanagedSourceDirectories := Seq(baseDirectory.value / "src"), + Compile / unmanagedSourceDirectories += baseDirectory.value / "src-non-bootstrapped", + // All the dependencies needed by the compiler + libraryDependencies ++= Seq( + "org.scala-lang.modules" % "scala-asm" % "9.8.0-scala-1", + Dependencies.compilerInterface, + "org.jline" % "jline-reader" % "3.29.0", + "org.jline" % "jline-terminal" % "3.29.0", + "org.jline" % "jline-terminal-jni" % "3.29.0", + //("io.get-coursier" %% "coursier" % "2.0.16" % Test).cross(CrossVersion.for3Use2_13), + ), + // NOTE: The only difference here is that we drop `-Werror` and semanticDB for now + Compile / scalacOptions := Seq("-deprecation", "-feature", "-unchecked", "-encoding", "UTF8", "-language:implicitConversions"), + // TODO: Enable these flags when the new stdlib is explicitelly null checked + //Compile / scalacOptions ++= Seq("-Yexplicit-nulls", "-Wsafe-init"), + // Make sure that the produced artifacts have the minimum JVM version in the bytecode + Compile / javacOptions ++= Seq("--target", Versions.minimumJVMVersion), + Compile / scalacOptions ++= Seq("--java-output-version", Versions.minimumJVMVersion), + // Only publish compilation artifacts, no test artifacts + Compile / publishArtifact := true, + Test / publishArtifact := false, + // Do not allow to publish this project for now + publish / skip := true, + // Project specific target folder. sbt doesn't like having two projects using the same target folder + target := target.value / "scala3-compiler-nonbootstrapped", + // Generate compiler.properties, used by sbt + Compile / resourceGenerators += Def.task { + import java.util._ + import java.text._ + val file = (Compile / resourceManaged).value / "compiler.properties" + val dateFormat = new SimpleDateFormat("yyyyMMdd-HHmmss") + dateFormat.setTimeZone(TimeZone.getTimeZone("GMT")) + val contents = //2.11.11.v20170413-090219-8a413ba7cc + s"""version.number=${version.value} + |maven.version.number=${version.value} + |git.hash=${VersionUtil.gitHash} + |copyright.string=Copyright 2002-$currentYear, LAMP/EPFL + """.stripMargin + + if (!(file.exists && IO.read(file) == contents)) { + IO.write(file, contents) + } + + Seq(file) + }.taskValue, + // sbt adds all the projects to scala-tool config which breaks building the scalaInstance + // as a workaround, I build it manually by only adding the compiler + scalaInstance := { + val lm = dependencyResolution.value + val log = streams.value.log + val retrieveDir = streams.value.cacheDirectory / "scala3-compiler" / scalaVersion.value + val comp = lm.retrieve("org.scala-lang" % "scala3-compiler_3" % + scalaVersion.value, scalaModuleInfo = None, retrieveDir, log) + .fold(w => throw w.resolveException, identity) + Defaults.makeScalaInstance( + scalaVersion.value, + Array.empty, + comp.toSeq, + Seq.empty, + state.value, + scalaInstanceTopLoader.value, + )}, + /* Add the sources of scalajs-ir. + * To guarantee that dotty can bootstrap without depending on a version + * of scalajs-ir built with a different Scala compiler, we add its + * sources instead of depending on the binaries. + */ + ivyConfigurations += SourceDeps.hide, + transitiveClassifiers := Seq("sources"), + libraryDependencies += + ("org.scala-js" %% "scalajs-ir" % scalaJSVersion % "sourcedeps").cross(CrossVersion.for3Use2_13), + Compile / sourceGenerators += Def.task { + val s = streams.value + val cacheDir = s.cacheDirectory + val trgDir = (Compile / sourceManaged).value / "scalajs-ir-src" + + val report = updateClassifiers.value + val scalaJSIRSourcesJar = report.select( + configuration = configurationFilter("sourcedeps"), + module = (_: ModuleID).name.startsWith("scalajs-ir_"), + artifact = artifactFilter(`type` = "src")).headOption.getOrElse { + sys.error(s"Could not fetch scalajs-ir sources") + } + + FileFunction.cached(cacheDir / s"fetchScalaJSIRSource", + FilesInfo.lastModified, FilesInfo.exists) { dependencies => + s.log.info(s"Unpacking scalajs-ir sources to $trgDir...") + if (trgDir.exists) + IO.delete(trgDir) + IO.createDirectory(trgDir) + IO.unzip(scalaJSIRSourcesJar, trgDir) + + val sjsSources = (trgDir ** "*.scala").get.toSet + sjsSources.foreach(f => { + val lines = IO.readLines(f) + val linesWithPackage = replacePackage(lines) { + case "org.scalajs.ir" => "dotty.tools.sjs.ir" + } + IO.writeLines(f, insertUnsafeNullsImport(linesWithPackage)) + }) + sjsSources + } (Set(scalaJSIRSourcesJar)).toSeq + }.taskValue, + ) + def dottyLibrary(implicit mode: Mode): Project = mode match { case NonBootstrapped => `scala3-library` case Bootstrapped => `scala3-library-bootstrapped`