haskell-language-server to void-packages
Tags: voidlinux, haskell, compiler, debugging
Published: 2021-01-17 05:30:21

I neded the `haskell-language-server` installed on my machine so I can edit `*.hs` files in VSCode so I get features like intellisense and syntax highlighting.

I'll go through the steps I took in order to troubleshoot and get a working version of `haskell-language-server` for `x86_64`, then additional fixes used in attempt to make it cross compile to `armv7l` and others.

I wrote a basic template for `void-packages`:

```bash
# Template file for 'haskell-language-server'
pkgname=haskell-language-server
version=0.8.0
revision=1
archs="x86_64"
build_style="haskell-stack"
short_desc="Haskell Language Server: Integration of ghcide and haskell-ide-engine"
maintainer="Wayne Van Son <waynevanson@gmail.com>"
license="Apache-2.0"
homepage="https://github.com/haskell/haskell-language-server"
distfiles="https://github.com/haskell/haskell-language-server/archive/${version}.tar.gz"
checksum="5ff053f0f4bb26b867fdc0b4071ba25c47eaa6febc9a4ef5b70a5a31c9433671"
```

The most important part besides the source files is `build_style="haskell-stack"`. This  provides us with `do_build()` and `do_install()` hooks that force the correct versions of `stack` and `ghc` (Glorious Haskell Compiler).
We use this because the codebase we're compiling is a haskell codebase.

## Dependencies

The [documentation](https://github.com/haskell/haskell-language-server#linux-specific-pre-requirements) states that that:

> On Linux you will need install a couple of extra libraries:
>
> - Unicode (ICU)
> - NCURSES
> - Zlib

Let's add these dependencies as `make-depends`

```bash
# Template file for 'haskell-language-server'
pkgname=haskell-language-server
version=0.8.0
revision=1
archs="x86_64"
build_style="haskell-stack"
makedepends="ncurses-libtinfo-devel icu-devel zlib-devel"
short_desc="Haskell Language Server: Integration of ghcide and haskell-ide-engine"
maintainer="Wayne Van Son <waynevanson@gmail.com>"
license="Apache-2.0"
homepage="https://github.com/haskell/haskell-language-server"
distfiles="https://github.com/haskell/haskell-language-server/archive/${version}.tar.gz"
checksum="5ff053f0f4bb26b867fdc0b4071ba25c47eaa6febc9a4ef5b70a5a31c9433671"
```

We've got everything we need as a base, so let's kick of a build with
```sh
# initialize `masterdir`, contains `/{etc,lib,usr}`
./xbps-src binary-bootstrap
# trigger a build of the package
./xbps-src pkg haskell-language-server
```

Let's figure out our first errors.

## Errors

### Error: Out of Memory

This is a problem with your machine, not the package or the compiler.

Run `./xbps-src pkg haskell-language-server` to continue where it left off. If any files where compiled, they'll be reused and not recompiled.

If you run `./xbps-src pkg -f haskell-language-server` they will be recompiled. I use this when I've made changes to the template that affect the build/install stages.

That's an easy fix, phew!

### Error: Haskell related.

We're getting a lot of errors from the codebase, which is unusual in a working package. This is because we're not using the latest version of `ghc`, but one with long-term support (lts).

Running `ghc --version` points to version `8.8.4`, which indeed is the [GHC-lts](https://www.stackage.org/lts) at this point in time.

I noticed that the source files come with a bunch of `stack-(n-n-n).yaml` files. The version number indicates which version of GHC we need to use.

We need to use that one instead of `stack.yaml`, which was done by default.

To use `stack-8.8.4.yaml`, we need to pass a flag to the `stack build` and `stack install` commands. We can do this by assigning the stack flags to the variable `make_build_args`:


```bash
# Template file for 'haskell-language-server'
pkgname=haskell-language-server
version=0.8.0
revision=1
archs="x86_64"
build_style="haskell-stack"
make_build_args="--stack-yaml stack-8.8.4.yaml"
makedepends="ncurses-libtinfo-devel icu-devel zlib-devel"
short_desc="Haskell Language Server: Integration of ghcide and haskell-ide-engine"
maintainer="Wayne Van Son <waynevanson@gmail.com>"
license="Apache-2.0"
homepage="https://github.com/haskell/haskell-language-server"
distfiles="https://github.com/haskell/haskell-language-server/archive/${version}.tar.gz"
checksum="5ff053f0f4bb26b867fdc0b4071ba25c47eaa6febc9a4ef5b70a5a31c9433671"
```

Let's build again using `./xbps-src pkg -f haskell-language-server` and see what we get next.

### Error: nopie

We're getting some crazy errors about the executables not being `pie` files. Here is the [Wikipedia Article](https://en.wikipedia.org/wiki/Position-independent_code) for reference.

The fix is that for every executable, we must specify the path to executable files produced by the `do_install()`.

```bash
# Template file for 'haskell-language-server'
pkgname=haskell-language-server
version=0.8.0
revision=1
archs="x86_64"
build_style="haskell-stack"
make_build_args="--stack-yaml stack-8.8.4.yaml"
makedepends="ncurses-libtinfo-devel icu-devel zlib-devel"
short_desc="Haskell Language Server: Integration of ghcide and haskell-ide-engine"
maintainer="Wayne Van Son <waynevanson@gmail.com>"
license="Apache-2.0"
homepage="https://github.com/haskell/haskell-language-server"
distfiles="https://github.com/haskell/haskell-language-server/archive/${version}.tar.gz"
checksum="5ff053f0f4bb26b867fdc0b4071ba25c47eaa6febc9a4ef5b70a5a31c9433671"
nopie_files="
/usr/bin/haskell-language-server
/usr/bin/haskell-language-server-wrapper
/usr/bin/ghcide-bench
/usr/bin/ghcide
/usr/bin/ghcide-test-preprocessor
"
```

## Architecture Compatibility

DONE! It compiled, what a time to be alive.
[void-packages/CONTRIBUTING.md](https://github.com/void-linux/void-packages/blob/master/CONTRIBUTING.md#committing-your-changes) explain that we should also try build for `armv7l`, but I always try build the following:

```sh
# defaults to `x86_64`, but never mention the
# arch if you're already using it;
# use for cross-compilation only
./xbps-src pkg -f haskell-language-server
./xbps-src -a x86-64-musl pkg -f haskell-language-server
./xbps-src -a armv7l pkg -f haskell-language-server
./xbps-src -a aarch64 pkg -f haskell-language-server
./xbps-src -a i868 pkg -f haskell-language-server
```

# `armv7l`

We purposefully restricted the architecture to `x86_64`, let's add `aarch64` to the `archs` variable.

```bash
# Template file for 'haskell-language-server'
pkgname=haskell-language-server
version=0.8.0
revision=1
archs="x86_64 aarch64"
build_style="haskell-stack"
makedepends="ncurses-libtinfo-devel icu-devel zlib-devel"
short_desc="Haskell Language Server: Integration of ghcide and haskell-ide-engine"
maintainer="Wayne Van Son <waynevanson@gmail.com>"
license="Apache-2.0"
homepage="https://github.com/haskell/haskell-language-server"
distfiles="https://github.com/haskell/haskell-language-server/archive/${version}.tar.gz"
checksum="5ff053f0f4bb26b867fdc0b4071ba25c47eaa6febc9a4ef5b70a5a31c9433671"
```


New build, let's run `./xbps-src -a aarch64 pkg -f haskell-language-server`.


### Error: `ncursesw`

It looks like we cannot find the ncursesw resource on this particular architecture. My experience indicates it's usually fixed with `ln -sf /lib/libtinfo.so.5 /libtinfo.so.6`, but the fix is for `ncursesw`, not `tinfo` so we will put the fix inside of the `pre_build()` hook.

```bash
# Template file for 'haskell-language-server'
pkgname=haskell-language-server
version=0.8.0
revision=1
archs="x86_64 armv7l"
build_style="haskell-stack"
make_build_args="--stack-yaml stack-8.8.4.yaml"
makedepends="ncurses-libtinfo-devel icu-devel zlib-devel"
short_desc="Haskell Language Server: Integration of ghcide and haskell-ide-engine"
maintainer="Wayne Van Son <waynevanson@gmail.com>"
license="Apache-2.0"
homepage="https://github.com/haskell/haskell-language-server"
distfiles="https://github.com/haskell/haskell-language-server/archive/${version}.tar.gz"
checksum="5ff053f0f4bb26b867fdc0b4071ba25c47eaa6febc9a4ef5b70a5a31c9433671"
nopie_files="
/usr/bin/haskell-language-server
/usr/bin/haskell-language-server-wrapper
/usr/bin/ghcide-bench
/usr/bin/ghcide
/usr/bin/ghcide-test-preprocessor
"

pre_build() {
    # fixes `/usr/bin/ld: cannot find -lncursesw`
    if [ "$XBPS_TARGET_MACHINE" != "x86_64" ] && [ -f "/lib/libncursesw.so" ]; then
        ln -sf /lib/libncursesw.so.6.2 /lib/libncursesw.so
    fi
}
```

A haskell dependency was looking for `/lib/libncursesw.so`, so we created a symbolic link (like a shortcut in Windows) to `/lib/libncursesw.so.6.2`.

Running `./xbps-src pkg haskell-language-server` brings us to our next error.

### Error: `network`

This is as far as I got with the `armv7l` version. It's also a problem on all the others.

Now I'm not sure what to do here. 

```
network                          > configure
network                          > [1 of 2] Compiling Main             ( /tmp/stack-8ee1647aa5b6024f/network-3.1.1.1/Setup.hs, /tmp/stack-8ee1647aa5b6024f/network-3.1.1.1/.stack-work/dist/x86_64-linux/Cabal-3.0.1.0/setup/Main.o )
network                          > [2 of 2] Compiling StackSetupShim   ( /builddir/haskell-language-server-0.8.0/.stack/setup-exe-src/setup-shim-mPHDZzAJ.hs, /tmp/stack-8ee1647aa5b6024f/network-3.1.1.1/.stack-work/dist/x86_64-linux/Cabal-3.0.1.0/setup/StackSetupShim.o )
network                          > Linking /tmp/stack-8ee1647aa5b6024f/network-3.1.1.1/.stack-work/dist/x86_64-linux/Cabal-3.0.1.0/setup/setup ...
network                          > Configuring network-3.1.1.1...
network                          > configure: WARNING: unrecognized options: --with-compiler
network                          > checking build system type... x86_64-pc-linux-gnu
network                          > checking host system type... x86_64-pc-linux-gnu
network                          > checking for gcc... /usr/bin/cc
network                          > checking whether the C compiler works... no
network                          > configure: error: in `/tmp/stack-8ee1647aa5b6024f/network-3.1.1.1/.stack-work/dist/x86_64-linux/Cabal-3.0.1.0/build':
network                          > configure: error: C compiler cannot create executables
network                          > See `config.log' for more details
```