# HG changeset patch # User wenzelm # Date 1646430829 -3600 # Node ID a51a0a7048540b5fb9ce41042f1403a03a1dd3eb # Parent e3475e1d509438d4682bf214e0539a7ea97da81f build component for VSCodium (cross-compiled from sources for all platforms); diff -r e3475e1d5094 -r a51a0a704854 etc/build.props --- a/etc/build.props Fri Mar 04 22:50:58 2022 +0100 +++ b/etc/build.props Fri Mar 04 22:53:49 2022 +0100 @@ -30,6 +30,7 @@ src/Pure/Admin/build_status.scala \ src/Pure/Admin/build_vampire.scala \ src/Pure/Admin/build_verit.scala \ + src/Pure/Admin/build_vscodium.scala \ src/Pure/Admin/build_zipperposition.scala \ src/Pure/Admin/check_sources.scala \ src/Pure/Admin/ci_profile.scala \ diff -r e3475e1d5094 -r a51a0a704854 src/Pure/Admin/build_vscodium.scala --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/Pure/Admin/build_vscodium.scala Fri Mar 04 22:53:49 2022 +0100 @@ -0,0 +1,278 @@ +/* Title: Pure/Admin/build_vscodium.scala + Author: Makarius + +Build component for VSCodium (cross-compiled from sources for all platforms). +*/ + +package isabelle + + +import java.security.MessageDigest +import java.util.Base64 + + +object Build_VSCodium +{ + /* patch resources */ + + // see https://github.com/microsoft/vscode/blob/main/build/gulpfile.vscode.js + // function computeChecksum(filename) + + def file_checksum(path: Path): String = + { + val digest = MessageDigest.getInstance("MD5") + digest.update(Bytes.read(path).array) + Bytes(Base64.getEncoder.encode(digest.digest())) + .text.replaceAll("=", "") + } + + def patch_resources(dir: Path): Unit = + { + HTML.init_fonts(dir + Path.explode("app/out/vs/base/browser/ui")) + + val workbench_css = dir + Path.explode("app/out/vs/workbench/workbench.desktop.main.css") + val checksum1 = file_checksum(workbench_css) + File.append(workbench_css, "\n\n" + HTML.fonts_css_dir(prefix = "../base/browser/ui")) + val checksum2 = file_checksum(workbench_css) + + val file_name = workbench_css.file_name + File.change_lines(dir + Path.explode("app/product.json")) { _.map(line => + if (line.containsSlice(file_name) && line.contains(checksum1)) { + line.replace(checksum1, checksum2) + } + else line) + } + } + + + /* platform info */ + + sealed case class Platform_Info( + platform: Platform.Family.Value, build_name: String, env: List[String]) + { + def platform_dir(dir: Path): Path = + { + val platform_name = + if (platform == Platform.Family.windows) Platform.Family.native(platform) + else Platform.Family.standard(platform) + dir + Path.explode(platform_name) + } + + def resources_dir(dir: Path): Path = + { + val resources = + if (platform == Platform.Family.macos) "VSCodium.app/Contents/Resources" + else "resources" + dir + Path.explode(resources) + } + + def build_dir(dir: Path): Path = dir + Path.explode(build_name) + + def environment(version: String): String = + (("MS_TAG=" + Bash.string(version)) :: "SHOULD_BUILD=yes" :: "VSCODE_ARCH=x64" :: env) + .map(s => "export " + s + "\n").mkString + } + + private val platform_info: Map[Platform.Family.Value, Platform_Info] = + Iterator( + Platform_Info(Platform.Family.linux, "VSCode-linux-x64", + List("OS_NAME=linux", "SKIP_LINUX_PACKAGES=True")), + Platform_Info(Platform.Family.linux_arm, "VSCode-linux-arm64", + List("OS_NAME=linux", "SKIP_LINUX_PACKAGES=True", "VSCODE_ARCH=arm64")), + Platform_Info(Platform.Family.macos, "VSCode-darwin-x64", + List("OS_NAME=osx")), + Platform_Info(Platform.Family.windows, "VSCode-win32-x64", + List("OS_NAME=windows", + "SHOULD_BUILD_ZIP=no", + "SHOULD_BUILD_EXE_SYS=no", + "SHOULD_BUILD_EXE_USR=no", + "SHOULD_BUILD_MSI=no", + "SHOULD_BUILD_MSI_NOUP=no"))) + .map(info => info.platform -> info).toMap + + + /* build vscodium */ + + val default_repository_url = "https://github.com/VSCodium/vscodium.git" + val default_version = "1.64.2" + def default_platforms: List[Platform.Family.Value] = Platform.Family.list + + private def vscodium_exe(dir: Path): Path = dir + Path.explode("bin/codium") + + private def macos_exe: String = +"""#!/usr/bin/env bash + +unset CDPATH +VSCODE_PATH="$(cd "$(dirname "$0")"/../VSCodium.app/Contents; pwd)" + +ELECTRON="$VSCODE_PATH/MacOS/Electron" +CLI="$VSCODE_PATH/Resources/app/out/cli.js" +ELECTRON_RUN_AS_NODE=1 "$ELECTRON" "$CLI" --ms-enable-electron-run-as-node "$@" +exit $? +""" + + def build_vscodium( + target_dir: Path = Path.current, + repository_url: String = default_repository_url, + version: String = default_version, + platforms: List[Platform.Family.Value] = default_platforms, + verbose: Boolean = false, + progress: Progress = new Progress): Unit = + { + /* prerequisites */ + + Linux.check_system() + + Isabelle_System.require_command("git") + if (platforms.nonEmpty) { + Isabelle_System.require_command("node") + Isabelle_System.require_command("yarn") + Isabelle_System.require_command("jq") + } + if (platforms.contains(Platform.Family.windows)) { + Isabelle_System.require_command("wine") + } + + + /* component */ + + val component_name = "vscodium-" + version + val component_dir = Isabelle_System.new_directory(target_dir + Path.basic(component_name)) + progress.echo("Component " + component_dir) + + + /* build */ + + for (platform <- platforms) { + val info = + platform_info.getOrElse(platform, error("No platform info for " + quote(platform.toString))) + + progress.echo("Building " + platform + " ...") + + Isabelle_System.with_tmp_dir("vscodium")(vscodium_dir => + { + def execute(lines: String*): Unit = + progress.bash(("set -e" :: info.environment(version) :: lines.toList).mkString("\n"), + cwd = vscodium_dir.file, echo = verbose).check + + execute( + "git clone -n " + Bash.string(repository_url) + " .", + "git checkout -q " + Bash.string(version), + "./get_repo.sh") + + for (name <- Seq("vscode/build/lib/electron.js", "vscode/build/lib/electron.ts")) { + File.change(vscodium_dir + Path.explode(name), strict = true) { + _.replace("""'resources/darwin/' + icon + '.icns'""", + """'resources/darwin/' + icon.toLowerCase() + '.icns'""") + } + } + + execute("./build.sh") + + val platform_dir = info.platform_dir(component_dir) + Isabelle_System.copy_dir(info.build_dir(vscodium_dir), platform_dir) + Isabelle_System.copy_file(vscodium_dir + Path.explode("LICENSE"), component_dir) + + patch_resources(info.resources_dir(platform_dir)) + + val exe = vscodium_exe(platform_dir) + Isabelle_System.make_directory(exe.dir) + + platform match { + case Platform.Family.macos => + File.write(exe, macos_exe) + File.set_executable(exe, true) + case Platform.Family.windows => + val files1 = File.find_files(exe.dir.file) + val files2 = + File.find_files(platform_dir.file, + pred = file => file.getName.endsWith(".exe") || file.getName.endsWith(".dll")) + for (file <- files1 ::: files2) File.set_executable(File.path(file), true) + Isabelle_System.bash("chmod -R o-w " + File.bash_path(platform_dir)) + case _ => + } + }) + } + + + /* settings */ + + val etc_dir = Isabelle_System.make_directory(component_dir + Path.explode("etc")) + File.write(etc_dir + Path.basic("settings"), + """# -*- shell-script -*- :mode=shellscript: + +ISABELLE_VSCODIUM_HOME="$COMPONENT/${ISABELLE_WINDOWS_PLATFORM64:-$ISABELLE_PLATFORM64}" + +case "$ISABELLE_PLATFORM_FAMILY" in + linux) + ISABELLE_ELECTRON="$ISABELLE_VSCODIUM_HOME/codium" + ;; + macos) + ISABELLE_ELECTRON="$ISABELLE_VSCODIUM_HOME/VSCodium.app/Contents/MacOS/Electron" + ;; + windows) + ISABELLE_ELECTRON="$ISABELLE_VSCODIUM_HOME/VSCodium.exe" + ;; +esac +""") + + + /* README */ + + File.write(component_dir + Path.basic("README"), + "This is VSCodium " + version + " from " + repository_url + +""" + +It has been built from sources using "isabelle build_vscodium": this applies +a few changes required for Isabelle/VSCode. + + + Makarius + """ + Date.Format.date(Date.now()) + "\n") + } + + + /* Isabelle tool wrapper */ + + val isabelle_tool = + Isabelle_Tool("build_vscodium", "build component for VSCodium", + Scala_Project.here, args => + { + var target_dir = Path.current + var repository_url = default_repository_url + var version = default_version + var platforms = default_platforms + var verbose = false + + val getopts = Getopts(""" +Usage: vscode_setup [OPTIONS] + + Options are: + -D DIR target directory (default ".") + -U URL repository URL + (default: """" + default_repository_url + """") + -V VERSION version (default: """" + default_version + """") + -p NAMES platform families + (default: """ + quote(platforms.mkString(",")) + """) + -v verbose + + Build VSCodium from sources and turn it into an Isabelle component. + + The build platform needs to be Linux with nodejs/yarn, jq, and wine + for targeting Windows. +""", + "D:" -> (arg => target_dir = Path.explode(arg)), + "U:" -> (arg => repository_url = arg), + "V:" -> (arg => version = arg), + "p:" -> (arg => platforms = Library.space_explode(',', arg).map(Platform.Family.parse)), + "v" -> (_ => verbose = true)) + + val more_args = getopts(args) + if (more_args.nonEmpty) getopts.usage() + + val progress = new Console_Progress() + + build_vscodium(target_dir = target_dir, repository_url = repository_url, + version = version, platforms = platforms, verbose = verbose, progress = progress) + }) +} diff -r e3475e1d5094 -r a51a0a704854 src/Pure/System/isabelle_tool.scala --- a/src/Pure/System/isabelle_tool.scala Fri Mar 04 22:50:58 2022 +0100 +++ b/src/Pure/System/isabelle_tool.scala Fri Mar 04 22:53:49 2022 +0100 @@ -231,6 +231,7 @@ Build_Status.isabelle_tool, Build_Vampire.isabelle_tool, Build_VeriT.isabelle_tool, + Build_VSCodium.isabelle_tool, Build_Zipperposition.isabelle_tool, Check_Sources.isabelle_tool, Components.isabelle_tool, diff -r e3475e1d5094 -r a51a0a704854 src/Tools/VSCode/src/vscode_setup.scala --- a/src/Tools/VSCode/src/vscode_setup.scala Fri Mar 04 22:50:58 2022 +0100 +++ b/src/Tools/VSCode/src/vscode_setup.scala Fri Mar 04 22:53:49 2022 +0100 @@ -23,6 +23,8 @@ def vscode_version: String = Isabelle_System.getenv_strict("ISABELLE_VSCODE_VERSION") def vscode_workspace: Path = Path.variable("ISABELLE_VSCODE_WORKSPACE") + def vscodium_home: Path = Path.variable("ISABELLE_VSCODIUM_HOME") + def exe_path(dir: Path): Path = dir + Path.explode("bin/codium") def vscode_installation(version: String, platform: Platform.Family.Value): (Boolean, Path) = @@ -139,7 +141,11 @@ } if (check) { - if (install_ok) { + if (vscodium_home.is_dir) { + init_workspace(vscode_workspace) + progress.echo(vscodium_home.expand.implode) + } + else if (install_ok) { init_workspace(vscode_workspace) progress.echo(install_dir.expand.implode) }