ghcup-hs
ghcup-hs copied to clipboard
Something seems wrong with ghcup installing bindist for i386 on debian 12
Something goes wrong during installation which means not all the files are copied into the installation directories.
- https://github.com/haskell/ghcup-metadata/actions/runs/9990740016/job/27612053068
I tried in a container unpacking and manually ./configure && make install the bindist and that worked, so it appears the bindist is correct.
With the manually installed bindist I can run the tests without problems.
Something goes wrong during installation which means not all the files are copied into the installation directories.
I don't think that's the case:
root@c3d8e90f42ba:~# file ~/.ghcup/bin/ghc
/root/.ghcup/bin/ghc: broken symbolic link to ../ghc/9.4.8/bin/ghc-9.4.8
root@c3d8e90f42ba:~# file ~/.ghcup/bin/../ghc/9.4.8/bin/ghc-9.4.8
/root/.ghcup/bin/../ghc/9.4.8/bin/ghc-9.4.8: cannot open `/root/.ghcup/bin/../ghc/9.4.8/bin/ghc-9.4.8' (Value too large for defined data type)Bourne-Again shell script, ASCII text executable
root@c3d8e90f42ba:~# ~/.ghcup/bin/../ghc/9.4.8/bin/ghc-9.4.8 --version
root@c3d8e90f42ba:~# cat ~/.ghcup/bin/../ghc/9.4.8/bin/ghc-9.4.8
#!/bin/bash
exedir="/root/.ghcup/ghc/9.4.8/lib/ghc-9.4.8/bin"
exeprog="./ghc-9.4.8"
executablename="/root/.ghcup/ghc/9.4.8/lib/ghc-9.4.8/bin/./ghc-9.4.8"
bindir="/root/.ghcup/ghc/9.4.8/bin"
libdir="/root/.ghcup/ghc/9.4.8/lib/ghc-9.4.8/lib"
docdir="/root/.ghcup/ghc/9.4.8/share/doc/ghc-9.4.8"
includedir="/root/.ghcup/ghc/9.4.8/include"
exec "$executablename" -B"$libdir" ${1+"$@"}
root@c3d8e90f42ba:~# /root/.ghcup/ghc/9.4.8/lib/ghc-9.4.8/bin/./ghc-9.4.8 --version
The Glorious Glasgow Haskell Compilation System, version 9.4.8
See that the symbolic link is considered broken, but the file is actually there. And then we get some Value too large for defined data type errors.
I see, is there something about the way ghcup is constructing these symlinks which causes the issue? The manual bindist install seems to work correctly.
The manual install worked locally for me but it seems something else is quite fundamentally broken on deb12 on i386. Here is a job I added to ghcup-ci testing which installs the bindist directly (and fails in a different place), which I can't reproduce locally in a docker container.
https://gitlab.haskell.org/ghc/ghcup-ci/-/jobs/1935815
GHC issue: https://gitlab.haskell.org/ghc/ghc/-/issues/25095
@erikd has hit this it seems
https://github.com/haskell/ghcup-metadata/actions/runs/12122182165/job/33794792278#step:5:13728
This was tracked down to https://github.com/haskell/unix/pull/318
Starting with the next release of GHCup, that should be fixed.
It appears it's not fixed.
https://github.com/haskell/ghcup-metadata/actions/runs/12611467513/job/35147163425#step:5:16612
This has the good ghcup binary. I can still reproduce in a container. touch-ing the file /root/.ghcup/ghc/9.4.8/bin/ghc-9.4.8 seems to "fix" it. So there's still something wrong in unix, potentially.
I also just ran into this. A workaround is to use ghcup 0.1.20.0, everything works for me there. All newer ghcup releases (including 0.1.40.0) produce a corrupted installation.
How to reproduce
On a x86_64-linux machine:
podman run --name ghcup-bug --arch i386 -dt i386/debian:bookworm
podman exec -it ghcup-bug bash
Then, in the container, set up some stuff:
apt update
apt install -y build-essential curl libffi-dev libffi8 libgmp-dev libgmp10 libncurses-dev libncurses5 libtinfo5
curl --proto '=https' --tlsv1.2 -sSf https://get-ghcup.haskell.org | BOOTSTRAP_HASKELL_NONINTERACTIVE=1 BOOTSTRAP_HASKELL_MINIMAL=1 sh
source /root/.ghcup/env
ghcup install ghc 9.6.6 --set
echo 'main = putStrLn "hi"' > test.hs
Now, try to compile test.hs:
$ ghc test.hs
[1 of 2] Compiling Main ( test.hs, test.o )
[2 of 2] Linking test
In file included from /tmp/ghc53990_0/ghc_3.c:1:0: error:
/root/.ghcup/ghc/9.6.6/lib/ghc-9.6.6/lib/../lib/i386-linux-ghc-9.6.6/rts-1.0.2/include/Rts.h:20:10: error:
fatal error: /root/.ghcup/ghc/9.6.6/lib/ghc-9.6.6/lib/../lib/i386-linux-ghc-9.6.6/rts-1.0.2/include/ghcconfig.h: Value too large for defined data type
20 | #include "ghcconfig.h"
| ^~~~~~~~~~~~~
|
20 | #include "ghcconfig.h"
| ^
compilation terminated.
ghcup 0.1.20.0 works fine
ghcup rm ghc 9.6.6
curl -sL https://github.com/haskell/ghcup-hs/releases/download/v0.1.20.0/i386-linux-ghcup-0.1.20.0 > /root/.ghcup/bin/ghcup
chmod +x /root/.ghcup/bin/ghcup
ghcup install ghc 9.6.6 --set
ghc test.hs && ./test
Yes, I thought for a moment that it's a bug in unix.
After an installation with i386 ghcup:
ghci> t <- getModificationTime "/root/.ghcup/ghc/9.4.8/bin/ghc-9.4.8"
ghci> t
2038-01-19 03:14:07 UTC
ghci> utcTimeToPOSIXSeconds t
2147483647s
ghci> maxBound :: Int
2147483647
It appears the max bound is causing issues with musl. But the question is how did it end up messed up that way in the first place.
I could not reproduce the issue with setModificationTime etc. on debian 12 in ghci manually, nor when I build ghcup there. This suggests there must be an issue with a combination of musl version and linux kernel version?
Hi @hasufell, I found this issue from here. My guess is this is caused because the musl library the builder is using has transitioned to time64, but the GHC the builder is using is not.
Background
In order to solve the Y2038, libc and musl migrated to a 64-bit size for time_t. You can find more information here and here. The gist is that this is an ABI breaking change, and binaries that link against versions of libc/musl that use time64 need to be recompiled.
The issue
-
The image we are using to build the i386 package for ghcup has musl with time64.
You can verify this by running the following:
$ docker run -ti --rm hasufell/i386-alpine-haskell:3.21 /bin/bash 632b1225802d:/# echo -e '#include <stdio.h>\n#include <time.h>\nvoid main() { printf("%u\\n", sizeof(time_t)); }' > foo.c 632b1225802d:/# gcc -o foo foo.c 632b1225802d:/# ./foo 8 -
The GHC we are using considers time_t to be 32-bit.
This happens either because this GHC was not compiled with 64-bit time_t, or because this GHC is old and doesn't contain the necessary fixes to support time64 (e.g., https://gitlab.haskell.org/ghc/packages/time/-/commit/d52314edb138b6ecd7e888c588f83917b0ee2c29, https://gitlab.haskell.org/ghc/packages/directory/-/commit/f6b288bd96fba5a955d1f73663eb52c1859ee765 etc). You can verify this is the case with the following:
$ docker run -ti --rm hasufell/i386-alpine-haskell:3.21 /bin/bash ... (Download and install https://downloads.haskell.org/~ghcup/unofficial-bindists/ghc/8.10.7/ghc-8.10.7-i386-alpine-linux.tar.xz) ghci> import Foreign.Storable ghci> import Foreign.C.Types ghci> sizeOf (0 :: CTime) 4 -
Since musl and GHC disagree about the size of CTime, this means that GHC itself may misbehave, and also that any programs that are compiled with this GHC will be broken wrt time operations. This is why the
ghcupbinary doesn't work.
Solution
You can try with a newer GHC (e.g., https://downloads.haskell.org/~ghcup/unofficial-bindists/ghc/9.6.7/ghc-9.6.7-i386-linux-alpine-3.17.7.tar.xz) which seems to be properly compiled for musl with time64.
i386 alpine built with 9.6.7 seems to segfault: https://github.com/haskell/ghcup-hs/actions/runs/14350951698/job/40230400883?pr=1252#step:6:546