From c8ae057a7c4a765434636c5281306f783001ee68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patryk=20Zieli=C5=84ski?= Date: Tue, 4 Nov 2025 13:19:02 +0100 Subject: [PATCH 1/2] add properties file for scala3 library --- library/src/scala/util/Properties.scala | 7 ++++++ project/Build.scala | 26 +++++++++++++++++++++++ tests/run/properties-version-string.check | 1 + tests/run/properties-version-string.scala | 7 ++++++ 4 files changed, 41 insertions(+) create mode 100644 tests/run/properties-version-string.check create mode 100644 tests/run/properties-version-string.scala diff --git a/library/src/scala/util/Properties.scala b/library/src/scala/util/Properties.scala index 765d5d17e5dc..dd520a62ef44 100644 --- a/library/src/scala/util/Properties.scala +++ b/library/src/scala/util/Properties.scala @@ -34,6 +34,7 @@ private[scala] trait PropertiesTrait { /** The name of the properties file */ protected val propFilename = "/" + propCategory + ".properties" + protected val lib3Filename = "/library3.properties" /** The loaded properties */ protected lazy val scalaProps: java.util.Properties = { @@ -42,6 +43,12 @@ private[scala] trait PropertiesTrait { if (stream ne null) quietlyDispose(props.load(stream), stream.close) + // If available in the same jar as the stdlib classes, overlay Scala 3 + // runtime properties contained in `library3.properties` (e.g., version.number). + val lib3Stream = pickJarBasedOn.getResourceAsStream(lib3Filename) + if (lib3Stream ne null) + quietlyDispose(props.load(lib3Stream), lib3Stream.close) + props } diff --git a/project/Build.scala b/project/Build.scala index 824405decc84..6af2bc00c48c 100644 --- a/project/Build.scala +++ b/project/Build.scala @@ -1916,6 +1916,19 @@ object Build { customMimaReportBinaryIssues("MiMaFilters.Scala3Library"), // Should we also patch .sjsir files keepSJSIR := false, + Compile / resourceGenerators += Def.task { + val file = (Compile / resourceManaged).value / "library3.properties" + val contents = + s"""version.number=${version.value} + |maven.version.number=${version.value} + |""".stripMargin + + if (!(file.exists && IO.read(file) == contents)) { + IO.write(file, contents) + } + + Seq(file) + }.taskValue, ) /* Configuration of the org.scala-lang:scala3-library_3:*.**.**-nonbootstrapped project */ @@ -2041,6 +2054,19 @@ object Build { customMimaReportBinaryIssues("MiMaFilters.Scala3Library"), // Should we also patch .sjsir files keepSJSIR := false, + Compile / resourceGenerators += Def.task { + val file = (Compile / resourceManaged).value / "library3.properties" + val contents = + s"""version.number=${version.value} + |maven.version.number=${version.value} + |""".stripMargin + + if (!(file.exists && IO.read(file) == contents)) { + IO.write(file, contents) + } + + Seq(file) + }.taskValue, ) /* Configuration of the org.scala-lang:scala3-library_3:*.**.**-bootstrapped project */ diff --git a/tests/run/properties-version-string.check b/tests/run/properties-version-string.check new file mode 100644 index 000000000000..d86bac9de59a --- /dev/null +++ b/tests/run/properties-version-string.check @@ -0,0 +1 @@ +OK diff --git a/tests/run/properties-version-string.scala b/tests/run/properties-version-string.scala new file mode 100644 index 000000000000..57e4adc92771 --- /dev/null +++ b/tests/run/properties-version-string.scala @@ -0,0 +1,7 @@ +object Test { + def main(args: Array[String]): Unit = { + val v = scala.util.Properties.versionNumberString + if (v.nonEmpty && !v.startsWith("2.")) println("OK") + else println("FAIL " + v) + } +} From 235846638a90574f8d8b05b996b25b80320c511f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patryk=20Zieli=C5=84ski?= Date: Wed, 5 Nov 2025 01:05:46 +0100 Subject: [PATCH 2/2] address review --- library/src/scala/util/Properties.scala | 7 - project/Build.scala | 138 +++++++----------- .../compiler-version-string.scala | 7 + tests/run/properties-version-string.check | 1 - tests/run/properties-version-string.scala | 4 +- 5 files changed, 64 insertions(+), 93 deletions(-) create mode 100644 tests/run-with-compiler/compiler-version-string.scala delete mode 100644 tests/run/properties-version-string.check diff --git a/library/src/scala/util/Properties.scala b/library/src/scala/util/Properties.scala index dd520a62ef44..765d5d17e5dc 100644 --- a/library/src/scala/util/Properties.scala +++ b/library/src/scala/util/Properties.scala @@ -34,7 +34,6 @@ private[scala] trait PropertiesTrait { /** The name of the properties file */ protected val propFilename = "/" + propCategory + ".properties" - protected val lib3Filename = "/library3.properties" /** The loaded properties */ protected lazy val scalaProps: java.util.Properties = { @@ -43,12 +42,6 @@ private[scala] trait PropertiesTrait { if (stream ne null) quietlyDispose(props.load(stream), stream.close) - // If available in the same jar as the stdlib classes, overlay Scala 3 - // runtime properties contained in `library3.properties` (e.g., version.number). - val lib3Stream = pickJarBasedOn.getResourceAsStream(lib3Filename) - if (lib3Stream ne null) - quietlyDispose(props.load(lib3Stream), lib3Stream.close) - props } diff --git a/project/Build.scala b/project/Build.scala index 6af2bc00c48c..99ec6e6910ca 100644 --- a/project/Build.scala +++ b/project/Build.scala @@ -433,6 +433,54 @@ object Build { private lazy val currentYear: String = java.util.Calendar.getInstance().get(java.util.Calendar.YEAR).toString + private val shellBanner: String = + """%n ________ ___ / / ___ + |%n / __/ __// _ | / / / _ | + |%n __\\ \\/ /__/ __ |/ /__/ __ | + |%n /____/\\___/_/ |_/____/_/ | | + |%n |/ %s""".stripMargin.replace("\n", "") + + // Common generator for properties files + lazy val generatePropertiesFile = (fileName: String, contents: Def.Initialize[String]) => Def.task { + val file = (Compile / resourceManaged).value / fileName + val data = contents.value + if (!(file.exists && IO.read(file) == data)) { + IO.write(file, data) + } + Seq(file) + } + + // Generate compiler.properties consumed by sbt + lazy val generateCompilerProperties: Def.Initialize[Task[Seq[File]]] = { + import java.util._ + import java.text._ + val dateFormat = new SimpleDateFormat("yyyyMMdd-HHmmss") + dateFormat.setTimeZone(TimeZone.getTimeZone("GMT")) + + val fileName = "compiler.properties" + val contents = Def.setting { + s"""version.number=${version.value} + |maven.version.number=${version.value} + |git.hash=${VersionUtil.gitHash} + |copyright.string=Copyright 2002-$currentYear, LAMP/EPFL + |""".stripMargin + } + generatePropertiesFile(fileName, contents) + } + + // Generate library.properties consumed by scala.util.Properties + lazy val generateLibraryProperties: Def.Initialize[Task[Seq[File]]] = { + val fileName = "library.properties" + val contents = Def.setting { + s"""version.number=${version.value} + |maven.version.number=${version.value} + |copyright.string=Copyright 2002-$currentYear, LAMP/EPFL + |shell.banner=${shellBanner} + |""".stripMargin + } + generatePropertiesFile(fileName, contents) + } + def scalacOptionsDocSettings(includeExternalMappings: Boolean = true) = { val extMap = Seq("-external-mappings:" + (if (includeExternalMappings) ".*scala/.*::scaladoc3::https://dotty.epfl.ch/api/," else "") + @@ -700,25 +748,7 @@ object Build { scalacOptions += "-Wconf:cat=deprecation&origin=scala\\.collection\\.mutable\\.AnyRefMap.*:s", // 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, + (Compile / resourceGenerators) += generateCompilerProperties.taskValue, // get libraries onboard libraryDependencies ++= Seq( @@ -1916,19 +1946,8 @@ object Build { customMimaReportBinaryIssues("MiMaFilters.Scala3Library"), // Should we also patch .sjsir files keepSJSIR := false, - Compile / resourceGenerators += Def.task { - val file = (Compile / resourceManaged).value / "library3.properties" - val contents = - s"""version.number=${version.value} - |maven.version.number=${version.value} - |""".stripMargin - - if (!(file.exists && IO.read(file) == contents)) { - IO.write(file, contents) - } - - Seq(file) - }.taskValue, + // Generate library.properties, used by scala.util.Properties + Compile / resourceGenerators += generateLibraryProperties.taskValue ) /* Configuration of the org.scala-lang:scala3-library_3:*.**.**-nonbootstrapped project */ @@ -2054,19 +2073,8 @@ object Build { customMimaReportBinaryIssues("MiMaFilters.Scala3Library"), // Should we also patch .sjsir files keepSJSIR := false, - Compile / resourceGenerators += Def.task { - val file = (Compile / resourceManaged).value / "library3.properties" - val contents = - s"""version.number=${version.value} - |maven.version.number=${version.value} - |""".stripMargin - - if (!(file.exists && IO.read(file) == contents)) { - IO.write(file, contents) - } - - Seq(file) - }.taskValue, + // Generate Scala 3 runtime properties overlay + Compile / resourceGenerators += generateLibraryProperties.taskValue, ) /* Configuration of the org.scala-lang:scala3-library_3:*.**.**-bootstrapped project */ @@ -2470,25 +2478,7 @@ object Build { // 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, + Compile / resourceGenerators += generateCompilerProperties.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 managedScalaInstance := false, @@ -2638,25 +2628,7 @@ object Build { // Project specific target folder. sbt doesn't like having two projects using the same target folder target := target.value / "scala3-compiler-bootstrapped", // 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, + Compile / resourceGenerators += generateCompilerProperties.taskValue, // Configure to use the non-bootstrapped compiler managedScalaInstance := false, scalaInstance := { diff --git a/tests/run-with-compiler/compiler-version-string.scala b/tests/run-with-compiler/compiler-version-string.scala new file mode 100644 index 000000000000..327f402cfdfc --- /dev/null +++ b/tests/run-with-compiler/compiler-version-string.scala @@ -0,0 +1,7 @@ +// scalajs: --skip +object Test { + def main(args: Array[String]): Unit = { + val v = dotty.tools.dotc.config.Properties.versionNumberString + assert(v.nonEmpty && v.startsWith("3.")) + } +} diff --git a/tests/run/properties-version-string.check b/tests/run/properties-version-string.check deleted file mode 100644 index d86bac9de59a..000000000000 --- a/tests/run/properties-version-string.check +++ /dev/null @@ -1 +0,0 @@ -OK diff --git a/tests/run/properties-version-string.scala b/tests/run/properties-version-string.scala index 57e4adc92771..3b4ac030a383 100644 --- a/tests/run/properties-version-string.scala +++ b/tests/run/properties-version-string.scala @@ -1,7 +1,7 @@ +// scalajs: --skip object Test { def main(args: Array[String]): Unit = { val v = scala.util.Properties.versionNumberString - if (v.nonEmpty && !v.startsWith("2.")) println("OK") - else println("FAIL " + v) + assert(v.nonEmpty && v.startsWith("3.")) } }