Skip to content

Commit da1cf8c

Browse files
committed
pkgsMusl.haskell.compiler.ghc8102Binary: Fix musl segfault. Fixes #118731 #129247.
This commit replaces the musl + glibc hackery in the GHC bindist compiler by using the new musl based bindist that GHC HQ provides (built on Alpine). We could alternatively also use a nix-built musl boostrap compiler, but it seems nicer to use the GHC HQ one for now. This fixes the compiler built by `pkgsMusl.haskell.compiler.ghc8102Binary` segfaulting (#118731) since the commit 5e2311d - musl: 1.2.1 -> 1.2.2 concretely, musl commit 01c7920f - remove redundant pthread struct members repeated for layout purposes which I suspect breaks some glibc/musl ABI compatibility that may have existed accidentally until then. The added lib.optional stdenv.targetPlatform.isMusl "pie"; also fixes that the packaged bindist compiler cannot create a binary in its `installCheck` phase (and overall); see detail explanation in #129247.
1 parent 5777bd3 commit da1cf8c

File tree

1 file changed

+76
-29
lines changed

1 file changed

+76
-29
lines changed

pkgs/development/compilers/ghc/8.10.2-binary.nix

Lines changed: 76 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{ lib, stdenv
22
, fetchurl, perl, gcc
33
, ncurses5
4-
, ncurses6, gmp, glibc, libiconv, numactl
4+
, ncurses6, gmp, libiconv, numactl
55
, llvmPackages
66

77
# minimal = true; will remove files that aren't strictly necessary for
@@ -49,16 +49,33 @@ let
4949
{ nixPackage = ncurses5; fileToCheckFor = "libtinfo.so.5"; }
5050
];
5151
};
52-
x86_64-linux = {
53-
src = {
54-
url = "${downloadsUrl}/${version}/ghc-${version}-x86_64-deb10-linux.tar.xz";
55-
sha256 = "0chnzy9j23b2wa8clx5arwz8wnjfxyjmz9qkj548z14cqf13slcl";
56-
};
57-
exePathForLibraryCheck = "ghc/stage2/build/tmp/ghc-stage2";
58-
archSpecificLibraries = [
59-
{ nixPackage = ncurses6; fileToCheckFor = "libtinfo.so.6"; }
60-
];
61-
};
52+
x86_64-linux =
53+
if stdenv.hostPlatform.isMusl
54+
then
55+
{ # musl-bindist (referred to below)
56+
src = {
57+
url = "${downloadsUrl}/${version}/ghc-${version}-x86_64-alpine3.10-linux-integer-simple.tar.xz";
58+
sha256 = "0xpcbyaxqyhbl6f0i3s4rp2jm67nqpkfh2qlbj3i2fiaix89ml0l";
59+
};
60+
exePathForLibraryCheck = "bin/ghc";
61+
archSpecificLibraries = [
62+
# In contrast to glibc builds, the musl-bindist uses `libncursesw.so.*`
63+
# instead of `libtinfo.so.*.`
64+
{ nixPackage = ncurses6; fileToCheckFor = "libncursesw.so.6"; }
65+
];
66+
}
67+
else
68+
{ # normal glibc based bindist
69+
src = {
70+
url = "${downloadsUrl}/${version}/ghc-${version}-x86_64-deb10-linux.tar.xz";
71+
sha256 = "0chnzy9j23b2wa8clx5arwz8wnjfxyjmz9qkj548z14cqf13slcl";
72+
};
73+
exePathForLibraryCheck = "ghc/stage2/build/tmp/ghc-stage2";
74+
archSpecificLibraries = [
75+
{ nixPackage = ncurses6; fileToCheckFor = "libtinfo.so.6"; }
76+
];
77+
}
78+
;
6279
armv7l-linux = {
6380
src = {
6481
url = "${downloadsUrl}/${version}/ghc-${version}-armv7-deb10-linux.tar.xz";
@@ -110,12 +127,6 @@ let
110127
libEnvVar = lib.optionalString stdenv.hostPlatform.isDarwin "DY"
111128
+ "LD_LIBRARY_PATH";
112129

113-
glibcDynLinker = assert stdenv.isLinux;
114-
if stdenv.hostPlatform.libc == "glibc" then
115-
# Could be stdenv.cc.bintools.dynamicLinker, keeping as-is to avoid rebuild.
116-
''"$(cat $NIX_CC/nix-support/dynamic-linker)"''
117-
else
118-
"${lib.getLib glibc}/lib/ld-linux*";
119130
in
120131

121132
stdenv.mkDerivation rec {
@@ -126,7 +137,20 @@ stdenv.mkDerivation rec {
126137
src = fetchurl binDistUsed.src;
127138

128139
nativeBuildInputs = [ perl ];
129-
propagatedBuildInputs = lib.optionals useLLVM [ llvmPackages.llvm ];
140+
propagatedBuildInputs =
141+
lib.optionals useLLVM [ llvmPackages.llvm ]
142+
# Because musl bindists currently provide no way to tell where
143+
# libgmp is (see not [musl bindists have no .buildinfo]), we need
144+
# to propagate `gmp`, otherwise programs built by this ghc will
145+
# fail linking with `cannot find -lgmp` errors.
146+
# Also, as of writing, the release pages of musl bindists claim
147+
# that they use `integer-simple` and do not require `gmp`; however
148+
# that is incorrect, so `gmp` is required until a release has been
149+
# made that includes https://gitlab.haskell.org/ghc/ghc/-/issues/20059.
150+
# (Note that for packaging the `-binary` compiler, nixpkgs does not care
151+
# about whether or not `gmp` is used; this comment is just here to explain
152+
# why the `gmp` dependency exists despite what the release page says.)
153+
++ lib.optionals stdenv.hostPlatform.isMusl [ gmp ]; # musl bindist needs this
130154

131155
# Set LD_LIBRARY_PATH or equivalent so that the programs running as part
132156
# of the bindist installer can find the libraries they expect.
@@ -187,6 +211,9 @@ stdenv.mkDerivation rec {
187211
patchShebangs ghc-${version}/configure
188212
'' +
189213
# We have to patch the GMP paths for the integer-gmp package.
214+
# Note [musl bindists have no .buildinfo]
215+
# Note that musl bindists do not contain them; unclear if that's intended;
216+
# see: https://gitlab.haskell.org/ghc/ghc/-/issues/20073#note_363231
190217
''
191218
find . -name integer-gmp.buildinfo \
192219
-exec sed -i "s@extra-lib-dirs: @extra-lib-dirs: ${gmp.out}/lib@" {} \;
@@ -203,16 +230,7 @@ stdenv.mkDerivation rec {
203230
# Rename needed libraries and binaries, fix interpreter
204231
lib.optionalString stdenv.isLinux ''
205232
find . -type f -perm -0100 -exec patchelf \
206-
--interpreter ${glibcDynLinker} {} \;
207-
'' +
208-
# We're kludging a glibc bindist into working with non-glibc...
209-
# Here we patch up the use of `__strdup` (part of glibc binary ABI)
210-
# to instead use `strdup` since musl doesn't provide __strdup
211-
# (`__strdup` is defined to be an alias of `strdup` anyway[1]).
212-
# [1] http://refspecs.linuxbase.org/LSB_4.0.0/LSB-Core-generic/LSB-Core-generic/baselib---strdup-1.html
213-
# Use objcopy magic to make the change:
214-
lib.optionalString stdenv.hostPlatform.isMusl ''
215-
find ./ghc-${version}/rts -name "libHSrts*.a" -exec ''${OBJCOPY:-objcopy} --redefine-sym __strdup=strdup {} \;
233+
--interpreter ${stdenv.cc.bintools.dynamicLinker} {} \;
216234
'';
217235

218236
# fix for `configure: error: Your linker is affected by binutils #16177`
@@ -222,6 +240,9 @@ stdenv.mkDerivation rec {
222240

223241
configurePlatforms = [ ];
224242
configureFlags = [
243+
# Note that musl-based bindists seem to do nothing with the
244+
# `--with-gmp-libraries` flag, see:
245+
# https://gitlab.haskell.org/ghc/ghc/-/issues/20073#note_363231
225246
"--with-gmp-libraries=${lib.getLib gmp}/lib"
226247
"--with-gmp-includes=${lib.getDev gmp}/include"
227248
] ++ lib.optional stdenv.isDarwin "--with-gcc=${./gcc-clang-wrapper.sh}"
@@ -232,6 +253,22 @@ stdenv.mkDerivation rec {
232253
# calls install-strip ...
233254
dontBuild = true;
234255

256+
# Apparently necessary for the ghc Alpine (musl) bindist:
257+
# When we strip, and then run the
258+
# patchelf --set-rpath "${libPath}:$(patchelf --print-rpath $p)" $p
259+
# below, running ghc (e.g. during `installCheckPhase)` gives some apparently
260+
# corrupted rpath or whatever makes the loader work on nonsensical strings:
261+
# running install tests
262+
# Error relocating /nix/store/...-ghc-8.10.2-binary/lib/ghc-8.10.5/bin/ghc: : symbol not found
263+
# Error relocating /nix/store/...-ghc-8.10.2-binary/lib/ghc-8.10.5/bin/ghc: ir6zf6c9f86pfx8sr30n2vjy-ghc-8.10.2-binary/lib/ghc-8.10.5/bin/../lib/x86_64-linux-ghc-8.10.5/libHSexceptions-0.10.4-ghc8.10.5.so: symbol not found
264+
# Error relocating /nix/store/...-ghc-8.10.2-binary/lib/ghc-8.10.5/bin/ghc: y/lib/ghc-8.10.5/bin/../lib/x86_64-linux-ghc-8.10.5/libHStemplate-haskell-2.16.0.0-ghc8.10.5.so: symbol not found
265+
# Error relocating /nix/store/...-ghc-8.10.2-binary/lib/ghc-8.10.5/bin/ghc: 8.10.5/libHStemplate-haskell-2.16.0.0-ghc8.10.5.so: symbol not found
266+
# Error relocating /nix/store/...-ghc-8.10.2-binary/lib/ghc-8.10.5/bin/ghc: �: symbol not found
267+
# Error relocating /nix/store/...-ghc-8.10.2-binary/lib/ghc-8.10.5/bin/ghc: �?: symbol not found
268+
# Error relocating /nix/store/...-ghc-8.10.2-binary/lib/ghc-8.10.5/bin/ghc: 64-linux-ghc-8.10.5/libHSexceptions-0.10.4-ghc8.10.5.so: symbol not found
269+
# This is extremely bogus and should be investigated.
270+
dontStrip = if stdenv.hostPlatform.isMusl then true else false; # `if` for explicitness
271+
235272
# On Linux, use patchelf to modify the executables so that they can
236273
# find editline/gmp.
237274
postFixup = lib.optionalString stdenv.isLinux
@@ -279,13 +316,23 @@ stdenv.mkDerivation rec {
279316
find $out -type f -name '*.p_o' -delete
280317
find $out -type f -name '*.p_hi' -delete
281318
find $out -type f -name '*_p.a' -delete
282-
rm $out/lib/ghc-*/bin/ghc-iserv-prof
319+
# `-f` because e.g. musl bindist does not have this file.
320+
rm -f $out/lib/ghc-*/bin/ghc-iserv-prof
283321
# Hydra will redistribute this derivation, so we have to keep the docs for
284322
# legal reasons (retaining the legal notices etc)
285323
# As a last resort we could unpack the docs separately and symlink them in.
286324
# They're in $out/share/{doc,man}.
287325
'';
288326

327+
# In nixpkgs, musl based builds currently enable `pie` hardening by default
328+
# (see `defaultHardeningFlags` in `make-derivation.nix`).
329+
# But GHC cannot currently produce outputs that are ready for `-pie` linking.
330+
# Thus, disable `pie` hardening, otherwise `recompile with -fPIE` errors appear.
331+
# See:
332+
# * https://github.com/NixOS/nixpkgs/issues/129247
333+
# * https://gitlab.haskell.org/ghc/ghc/-/issues/19580
334+
hardeningDisable = lib.optional stdenv.targetPlatform.isMusl "pie";
335+
289336
doInstallCheck = true;
290337
installCheckPhase = ''
291338
unset ${libEnvVar}

0 commit comments

Comments
 (0)