{
  "$type": "site.standard.document",
  "bskyPostRef": {
    "cid": "bafyreieowpvju5kvjo22xtuvec2bkuw2cx4fi2mlfljijwn4zwp2shwj6m",
    "uri": "at://did:plc:pi6woz4d47bkuws673w2il2r/app.bsky.feed.post/3mjhx42iynob2"
  },
  "path": "/t/ann-ghcup-0-2-0-0-rc-or-beta-maybe/13930#post_1",
  "publishedAt": "2026-04-14T16:06:31.000Z",
  "site": "https://discourse.haskell.org",
  "tags": [
    "Intaller DSL · Issue #141 · haskell/ghcup-hs · GitHub"
  ],
  "textContent": "This is maybe more of a **BETA** than a _RELEASE CANDIDATE_ , but anyway.\n\nWith support from IOG, I have implemented some form of Intaller DSL · Issue #141 · haskell/ghcup-hs · GitHub\n\nIt’s not really a DSL though, but rather an “install specification”. That means **GHCup can now install arbitrary tools**. This moved us a bit on the “installer vs package manager” design spectrum. But it’s still an installer (for several reasons).\n\n## How to test\n\nYou may want to back up your `~/.ghcup` directory, especially if you have compiled GHCs from source. But I encourage people to test this RC on their existing installation, since that may expose more bugs.\n\nRun this (even with a pre-existing installation):\n\n\n    curl --proto '=https' --tlsv1.2 -sSf https://raw.githubusercontent.com/haskell/ghcup-hs/refs/heads/installer-dsl2/scripts/bootstrap/bootstrap-haskell | BOOTSTRAP_HASKELL_NONINTERACTIVE=yes BOOTSTRAP_HASKELL_MINIMAL=yes sh\n\n\nThen make sure you’re not using the vanilla channel. If in doubt, edit `~/.ghcup/config.yaml` and ensure that you have this configuration:\n\n\n    url-source:\n    - GHCupURL\n\n\nAnd now fire away:\n\n\n    ghcup install shellcheck --set latest\n    ghcup install ormolu     --set latest\n    ghcup install pandoc     --set latest\n    ghcup install hlint      --set latest\n\n\n## What’s the point?\n\nOne major point is to be able to install alternative compilers and GHC forks. It just so happens that this is the easiest approach.\n\n## How do I package tool XY?\n\nThe spec for hlint is as follows:\n\n\n      hlint:\n        3.10:\n          viTags:\n            - Latest\n            - Recommended\n          viArch:\n            A_64:\n              Linux_UnknownLinux:\n                unknown_versioning:\n                  dlUri: https://github.com/ndmitchell/hlint/releases/download/v3.10/hlint-3.10-x86_64-linux.tar.gz\n                  dlHash: ccabc8802a58154699a3583b8dddc5ea2e6d65753a62c45c0e80088ebb16b42b\n                  dlSubdir: hlint-3.10\n                  dlInstallSpec\n                    exeRules:\n                      - installSource: \"hlint\"\n                        installDest: \"bin/hlint\"\n                    dataRules:\n                      - installPattern: [\"data/**\"]\n                    exeSymLinked:\n                     - linkName: \"hlint-${PKGVER}\" # the versioned binary\n                       setName: \"hlint\"            # for 'ghcup set' only\n                       target: \"bin/hlint\"         # linkName and setName both point to ~/.ghcup/hlint/3.10/bin/hlint\n                       pVPMajorLinks: false        # whether to create tool-X.Y symlinks (useful for GHC)\n\n\nThis installs some executables and some data files and `exeSymLinked` tells ghcup how to expose binaries in `~/.ghcup/bin`.\n\nWe can also execute configure and make, e.g. for something like GHC the `dlInstallSpec` would look like:\n\n\n    dlInstallSpec:\n      exeRules: []\n      dataRules: []\n      configure:\n        configFile: configure\n        configArgs:\n        - \"--prefix=${PREFIX}\"\n      make:\n        makeArgs:\n        - DESTDIR=${TMPDIR}\n        - install\n      preserveMtimes: true\n      exeSymLinked:\n      - target: bin/ghc\n        linkName: ghc-${PKGVER}\n        pVPMajorLinks: true\n        setName: ghc\n      - target: bin/ghci\n        linkName: ghci-${PKGVER}\n        pVPMajorLinks: true\n        setName: ghci\n    # and so forth...\n\n\nThere’s some things that packagers should know:\n\n  * configure script must support `--prefix`\n  * make must support `DESTDIR`\n  * a makefile-only build system is possible too, then the Makefile also needs to support some way to pass the prefix\n  * the first element in `exeSymLinked` is used for `ghcup whereis`\n  * configure and make are not supposed to:\n    * download from the internet\n    * write anywhere outside of their current working dir and `$TMPDIR`\n    * compile stuff from source\n\n\n\n## Bubblewrap support\n\nSince users may in the future rely on third-party channels that support new tools, they need a way to protect themselves from buggy configure/Makefiles. This can be achieved like so in `~/.ghcup/config.yaml`\n\n\n    build-wrapper:\n      cmd: bwrap\n      cmdArgs: [ \"--ro-bind\" , \"/\" , \"/\"\n               , \"--bind\" , \"/home/hasufell/.ghcup\" , \"/home/hasufell/.ghcup\"\n               , \"--bind\" , \"/home/hasufell/.cabal\" , \"/home/hasufell/.cabal\"\n               , \"--dev\" , \"/dev\"\n               , \"--proc\" , \"/proc\"\n               , \"--tmpfs\" , \"/tmp\"\n               ]\n\n\nThe `.cabal` bind mount is necessary for `ghcup compile hls`. Please adjust the paths to your own configuration. If you don’t compile hls from source, you can also specify `--unshare-all`.",
  "title": "[ANN] GHCup 0.2.0.0 RC (or beta, maybe)"
}