ghcup-talk/GHCup.md
2024-06-01 22:07:00 +08:00

12 KiB
Raw Blame History

% GHCup % Julian Ospald % June 07, 2024

Introduction

What is GHCup?

State of 2019

::: incremental

  • stack is the only "Haskell Installer"
  • no unified alternative for cabal users
  • distro packages, nix, manual installs, ...
  • 🤮

:::

How it started

::: incremental

  • 🤹 small team at work (Capital Match), using different platforms
    • originally used stack
    • cabal distro packages constantly out of date
  • 🦾 first version was 165 LOC
    • Posix shell
  • {#id .class height=32px} only supported linux and mac
  • {#id .class height=32px} inspired by rustup

:::

GHCup today

Haskell Survey 2022:

. . .

  • over 17k LOC Haskell
  • supports all platforms: Linux, Windows, macOS, FreeBSD

GHCup and haskell.org

The default installer:

. . .

  • provides infrastructure (home page, downloads)

GHCup and the Haskell Foundation

::: incremental

:::

Philosophy

What is a good installer?

::: incremental

  • it installs (just that)
    • everywhere
  • intuitive interface
    • ghcup install ghc
  • good documentation
    • but you shouldn't have to read it
  • get out of the way
    • has no self-fulfilling purpose

:::

Goals and principles

::: incremental

  • ☮️ unification
  • unix principles
    • 🛠️ do one thing and do it well
    • ⚗️ pipes, compose stdout and stdin (re-usable)
  • 🎁 good re-distribution
  • 🛣️ user experience

:::

What is GHCup (simplified)?

curl -s -L 'https://downloads.haskell.org/~ghc/9.6.5/ghc-9.6.5-x86_64-fedora33-linux.tar.xz' |
  tar -xJ -C /tmp                              &&
  cd /tmp/ghc-9.6.5-x86_64-unknown-linux/      &&
  ./configure --prefix="$HOME/.local"          &&
  make install                                 &&
  rm -rf /tmp/ghc-9.6.5-x86_64-unknown-linux/

What is GHCup really?

::: incremental

  • {#id .class width=32 height=32px} installer
  • {#id .class width=32 height=32px} distribution channel
  • {#id .class width=32 height=32px} feedback channel
  • {#id .class width=32 height=32px} testing/QA gateway
  • {#id .class width=32 height=32px} provider of sane defaults (e.g. "recommended" GHC version)
  • {#id .class width=32 height=32px} glue for holistic toolchain experience
    • VSCode, stack, cabal-install integration
  • {#id .class width=32 height=32px} CI provisioning (e.g. github actions)

:::

Relationships

Upstream (dependencies)

  • supported tools
    • GHC
    • Cabal
    • HLS
    • Stack

. . .

  • decisions that affect us
    • release frequency
    • upstream CI
    • platform support
    • binary distributions (the .tar.gz/.zip)

Downstream (dependents)

  • {#id .class height=32px} Haskell developers
    • beginners, advanced, students, companies
  • {#id .class width=32 height=32px} end users (e.g. compiling pandoc from source)
  • {#id .class width=32 height=32px} GitHub CI
    • GitHub images, Haskell repos
  • 🪞 mirrors
  • 🧰 tools

The installer in detail

How does it work?

  • Architectural components
    • {#id .class height=32px} bootstrap scripts
    • {#id .class height=32px} ghcup binary (compiled)
    • {#id .class height=32px} ghcup-metadata

. . .

  • Logical components
    • {#id .class height=32px} cli interface
    • {#id .class height=32px} file layout / installation destination
    • {#id .class height=32px} bindist selection
    • {#id .class height=32px} tui interface
    • {#id .class height=32px} configuration

Basic CLI (context)

  • Architectural components
    • {#id .class height=32px} bootstrap scripts
    • {#id .class height=32px} ghcup binary (compiled)
    • {#id .class height=32px} ghcup-metadata
  • Logical components
    • {#id .class height=32px} cli interface
    • {#id .class height=32px} file layout / installation destination
    • {#id .class height=32px} bindist selection
    • {#id .class height=32px} tui interface
    • {#id .class height=32px} configuration

Basic CLI

::: incremental

  • show all available tools / versions
    ghcup list
    
  • install a tool
    ghcup install ghc latest
    
  • make a tool version the default
    ghcup set ghc latest
    
  • remove a tool version
    ghcup rm ghc 9.10.1
    

:::

File layout (context)

  • Architectural components
    • {#id .class height=32px} bootstrap scripts
    • {#id .class height=32px} ghcup binary (compiled)
    • {#id .class height=32px} ghcup-metadata
  • Logical components
    • {#id .class height=32px} cli interface
    • {#id .class height=32px} file layout / installation destination
    • {#id .class height=32px} bindist selection
    • {#id .class height=32px} tui interface
    • {#id .class height=32px} configuration

File layout

::: incremental

  • root dir

    $ ls ~/.ghcup
    📁bin 📁ghc 📁hls
    📁cache 📁db 📁logs 📁tmp 🗑trash 📄config.yaml 📄env
    
  • GHC and HLS are installed into sub-directories

    $ ls ~/.ghcup/ghc
    📁8.10.7 📁9.0.2 📁9.2.8
    
  • bin directory is mostly symbolic links (compare with update-alternatives)

    $ ls ~/.ghcup/bin
    📄ghcup
    🔗cabal 📄cabal-3.10.3.0
    🔗ghc 🔗ghc-8.10 🔗ghc-8.10.7 🔗ghc-9.0 🔗ghc-9.0.2 🔗ghc-9.2 🔗ghc-9.2.8
    

:::

Bindist selection (context)

  • Architectural components
    • {#id .class height=32px} bootstrap scripts
    • {#id .class height=32px} ghcup binary (compiled)
    • {#id .class height=32px} ghcup-metadata
  • Logical components
    • {#id .class height=32px} cli interface
    • {#id .class height=32px} file layout / installation destination
    • {#id .class height=32px} bindist selection
    • {#id .class height=32px} tui interface
    • {#id .class height=32px} configuration

Bindist selection (sysinfo)

Gather system information:

::: incremental

  • module GHCup.Platform
  • System.Info.arch and System.Info.os (compile-time strings)
  • distro detection mostly via /etc/os-release

:::

Bindist selection (mapping)

Map binaries to systems:

::: incremental

  • binary compatibility (platform, distro, distro version)
    • finite set of binaries
    • statically linked GHC?
  • static mapping in ghcup-metadata YAML files
  • alternative dynamic logic (utilizing ldconfig -p output)
    • for stack compatibility
  • updated on every release
  • "channels"

:::

Installation flow

{#id .class height=500px}

TUI interface (context)

  • Architectural components
    • {#id .class height=32px} bootstrap scripts
    • {#id .class height=32px} ghcup binary (compiled)
    • {#id .class height=32px} ghcup-metadata
  • Logical components
    • {#id .class height=32px} cli interface
    • {#id .class height=32px} file layout / installation destination
    • {#id .class height=32px} bindist selection
    • {#id .class height=32px} tui interface
    • {#id .class height=32px} configuration

TUI interface

{#id .class height=550px}

Configuration (context)

  • Architectural components
    • {#id .class height=32px} bootstrap scripts
    • {#id .class height=32px} ghcup binary (compiled)
    • {#id .class height=32px} ghcup-metadata
  • Logical components
    • {#id .class height=32px} cli interface
    • {#id .class height=32px} file layout / installation destination
    • {#id .class height=32px} bindist selection
    • {#id .class height=32px} tui interface
    • {#id .class height=32px} configuration

Configuration

::: incremental

  • Types of configuration:
    • environment variables
    • cli switches / TUI options
    • config file (~/.ghcup/config.yaml)
  • e.g.
    • env: GHCUP_INSTALL_BASE_PREFIX (default $HOME)
    • cli: ghcup install ghc -u <url> <version>
    • config: url-source (selecting and mixing "channels")
      • file/http/https URI
      • GHCupURL
      • StackSetupURL

:::

Phew

{#id .class height=550px}

Distribution

What is distribution?

  • QA gate between "upstream" and "downstream"
  • trust relationship (with upstream and downstream)
  • release selection and defaults
  • binary distribution

What happens on e.g. a GHC release

. . .

  • community adoption (both industry and "open source")
  • stack LTS
  • HLS support
  • known issues and regressions
  • GHC HQs opinion and support window
  • must be consistent across platforms

Contributing

How to contribute

::: incremental

:::

Getting started

Head over to https://github.com/haskell/ghcup-hs/issues/1074 (zurihac labeled issue).

Advanced topics

  • bootstrap scripts
  • windows and MSYS2
  • security
  • HLS/GHC interaction
  • reproducibility
  • stack integration
  • bindist work (curation)
  • isolated installs
  • mirrors