# HG changeset patch # User wenzelm # Date 1711481946 -3600 # Node ID b082476a8036a5532f3f47b318479c11b0e90855 # Parent 6964a23f595a6fdfa7fe6bc7953520382b76fb7d dynamic setup of Go component, similar to Dotnet; diff -r 6964a23f595a -r b082476a8036 etc/build.props --- a/etc/build.props Tue Mar 26 20:23:13 2024 +0100 +++ b/etc/build.props Tue Mar 26 20:39:06 2024 +0100 @@ -27,7 +27,6 @@ src/Pure/Admin/component_eptcs.scala \ src/Pure/Admin/component_foiltex.scala \ src/Pure/Admin/component_fonts.scala \ - src/Pure/Admin/component_go.scala \ src/Pure/Admin/component_hugo.scala \ src/Pure/Admin/component_javamail.scala \ src/Pure/Admin/component_jdk.scala \ @@ -212,6 +211,7 @@ src/Pure/Tools/dump.scala \ src/Pure/Tools/flarum.scala \ src/Pure/Tools/fontforge.scala \ + src/Pure/Tools/go_setup.scala \ src/Pure/Tools/java_monitor.scala \ src/Pure/Tools/logo.scala \ src/Pure/Tools/mkroot.scala \ diff -r 6964a23f595a -r b082476a8036 etc/settings --- a/etc/settings Tue Mar 26 20:23:13 2024 +0100 +++ b/etc/settings Tue Mar 26 20:39:06 2024 +0100 @@ -186,6 +186,13 @@ ### +### Go +### + +ISABELLE_GO_VERSION="1.22.1" + + +### ### Misc settings ### diff -r 6964a23f595a -r b082476a8036 lib/Tools/go --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lib/Tools/go Tue Mar 26 20:39:06 2024 +0100 @@ -0,0 +1,13 @@ +#!/usr/bin/env bash +# +# Author: Makarius +# +# DESCRIPTION: invoke go within the Isabelle environment + +if [ -z "$ISABELLE_GOEXE" ]; then + echo "Missing Go installation: need to run \"isabelle go_setup\" first" >&2 + exit 2 +else + export GOROOT="$ISABELLE_GOROOT" + exec "$ISABELLE_GOEXE/go" "$@" +fi diff -r 6964a23f595a -r b082476a8036 lib/Tools/gofmt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lib/Tools/gofmt Tue Mar 26 20:39:06 2024 +0100 @@ -0,0 +1,13 @@ +#!/usr/bin/env bash +# +# Author: Makarius +# +# DESCRIPTION: invoke gofmt within the Isabelle environment + +if [ -z "$ISABELLE_GOEXE" ]; then + echo "Missing Go installation: need to run \"isabelle go_setup\" first" >&2 + exit 2 +else + export GOROOT="$ISABELLE_GOROOT" + exec "$ISABELLE_GOEXE/gofmt" "$@" +fi diff -r 6964a23f595a -r b082476a8036 src/Pure/Admin/component_go.scala --- a/src/Pure/Admin/component_go.scala Tue Mar 26 20:23:13 2024 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,152 +0,0 @@ -/* Title: Pure/Admin/component_go.scala - Author: Makarius - -Build Isabelle component for Go: https://go.dev -*/ - -package isabelle - - -object Component_Go { - /* platform information */ - - sealed case class Platform_Info(platform: String, go_platform: String) - extends Platform.Info { - def paths: List[String] = List(platform, "pkg/tool/" + go_platform) - - def download(base_url: String, version: String): String = { - val ext = if (is_windows) ".zip" else ".tar.gz" - Url.append_path(base_url, "go" + version + "." + go_platform.replace("_", "-") + ext) - } - } - - val all_platforms: List[Platform_Info] = - List( - Platform_Info("arm64-darwin", "darwin_arm64"), - Platform_Info("arm64-linux", "linux_arm64"), - Platform_Info("x86_64-darwin", "darwin_amd64"), - Platform_Info("x86_64-linux", "linux_amd64"), - Platform_Info("x86_64-windows", "windows_amd64")) - - - /* build go */ - - val default_url = "https://go.dev/dl" - val default_version = "1.22.1" - - def build_go( - base_url: String = default_url, - version: String = default_version, - target_dir: Path = Path.current, - progress: Progress = new Progress - ): Unit = { - val component_dir = - Components.Directory(target_dir + Path.basic("go-" + version)).create(progress = progress) - - - /* download */ - - Isabelle_System.with_tmp_dir("download") { download_dir => - for (platform <- all_platforms.reverse) { - val download = platform.download(base_url, version) - - val archive_name = - Url.get_base_name(download) getOrElse - error("Malformed download URL " + quote(download)) - val archive_path = download_dir + Path.basic(archive_name) - - Isabelle_System.download_file(download, archive_path, progress = progress) - Isabelle_System.extract(archive_path, component_dir.path, strip = true) - - val platform_dir = component_dir.path + platform.path - Isabelle_System.move_file(component_dir.bin, platform_dir) - } - } - - File.find_files(component_dir.path.file, pred = file => File.is_exe(file.getName)). - foreach(file => File.set_executable(File.path(file))) - - - /* isabelle tool */ - - val isabelle_tool_dir = component_dir.path + Path.explode("isabelle_tool") - Isabelle_System.make_directory(isabelle_tool_dir) - - for (tool <- List("go", "gofmt")) { - val isabelle_tool = isabelle_tool_dir + Path.basic(tool) - File.write(isabelle_tool, -"""#!/usr/bin/env bash -# -# Author: Makarius -# -# DESCRIPTION: invoke """ + tool + """ within the Isabelle environment - -export GOROOT="$ISABELLE_GOROOT" -exec "$ISABELLE_GOEXE/""" + tool + """" "$@" -""") - File.set_executable(isabelle_tool) - } - - - /* settings */ - - component_dir.write_settings(""" -ISABELLE_GOROOT="$COMPONENT" -ISABELLE_GOEXE="$ISABELLE_GOROOT/${ISABELLE_WINDOWS_PLATFORM64:-${ISABELLE_APPLE_PLATFORM64:-$ISABELLE_PLATFORM64}}" - -ISABELLE_TOOLS="$ISABELLE_TOOLS:$ISABELLE_GOROOT/isabelle_tool" -""") - - - /* platform.props */ - - File.write(component_dir.platform_props, - (for ((a, b) <- all_platforms.groupBy(_.family_name).iterator) - yield a + " = " + b.flatMap(_.paths).mkString(" ") - ).mkString("", "\n", "\n")) - - - /* README */ - - File.write(component_dir.README, - """This distribution of Go has been assembled from official downloads from -""" + base_url + """ - - - Makarius - """ + Date.Format.date(Date.now()) + "\n") - } - - - /* Isabelle tool wrapper */ - - val isabelle_tool = - Isabelle_Tool("component_go", "build component for Go", Scala_Project.here, - { args => - var target_dir = Path.current - var base_url = default_url - var version = default_version - - val getopts = Getopts(""" -Usage: isabelle component_go [OPTIONS] - - Options are: - -D DIR target directory (default ".") - -U URL download URL (default: """" + default_url + """") - -V VERSION version (default: """" + default_version + """") - - Build component for Go development environment. -""", - "D:" -> (arg => target_dir = Path.explode(arg)), - "U:" -> (arg => base_url = arg), - "V:" -> (arg => version = arg)) - - val more_args = getopts(args) - if (more_args.nonEmpty) getopts.usage() - - val progress = new Console_Progress() - - build_go(base_url = base_url, version = version, target_dir = target_dir, - progress = progress) - }) -} diff -r 6964a23f595a -r b082476a8036 src/Pure/System/components.scala --- a/src/Pure/System/components.scala Tue Mar 26 20:23:13 2024 +0100 +++ b/src/Pure/System/components.scala Tue Mar 26 20:39:06 2024 +0100 @@ -202,9 +202,11 @@ def README: Path = path + Path.basic("README") def LICENSE: Path = path + Path.basic("LICENSE") - def create(progress: Progress = new Progress): Directory = { - progress.echo("Creating component directory " + toString) - ssh.new_directory(path) + def create(progress: Progress = new Progress, permissive: Boolean = false): Directory = { + if (!permissive || !ssh.is_dir(path)) { + progress.echo("Creating component directory " + toString) + ssh.new_directory(path) + } ssh.make_directory(etc) this } diff -r 6964a23f595a -r b082476a8036 src/Pure/System/isabelle_tool.scala --- a/src/Pure/System/isabelle_tool.scala Tue Mar 26 20:23:13 2024 +0100 +++ b/src/Pure/System/isabelle_tool.scala Tue Mar 26 20:39:06 2024 +0100 @@ -135,6 +135,7 @@ Dotnet_Setup.isabelle_tool, Dump.isabelle_tool, Export.isabelle_tool, + Go_Setup.isabelle_tool, Logo.isabelle_tool, ML_Process.isabelle_tool, Mercurial.isabelle_tool1, @@ -175,7 +176,6 @@ Component_Easychair.isabelle_tool, Component_Foiltex.isabelle_tool, Component_Fonts.isabelle_tool, - Component_Go.isabelle_tool, Component_Hugo.isabelle_tool, Component_Javamail.isabelle_tool, Component_JDK.isabelle_tool, diff -r 6964a23f595a -r b082476a8036 src/Pure/Tools/go_setup.scala --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/Pure/Tools/go_setup.scala Tue Mar 26 20:39:06 2024 +0100 @@ -0,0 +1,172 @@ +/* Title: Pure/Tools/go_setup.scala + Author: Makarius + +Dynamic setup of Go component. +*/ + +package isabelle + + +object Go_Setup { + /* platform information */ + + sealed case class Platform_Info(platform: String, go_platform: String) + extends Platform.Info { + def paths: List[String] = List(platform, "pkg/tool/" + go_platform) + + def download(base_url: String, version: String): String = { + val ext = if (is_windows) ".zip" else ".tar.gz" + Url.append_path(base_url, "go" + version + "." + go_platform.replace("_", "-") + ext) + } + } + + val all_platforms: List[Platform_Info] = + List( + Platform_Info("arm64-darwin", "darwin_arm64"), + Platform_Info("arm64-linux", "linux_arm64"), + Platform_Info("x86_64-darwin", "darwin_amd64"), + Platform_Info("x86_64-linux", "linux_amd64"), + Platform_Info("x86_64-windows", "windows_amd64")) + + def check_platform_spec(spec: String): String = + Platform.check_spec(all_platforms, spec) + + + /* Go download and setup */ + + def default_platform: String = + Isabelle_Platform.self.ISABELLE_PLATFORM(windows = true, apple = true) + def default_target_dir: Path = Components.default_components_base + val default_url = "https://go.dev/dl" + def default_version: String = Isabelle_System.getenv_strict("ISABELLE_GO_VERSION") + + def go_setup( + platforms: List[String] = List(default_platform), + base_url: String = default_url, + version: String = default_version, + target_dir: Path = default_target_dir, + progress: Progress = new Progress, + force: Boolean = false + ): Unit = { + platforms.foreach(check_platform_spec) + + + /* component directory */ + + val component_dir = + Components.Directory(target_dir + Path.basic("go-" + version)).create(permissive = true) + + progress.echo("Component directory " + component_dir) + + component_dir.write_settings(""" +ISABELLE_GOROOT="$COMPONENT" + +if [ -n "$ISABELLE_WINDOWS_PLATFORM64" -a -d "$ISABELLE_GOROOT/$ISABELLE_WINDOWS_PLATFORM64" ]; then + ISABELLE_GOEXE="$ISABELLE_GOROOT/$ISABELLE_WINDOWS_PLATFORM64" +elif [ -n "$ISABELLE_APPLE_PLATFORM64" -a -d "$ISABELLE_GOROOT/$ISABELLE_APPLE_PLATFORM64" ]; then + ISABELLE_GOEXE="$ISABELLE_GOROOT/$ISABELLE_APPLE_PLATFORM64" +elif [ -d "$ISABELLE_GOROOT/$ISABELLE_PLATFORM64" ]; then + ISABELLE_GOEXE="$ISABELLE_GOROOT/$ISABELLE_PLATFORM64" +fi +""") + + File.write(component_dir.platform_props, + (for ((a, b) <- all_platforms.groupBy(_.family_name).iterator) + yield a + " = " + b.flatMap(_.paths).mkString(" ") + ).mkString("", "\n", "\n")) + + for (old <- proper_string(Isabelle_System.getenv("ISABELLE_GOROOT"))) { + Components.update_components(false, Path.explode(old)) + } + + Components.update_components(true, component_dir.path) + + + /* download and setup */ + + Isabelle_System.with_tmp_dir("download") { download_dir => + for (platform <- all_platforms if platforms.exists(platform.is)) { + val platform_dir = component_dir.path + platform.path + if (platform_dir.is_dir && !force) { + progress.echo_warning("Platform " + platform + " already installed") + } + else { + progress.echo("Platform " + platform + " ...") + progress.expose_interrupt() + + if (force) { + for (name <- platform.paths) { + val dir = component_dir.path + Path.explode(name) + if (dir.is_dir) Isabelle_System.rm_tree(dir) + } + } + + val download = platform.download(base_url, version) + + val archive_name = + Url.get_base_name(download) getOrElse + error("Malformed download URL " + quote(download)) + val archive_path = download_dir + Path.basic(archive_name) + + Isabelle_System.download_file(download, archive_path) + Isabelle_System.extract(archive_path, component_dir.path, strip = true) + Isabelle_System.move_file(component_dir.bin, platform_dir) + } + } + } + + File.find_files(component_dir.path.file, pred = file => File.is_exe(file.getName)). + foreach(file => File.set_executable(File.path(file))) + + + /* README */ + + File.write(component_dir.README, + """This installation of Go has been produced via "isabelle go_setup". + + + Makarius + """ + Date.Format.date(Date.now()) + "\n") + } + + + /* Isabelle tool wrapper */ + + val isabelle_tool = + Isabelle_Tool("go_setup", "dynamic setup of Go component", Scala_Project.here, + { args => + var target_dir = default_target_dir + var base_url = default_url + var version = default_version + var force = false + var platforms = List(default_platform) + + val getopts = Getopts(""" +Usage: isabelle go_setup [OPTIONS] + + Options are: + -D DIR target directory (default ".") + -U URL download URL (default: """" + default_url + """") + -V VERSION version (default: """" + default_version + """") + -f force fresh installation of specified platforms + -p PLATFORMS comma-separated list of platform specifications, + as family or formal name (default: """ + quote(default_platform) + """) + + Download the Go development environment and configure it as Isabelle + component. See also https://go.dev +""", + "D:" -> (arg => target_dir = Path.explode(arg)), + "U:" -> (arg => base_url = arg), + "V:" -> (arg => version = arg), + "f" -> (_ => force = true), + "p:" -> (arg => platforms = space_explode(',', arg).map(check_platform_spec))) + + val more_args = getopts(args) + if (more_args.nonEmpty) getopts.usage() + + val progress = new Console_Progress() + + go_setup(platforms = platforms, base_url = base_url, version = version, + target_dir = target_dir, progress = progress, force = force) + }) +}