How to use GHC 7.10

I managed to get a working GHC 7.10 setup, and I wanted to put all the necessary information in one place, just for future reference.

GHCup has GHC 7.10, but it notes some warnings about linking errors that happen on modern distros.

So my approach is instead to use the fpco Docker images, so that also system libraries and the C toolchain are compatible. It’s problematic, though, because the newest Docker versions use a new manifest version, and as such they can’t pull old images and more.

What I did on x86_64 on Debian Bullseye is:

  1. Install official Docker apt repositories

  2. Install a older version of Docker from mid-2024, with support for the old manifest. I picked the last v26 version:

    VER="5:26.1.4-1~debian.11~bullseye" sudo apt install \
        docker-ce-cli=${VER} \
        docker-ce=${VER}
    
  3. Configure Docker to be able to pull old images:

    sudo mkdir -p /etc/systemd/system/docker.service.d
    

    Write to file /etc/systemd/system/docker.service.d/v1-manifest.conf:

    [Service]
    Environment="DOCKER_ENABLE_DEPRECATED_PULL_SCHEMA_1_IMAGE=1"
    
  4. Reboot

  5. Now you should be able to run

    docker run -it fpco/stack-build:lts-6.30 /bin/bash
    
  6. In the container, you must configure the new Stackage snapshot location. Stack v1.3.2 still has documentation available online. Execute mkdir /etc/stack and write to /etc/stack/config.yaml:

    latest-snapshot-url: https://stackage-haddock.haskell.org/snapshots.json
    system-ghc: true
    
  7. You can run stack repl --package lens and it will make the global project configuration file /root/.stack/global-project/stack.yaml with the current resolver (right now it is lts-23.10), and then fail the build.

  8. Patch the global project stack.yaml to point at lts-6.30. I suppose newer ones like lts-6.35 should also work.

  9. Now commands like stack repl --package lens work. Using the right resolver and using the system GHC.

Note that the steps that modify the fpco image could of course be used to create new Docker image, and if that image is uploaded, it uses manifest v2, and should therefore work with current Docker versions. And hopefully a few years into the future.

To make this really future proof, I’d like to back up the source packages too at some point.

3 Likes

The GHCup message does say:

You may have to pass ‘–ghc-option=-optc-no-pie --ghc-option=-optl-no-pie’ to cabal build/install.

That worked for me last time I encountered this. I think you can even add these as defaults in your cabal config somewhere. Why take the drastic step of using Docker?

The more modern tools I use, the more likely I am to encounter an issue. Using Docker is almost as convenient as being on the host machine. GHCup might be able to install a working compiler, but I would also be relying on modern versions of Cabal working with these ancient library versions. My goal is not to get the latest libraries working with an old compiler, my goal is to conveniently access the ecosystem as it was back then.

For even older GHC releases like 6.2.2, I am considering extracting shared objects from a RedHat Linux 9 installation and manually constructing a i386 Docker image. How’s that for drastic? :wink: How would you prefer to set up GHC 6.2.2 environment?

Forgive me my curiosity but what do you need ghc 7.10 for?

To drill down a little on @Swordlash’s q, if you want only the compiler + Prelude, you can download and unpack from the GHC download page [**].

If you’re wanting to add other packages, or even compile the compiler, I’m curioser and curioser.

[**] Although I notice the url seems to be broken, should be https://www.haskell.org/ghc/download_ghc_7_10_3.html

If bootstrapping, I wonder if it could be useful to have a complete working environment for reference.

Let’s say a separate compiler for the GHC 8.0 sources were to be written. Maybe it would be useful to have a reference to compare with. To answer questions like “this module takes awfully long to compile, I wonder if GHC 7.10 also took ages”.

Suppose there is a bug in the type checker of GHC 7.10, which makes it able to compile a GHC 8.0 module even though it shouldn’t. The fact that for the last ~30 years, only GHC can compile itself, means that it is less likely that people would discover if GHC were too reliant on a quirk that it wasn’t supposed to be reliant on.

Does that make sense? Maybe I can retroactively come up with some other justification.