11 KiB
11 KiB
% 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
. . .
- 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
- affiliation: https://haskell.foundation/affiliates/
- pays for CI
- pays consultants to assist the project
:::
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)
:::
Upstream (dependencies)
::: incremental
- GHC
- Cabal
- HLS
- Stack
:::
Downstream (dependents)
::: incremental
- {#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
:::
Bits and pieces
How does it work?
::: incremental
- Architectural components
- Logical components
:::
Basic CLI (context)
- Architectural components
- Logical components
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
- Logical components
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
- Logical components
Bindist selection (sysinfo)
Gather system information:
::: incremental
- module
GHCup.Platform
System.Info.arch
andSystem.Info.os
(compile-time strings)- distro detection mostly via
/etc/os-release
- specified by freedesktop.org
- using os-release package for parsing
:::
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
- Tool -> Version -> Architecture -> Platform/Distro -> binary URL
- mapping based on binary compatibility
- alternative dynamic logic (utilizing
ldconfig -p
output)- for stack compatibility
- updated on every release
- "channels"
:::
Installation flow
TUI interface (context)
- Architectural components
- Logical components
TUI interface
Configuration (context)
- Architectural components
- Logical components
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
- env:
:::
Phew
Contributing
How to contribute
Some live action:
- project structure
- building the project (flags and project files)
- small code walkthrough
The future
::: incremental
- nightlies
- revisions
- curating old releases
- beefed up
ghcup compile
interface - TUF?
- supporting more tools (installer DSL)
:::
Advanced topics
- bootstrap scripts
- windows and MSYS2
- security
- HLS/GHC interaction
- reproducibility
- stack integration
- bindist work (curation)
- isolated installs
- mirrors
Cool things to contribute to
- documentation
- discussions
- deciding on defaults (metadata etc.)
- API for e.g. stack
- Dhall
- manpage (via optparse-applicative?)
- TUI (@lsmor)
- YAML schema for metadata
- integration test
- cross compiler support
- nightlies
- "health check" command