Esta página aún no está traducida al español. Leer la versión en inglés

The installers

How Larva is published and installed - publish-larva and build-installer, the LarvaSetup wizard and its registry keys, install.sh for Linux and macOS, the installed layout and the CI workflow.

Última actualización: 15 min de lectura Editar en GitHub

En esta página

Install Larva tells you how to install. This page describes what the installers are made of, what they write on the machine, and how they are built.

There are three deliverables, each built on its own operating system because ahead-of-time compilation only targets the system it runs on:

File System Built by
LarvaSetup-<version>-win-x64.exe Windows x64 tools/build-installer.ps1
Larva-<version>-win-x64.zip Windows x64 (portable) tools/build-installer.ps1
Larva-<version>-linux-x64.tar.gz Linux x64 tools/build-installer.sh
Larva-<version>-osx-arm64.tar.gz macOS arm64 tools/build-installer.sh

The Linux and macOS archives and their install.sh are new. The design record says they were tried only with Git Bash on Windows and a simulated larva (install, uninstall, the macOS property list), not yet on a real Linux or macOS machine. Treat them as untested.

What gets installed

Every installer puts the same set of files in one folder:

Larva/
├── larva.exe                 the toolchain, compiled ahead of time (larva on Linux and macOS)
├── LLVM-C.dll                LLVM's C API and the binding library larva calls it through
├── libLLVMSharp.dll          (.so/.dylib files on Linux and macOS)
├── System.Core.dll           the standard library, compiled (a PE file whose content is an .lva section)
├── System.Bindings.dll       what binding profiles are written against
├── Languages/
│   └── Antril/
│       ├── Antril.dll        the language pack, native, its files hashed and the manifest signed
│       ├── ant-file.ico      the icon of the pack's source files
│       └── language.json
├── Templates/
│   ├── Console App/          template.json + template.lva (Larva HIR: each language writes its own source)
│   └── Library/
├── icons/                    file-lva, file-lvo, file-lvm, file-bind, file-queen, file-hive (.ico; .svg and .icns elsewhere)
├── README.txt
├── uninstall.exe             (Windows) the setup program itself
├── install.sh                (Linux, macOS) the installer, which is also the uninstaller
└── uninstall.files           the list of what the installation put here

No source code is installed. Earlier versions shipped System.Core as .ant files and compiled it on first use; now the build compiles it once with the larva being shipped (larva lib), so the installed larva never needs a language pack to build its own standard library, and Larva's installation does not depend on any one language. A working copy of the repository still compiles Library/System.Core and Library/System.Bindings from source and caches the result.

The installed layout on a Windows machine, with its list:

Terminal
cat uninstall.files
icons\file-bind.ico
icons\file-hive.ico
icons\file-lva.ico
icons\file-lvm.ico
icons\file-lvo.ico
icons\file-queen.ico
Languages\Antril\ant-file.ico
Languages\Antril\Antril.dll
Languages\Antril\language.json
Templates\Console App\template.json
Templates\Console App\template.lva
Templates\Library\template.json
Templates\Library\template.lva
larva.exe
libLLVMSharp.dll
LLVM-C.dll
README.txt
System.Bindings.dll
System.Core.dll
uninstall.exe

larva finds what it needs relative to its own executable: System.Core.dll and System.Bindings.dll next to it, language packs in Languages/ next to it (plus %LOCALAPPDATA%\Larva\Languages and LARVA_LANGUAGES), templates in Templates/. That is why a portable zip works from any folder, and why the Linux launcher is a script that execs the real binary instead of a symbolic link.

Larva and the languages built on it are separate products. The installer, its texts and the README describe Larva as a set of build tools (larva build, larva lsp, larva bind) and do not name any language or editor; the languages arrive as packs in Languages/.

Publishing larva

tools/publish-larva.ps1 (Windows) and tools/publish-larva.sh (Linux x64, macOS arm64) produce artifacts/larva/:

  1. Publish Larva.Cli ahead of time for the runtime identifier (win-x64, linux-x64, osx-arm64). A native larva starts compiling at once: for a small program, the frontend, HIR linking, lowering and IR checks take tens of milliseconds instead of a second of warm-up.
  2. Find the signing key: LARVA_SIGNING_KEY (a PEM file), else artifacts/keys/languages.pem, created on first use with larva languages key.
  3. Copy each language pack found in the pack folders (-Languages <folders> on Windows, LARVA_PACKS separated by : on Linux and macOS; by default ../Antril/artifacts/languages) to artifacts/larva/Languages/<Name>/, and sign it with larva languages pack <folder> --key <key>, which completes the manifest's file hashes and signature.

Each language is built in its own repository. The Antril repository's tools/publish-pack.ps1 or .sh writes its native pack to artifacts/languages/Antril; on Linux and macOS the pack's library is X.so or X.dylib and the manifest's entry is rewritten to match. larva only signs and ships packs. The script fails if it found none.

-Offline (Windows) builds only from the local package cache and pins the runtime version found there.

Building the Windows installer

tools/build-installer.ps1 [-Offline] [-Languages <folders>]:

  1. Publish larva with publish-larva.ps1.
  2. Stage the files in artifacts/installer/stage:
    • larva.exe, LLVM-C.dll, libLLVMSharp.dll and Languages/ from artifacts/larva;
    • the .ico file icons from brand/ into icons/;
    • System.Core.dll, built by the staged larva: larva lib -o System.Core.dll --borrowcheck enforce Library/System.Core/*.ant (System.Core uses &mut borrows, so it is checked whatever the build machine's default is);
    • System.Bindings.dll: larva lib -o System.Bindings.dll Library/System.Bindings/*.ant;
    • each folder of Templates/ packed with larva new --pack <template> -o Templates;
    • README.txt.
  3. Zip the stage into Larva-<version>-win-x64.zip.
  4. Publish Larva.Setup ahead of time with -p:Payload=<zip>: the project embeds the zip as the resource payload.zip. The result is copied to LarvaSetup-<version>-win-x64.exe (about 40 MB).
  5. Test the file types with LarvaSetup.exe --types-test <stage> (below) and fail the build if Larva.Library, Larva.Object, Larva.Project or Larva.Package is not registered, or if any Larva. class is left after removal.

The version comes from Larva.Cli's project file and is passed to the setup, so larva --version and the installer always agree.

LarvaSetup

Larva.Setup is a small program compiled ahead of time, with no UI framework:

File Role
Program Options, silent mode, uninstall, the hidden test modes.
Installer Everything that installs and removes: payload, PATH, registry, file types, Hive registry, uninstall list. Shared by the wizard and the command line.
Wizard The wizard: one Win32 window, its controls shown or hidden per page, header and welcome panel painted with GDI.
Native The Windows calls: user32, gdi32, comctl32, shell32, advapi32.
Texts The wizard's strings (English).
app.manifest asInvoker, DPI awareness, common controls v6.

Options

From --help (the text in Program):

  LarvaSetup.exe [--dir <folder>] [--no-path] [--no-registry] [--no-hive] [--no-types]              the wizard
  LarvaSetup.exe --silent [--dir <folder>] [--no-path] [--no-registry] [--no-hive] [--no-types]     no questions
  LarvaSetup.exe --uninstall [--silent] [--dir <folder>] [--no-path] [--no-registry]

--silent also answers to -s, /s and /silent; --uninstall to /uninstall; --help to -h and /?. An unknown option prints an error and exits with 2. Because the program is a Windows GUI application, --silent and --help attach to the console of the process that started them (AttachConsole(-1)) to print.

Two options are not listed: --types-test <folder> and --wizard-test <folder> (below).

Why per user, and why asInvoker

Larva installs for the current user, in %LOCALAPPDATA%\Programs\Larva, with no administrator rights. Everything it writes is under HKEY_CURRENT_USER and the user's profile. Windows raises any program whose name contains "Setup" to administrator by default (installer detection); the manifest's requestedExecutionLevel level="asInvoker" turns that off, so the setup runs with the user's own rights and writes to the user's own registry and folders, not an administrator's.

Installing

Installer.Install(folder, path, registry, hive, types, progress):

  1. Remove the previous installation's files (RemoveInstalled): the files named in uninstall.files, or, in a folder with no list but a larva.exe, what 0.7.0 shipped (larva.exe, the LLVM libraries, System.Core.dll, README.txt, uninstall.exe and the old Library/System.Core/*.ant). Only those files are deleted, and then their folders if they end up empty. Anything else in the folder is left alone.
  2. Extract each entry of payload.zip, refusing any path that would land outside the folder. Progress is reported per file, weighted by size, from 0 to 85 %.
  3. Copy itself to uninstall.exe.
  4. Write uninstall.files: the relative path of every file it put there.
  5. PATH (unless --no-path): append the folder to HKCU\Environment\Path, keeping the value as REG_EXPAND_SZ and its other entries untouched; skip it if an entry already expands to the same folder. Then broadcast WM_SETTINGCHANGE with "Environment" (SendMessageTimeout to all top-level windows, 5 s), so Explorer and new terminals see it.
  6. Installed apps (unless --no-registry): write the uninstall key (below).
  7. Hive registry (unless --no-hive): AddHiveProvider (below).
  8. File types (unless --no-types): RegisterFileTypes (below).
  9. Check: run larva.exe --version from the folder. An installation whose larva does not answer is reported as failed.

In the wizard, the install runs on a background thread and posts progress messages to the window. Before it starts, the wizard counts larva processes running from the destination (RunningFrom): an editor's language server holds larva.exe open, and overwriting it would fail halfway. It asks to close them and retry.

Registry keys

Key Values Written when
HKCU\Environment Path (REG_EXPAND_SZ) with the folder appended PATH option
HKCU\Software\Microsoft\Windows\CurrentVersion\Uninstall\Larva DisplayName = Larva <version>, DisplayVersion, Publisher = Larva, InstallLocation, DisplayIcon = uninstall.exe, UninstallString = "…\uninstall.exe" --uninstall, QuietUninstallString = "…\uninstall.exe" --uninstall --silent, EstimatedSize (KB, DWORD), NoModify = 1, NoRepair = 1 Installed-apps option
HKCU\Software\Classes\Larva.* default value: the type's name; DefaultIcon = "<icon>",0 File-types option
HKCU\Software\Classes\.<ext> OpenWithProgids\<class>; default value = the class only if it was empty File-types option

The uninstall key is also how the setup recognizes an earlier installation. InstalledFolder reads InstallLocation to propose the same folder, and InstalledVersion reads DisplayVersion so the Ready page can say whether this is an upgrade, a reinstall, or a replacement of a different installation in the chosen folder.

File types

FileTypes(folder) lists Larva's own file kinds and those of every installed language pack:

Extension Class Description Icon
.lva Larva.Library Larva library icons\file-lva.ico
.lvo Larva.Object Larva object file icons\file-lvo.ico
.lvm Larva.Module Larva module icons\file-lvm.ico
.bind Larva.Binding Larva binding description icons\file-bind.ico
.queen Larva.Project Larva project icons\file-queen.ico
.hive Larva.Package Hive package icons\file-hive.ico
each pack extension (.ant) Larva.<Name>.<ext> (Larva.Antril.ant) <Name> source file the pack's icon from language.json

RegisterFileTypes creates each class with its icon, lists it under the extension's OpenWithProgids, and makes it the extension's default only when no other program has claimed the extension. Then it calls SHChangeNotify(SHCNE_ASSOCCHANGED) so Explorer redraws icons. Larva never takes an extension away from another program.

UnregisterFileTypes removes the Larva.* classes whose DefaultIcon points inside the installation folder (so two installations in different folders do not remove each other's), every reference to them in OpenWithProgids and default values, and an extension key left empty.

--types-test <folder> checks both functions without touching the user's registry: it loads a private hive file (<folder>\types.dat) with RegLoadAppKey, redirects HKEY_CURRENT_USER to it for this process with RegOverridePredefKey, sets .bind to belong to Other.Program, registers, prints the classes, unregisters and prints them again. build-installer.ps1 runs it on every build.

The Hive registry

AddHiveProvider edits larva's settings file: LARVA_CONFIG when set, else %APPDATA%\Larva\defaults.json. It puts https://www.antril.org/hive-api first in hive.provider (a comma-separated list), keeps the other registries and the rest of the file, and does nothing if that registry is already there. This is the same setting larva config hive.provider writes. Uninstalling does not remove it.

The wizard

With no --silent, Wizard.Run shows five pages in one window:

Page Shows
Welcome The logo on a green panel (accent #1E6B33) and what Larva is.
Destination folder and options The folder (with Browse...), four check boxes (PATH, Installed apps, the Hive registry, file types), space required and space available, updated as the folder changes.
Ready to install A summary: folder, options, upgrade/reinstall/replace, and the optional system components: MSVC build tools (found with vswhere, including preview versions), clang, Node.js.
Installing A progress bar and the current file ("Extracting: …") or step.
Installation complete Where Larva is, whether it is on the PATH, and Open the installation folder.

The window is DPI-aware (sizes scaled by GetDpiForSystem), uses common controls v6, and draws the worm logo by hand when the icon cannot be loaded. The texts are English only; an earlier Spanish set and the lookup of Windows' UI language were removed.

--wizard-test <folder> --dir <target> walks the pages by itself, saves each as a PNG in <folder>, and installs into <target> with the PATH, Installed apps, Hive and file-type steps all turned off.

Silent mode

--silent installs into --dir or the default folder, prints Larva <version> into <folder>, then Installed: <larva --version> and whether the folder is on the PATH, and one line per optional component (Installer.Prerequisites):

Component How it is found Line when missing
MSVC build tools vswhere -latest -prerelease -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 `larva build` of native executables needs them
clang C:\Program Files\LLVM\bin\clang.exe or clang.exe on PATH `larva bind` reads C headers without preprocessing them
Node node.exe on PATH only needed to run WebAssembly builds outside a browser

Found components print ok, missing ones --. On failure it exits with 1 and suggests closing whatever uses Larva.

Uninstalling

uninstall.exe --uninstall (what Installed apps runs) asks for confirmation unless --silent, then Installer.Uninstall:

  1. Refuses if the folder has no larva.exe.
  2. Removes the folder from the user's PATH and broadcasts the change.
  3. Deletes the uninstall key.
  4. Unregisters the file types.
  5. Deletes the files in uninstall.files (except the running uninstall.exe) and the folders they leave empty.
  6. A program cannot delete its own file while it runs, so when uninstall.exe runs from the folder it starts a hidden cmd.exe that waits about two seconds (ping -n 3 127.0.0.1), deletes uninstall.exe, and removes the folder with rmdir without /s: the folder goes only if nothing else is left in it.

Files the user put in the installation folder are never deleted.

Linux and macOS: install.sh

The archive Larva-<version>-<rid>.tar.gz unpacks to a folder with the installed layout plus install.sh. The same script installs and, once copied into the installation folder, uninstalls.

./install.sh [--prefix <folder>] [--no-path] [--no-hive] [--no-types]
./install.sh --uninstall [--prefix <folder>]
Linux macOS
Default folder ${XDG_DATA_HOME:-~/.local/share}/larva ~/Library/Application Support/Larva
Command ~/.local/bin/larva (a launcher script) same
PATH line ~/.profile ~/.zprofile
File types shared-mime-info XML + hicolor SVG icons a Larva Files.app bundle registered with Launch Services

Installing

  1. Refuse to run unless larva is next to the script.

  2. Write the list of every file in the archive (find . -type f) to uninstall.files, and copy each file into the prefix (skipped when installing in place).

  3. On macOS, remove the quarantine attribute from the prefix only (xattr -dr com.apple.quarantine), so the downloaded binaries can run.

  4. Write ~/.local/bin/larva:

    #!/bin/sh
    # added by Larva install.sh launcher (install.sh --uninstall removes it)
    exec "<prefix>/larva" "$@"
    

    A launcher rather than a link, because larva looks for its libraries, System.Core.dll and Languages/ next to its own executable. An existing ~/.local/bin/larva without the marker comment is someone else's and is left alone.

  5. Unless --no-path, and only when ~/.local/bin is not already on PATH: append export PATH="$HOME/.local/bin:$PATH" # added by Larva install.sh to the profile file, once.

  6. Unless --no-hive: read larva config hive.provider and put https://www.antril.org/hive-api first if it is not there.

  7. Unless --no-types: register file types.

  8. Report whether cc (to link native executables) and clang (to preprocess headers in larva bind) are installed, and print the installed version.

File types on Linux

linux_types writes $XDG_DATA_HOME/mime/packages/larva.xml, one mime-type per kind (application/x-larva-library, -object, -module, -binding, -project, -package, and application/x-larva-source-<id> per pack extension) with a glob pattern and an icon name, copies each SVG icon to icons/hicolor/scalable/mimetypes/application-x-larva-<type>.svg, and runs update-mime-database and gtk-update-icon-cache when they exist.

File types on macOS

macOS assigns icons to file types declared by an application. mac_types builds ~/Applications/Larva Files.app: an Info.plist with UTExportedTypeDeclarations (one org.larva.<type> per kind, conforming to public.plain-text for sources, bindings and projects and to public.data for the rest, with its .icns icon and extension) and CFBundleDocumentTypes with role and handler rank None, an executable that only exits, and LSUIElement so it never shows in the Dock. It is registered with lsregister -f. The bundle opens nothing; it only names and draws Larva's files.

Uninstalling

install.sh --uninstall [--prefix <folder>] removes the file types (or unregisters and deletes the app bundle), the marked PATH line, the launcher if it carries the marker, each file in uninstall.files, and the empty folders left behind. The Hive registry setting stays.

Building the archives

tools/build-installer.sh:

  1. publish-larva.sh for the current system (linux-x64 or osx-arm64; other systems are refused).
  2. Stage larva, the LLVM shared libraries, Languages/, System.Core.dll and System.Bindings.dll built with larva lib (System.Core with --borrowcheck enforce), the templates (larva new --pack), the SVG and .icns icons, install.sh and a README.
  3. tar -czf Larva-<version>-<rid>.tar.gz.
  4. Try the installer in a throwaway home: HOME, XDG_DATA_HOME and LARVA_CONFIG pointed into a temporary folder, install.sh --prefix … --no-path, run the launcher with --version, then install.sh --uninstall from the installed copy, and fail if larva or the launcher is left behind.

Larva.Llvm picks the LLVM runtime packages of the operating system it is built on, so each archive carries the right libLLVM library.

The CI workflow

.github/workflows/installers.yml in the Larva repository builds all three on their own runners, on a manual run or on a tag v*:

Matrix entry Runner Language pack Installer
Windows windows-latest pwsh -File Antril/tools/publish-pack.ps1 pwsh -File Larva/tools/build-installer.ps1
Linux ubuntu-latest sh Antril/tools/publish-pack.sh sh Larva/tools/build-installer.sh
macOS macos-latest sh Antril/tools/publish-pack.sh sh Larva/tools/build-installer.sh

Each job checks out Larva and the Antril repository side by side (the scripts expect ../Antril from Larva), installs the platform toolchain (on Linux, clang and zlib1g-dev for ahead-of-time compilation), writes the LARVA_SIGNING_KEY secret to a file when it is set so the packs are signed with the release key, builds Antril's pack, builds the installer (which tests itself), and uploads *.exe, *.zip and *.tar.gz from artifacts/installer. fail-fast is off, so one platform's failure does not cancel the others.

Not done yet

  • Linux and macOS installers have not run on a real Linux or macOS machine.
  • No installer for Linux arm64 or macOS x64: publish-larva.sh refuses other systems.
  • The build scripts do not code-sign the installers (Windows SmartScreen, macOS Gatekeeper); on macOS, install.sh removes the quarantine attribute from its own folder instead.

¿Te resultó útil esta página?

No se guarda ninguna dirección; tu nombre de usuario sí, si iniciaste sesión.

Esc