--- a/etc/build.props Fri Mar 25 17:21:39 2022 +0100
+++ b/etc/build.props Sat Mar 26 14:12:38 2022 +0100
@@ -25,6 +25,7 @@
src/Pure/Admin/build_pdfjs.scala \
src/Pure/Admin/build_polyml.scala \
src/Pure/Admin/build_release.scala \
+ src/Pure/Admin/build_scala.scala \
src/Pure/Admin/build_spass.scala \
src/Pure/Admin/build_sqlite.scala \
src/Pure/Admin/build_status.scala \
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Pure/Admin/build_scala.scala Sat Mar 26 14:12:38 2022 +0100
@@ -0,0 +1,161 @@
+/* Title: Pure/Admin/build_scala.scala
+ Author: Makarius
+
+Build Isabelle Scala component from official downloads.
+*/
+
+package isabelle
+
+
+object Build_Scala
+{
+ /* downloads */
+
+ sealed case class Download(
+ name: String,
+ version: String,
+ url: String,
+ physical_url: String = "",
+ base_version: String = "3")
+ {
+ def make_url(template: String): String =
+ template.replace("{V}", version).replace("{B}", base_version)
+
+ def proper_url: String = make_url(proper_string(physical_url).getOrElse(url))
+
+ def artifact: String =
+ Library.take_suffix[Char](_ != '/', proper_url.toList)._2.mkString
+
+ def get(path: Path, progress: Progress = new Progress): Unit =
+ Isabelle_System.download_file(proper_url, path, progress = progress)
+
+ def get_unpacked(dir: Path, strip: Int = 0, progress: Progress = new Progress): Unit =
+ Isabelle_System.with_tmp_file("archive")(archive_path =>
+ {
+ get(archive_path, progress = progress)
+ progress.echo("Unpacking " + artifact)
+ Isabelle_System.gnutar("-xzf " + File.bash_path(archive_path),
+ dir = dir, strip = strip).check
+ })
+
+ def print: String =
+ " * " + name + " " + version +
+ (if (base_version.nonEmpty) " for Scala " + base_version else "") +
+ ":\n " + make_url(url)
+ }
+
+ val main_download: Download =
+ Download("scala", "3.1.1", base_version = "",
+ url = "https://github.com/lampepfl/dotty/releases/download/{V}/scala3-{V}.tar.gz")
+
+ val lib_downloads: List[Download] = List(
+ Download("scala-parallel-collections", "1.0.4",
+ "https://mvnrepository.com/artifact/org.scala-lang.modules/scala-parallel-collections_{B}/{V}",
+ physical_url = "https://repo1.maven.org/maven2/org/scala-lang/modules/scala-parallel-collections_{B}/{V}/scala-parallel-collections_{B}-{V}.jar"),
+ Download("scala-parser-combinators", "2.1.1",
+ "https://mvnrepository.com/artifact/org.scala-lang.modules/scala-parser-combinators_{B}/{V}",
+ physical_url = "https://repo1.maven.org/maven2/org/scala-lang/modules/scala-parser-combinators_{B}/{V}/scala-parser-combinators_{B}-{V}.jar"),
+ Download("scala-swing", "3.0.0",
+ "https://mvnrepository.com/artifact/org.scala-lang.modules/scala-swing_{B}/{V}",
+ physical_url = "https://repo1.maven.org/maven2/org/scala-lang/modules/scala-swing_{B}/{V}/scala-swing_{B}-{V}.jar"),
+ Download("scala-xml", "2.0.1",
+ "https://mvnrepository.com/artifact/org.scala-lang.modules/scala-xml_{B}/{V}",
+ physical_url = "https://repo1.maven.org/maven2/org/scala-lang/modules/scala-xml_3/2.0.1/scala-xml_{B}-{V}.jar")
+ )
+
+
+ /* build Scala component */
+
+ def build_scala(
+ target_dir: Path = Path.current,
+ progress: Progress = new Progress): Unit =
+ {
+ /* component */
+
+ val component_name = main_download.name + "-" + main_download.version
+ val component_dir = Isabelle_System.new_directory(target_dir + Path.basic(component_name))
+ progress.echo("Component " + component_dir)
+
+
+ /* download */
+
+ main_download.get_unpacked(component_dir, strip = 1, progress = progress)
+
+ val lib_dir = component_dir + Path.explode("lib")
+ lib_downloads.foreach(download =>
+ download.get(lib_dir + Path.basic(download.artifact), progress = progress))
+
+ File.write(component_dir + Path.basic("LICENSE"),
+ Url.read(Url("https://www.apache.org/licenses/LICENSE-2.0.txt")))
+
+
+ /* classpath */
+
+ val classpath =
+ {
+ def no_function(name: String): String = "function " + name + "() {\n:\n}"
+ val script =
+ cat_lines(List(
+ no_function("stty"),
+ no_function("tput"),
+ "PROG_HOME=" + File.bash_path(component_dir),
+ File.read(component_dir + Path.explode("bin/common"))
+ .replace("scala_exit_status=127", "scala_exit_status=0"),
+ "compilerJavaClasspathArgs",
+ "echo \"$jvm_cp_args\""))
+
+ val main_classpath = Path.split(Isabelle_System.bash(script).check.out).map(_.file_name)
+ val lib_classpath = lib_downloads.map(_.artifact)
+
+ main_classpath ::: lib_classpath
+ }
+
+
+ /* settings */
+
+ val etc_dir = Isabelle_System.make_directory(component_dir + Path.basic("etc"))
+ File.write(etc_dir + Path.basic("settings"),
+ """# -*- shell-script -*- :mode=shellscript:
+
+SCALA_HOME="$COMPONENT"
+""" + terminate_lines(classpath.map(jar => "classpath \"$SCALA_HOME/lib/" + jar + "\"")))
+
+
+ /* README */
+
+ File.write(component_dir + Path.basic("README"),
+ "This distribution of Scala integrates the following parts:\n\n" +
+ (main_download :: lib_downloads).map(_.print).mkString("\n\n") + """
+
+
+ Makarius
+ """ + Date.Format.date(Date.now()) + "\n")
+ }
+
+
+ /* Isabelle tool wrapper */
+
+ val isabelle_tool =
+ Isabelle_Tool("build_scala", "build Isabelle Scala component from official downloads",
+ Scala_Project.here, args =>
+ {
+ var target_dir = Path.current
+
+ val getopts = Getopts("""
+Usage: isabelle build_scala [OPTIONS]
+
+ Options are:
+ -D DIR target directory (default ".")
+
+ Build Isabelle Scala component from official downloads.
+""",
+ "D:" -> (arg => target_dir = Path.explode(arg)))
+
+ val more_args = getopts(args)
+ if (more_args.nonEmpty) getopts.usage()
+
+ val progress = new Console_Progress()
+
+ build_scala(target_dir = target_dir, progress = progress)
+ })
+}
--- a/src/Pure/System/isabelle_tool.scala Fri Mar 25 17:21:39 2022 +0100
+++ b/src/Pure/System/isabelle_tool.scala Sat Mar 26 14:12:38 2022 +0100
@@ -227,6 +227,7 @@
Build_PolyML.isabelle_tool2,
Build_SPASS.isabelle_tool,
Build_SQLite.isabelle_tool,
+ Build_Scala.isabelle_tool,
Build_Status.isabelle_tool,
Build_Vampire.isabelle_tool,
Build_VeriT.isabelle_tool,