Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 9 additions & 2 deletions pkgs/development/compilers/ghc/common-hadrian.nix
Original file line number Diff line number Diff line change
Expand Up @@ -340,7 +340,14 @@ let
]
++ lib.optionals targetPlatform.useAndroidPrebuilt [
"*.*.ghc.c.opts += -optc-std=gnu99"
];
]
# Inform GHC that we can't load dynamic libraries which forces iserv-proxy to load static libraries
++
lib.optionals
(targetPlatform.isAndroid || (targetPlatform.isMusl && hostPlatform != targetPlatform))
[
"*.ghc.cabal.configure.opts += --flags=-dynamic-system-linker"
];

# Splicer will pull out correct variations
libDeps =
Expand Down Expand Up @@ -632,7 +639,7 @@ stdenv.mkDerivation (
"--with-ffi-includes=${targetLibs.libffi.dev}/include"
"--with-ffi-libraries=${targetLibs.libffi.out}/lib"
]
++ lib.optionals (targetPlatform == hostPlatform && !enableNativeBignum) [
++ lib.optionals (!enableNativeBignum) [
"--with-gmp-includes=${targetLibs.gmp.dev}/include"
"--with-gmp-libraries=${targetLibs.gmp.out}/lib"
]
Expand Down
84 changes: 84 additions & 0 deletions pkgs/development/haskell-modules/configuration-cross.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
{ pkgs, haskellLib }:

let
inherit (pkgs) lib;
in

with haskellLib;

self: super: {
# Avoids a cycle by disabling use of the external interpreter by the packages that are dependencies of iserv-proxy
# These in particular can't rely on template haskell for cross-compilation anyway as they can't rely on iserv-proxy
inherit
(
let
breakCycle = overrideCabal {
doCheck = false; # test packages themselves like to rely on TH for discovering test cases
enableExternalInterpreter = false;
};
in
lib.mapAttrs (_: breakCycle) { inherit (super) iserv-proxy libiserv network; }
)
iserv-proxy
libiserv
network
;

# qemu: uncaught target signal 4 (Illegal instruction) - core dumped
th-expand-syns = dontCheck super.th-expand-syns;

# test/Unicode/CharSpec.hs:206:21:
# 1) Unicode.Char.Case toUpper
# predicate failed on: '\411'
unicode-data = dontCheck super.unicode-data;

# syntax error: unexpected word (expecting ")")
jsaddle-warp = dontCheck super.jsaddle-warp;

# test-pandoc: line 0: syntax error: unterminated quoted string
pandoc = dontCheck super.pandoc;

# Tests take a long time or maybe hang
bitvec = dontCheck super.bitvec;
crypton = dontCheck super.crypton;
crypton-x509-validation = dontCheck super.crypton-x509-validation;
tls = dontCheck super.tls;

# Test suite rootCleanup: FAIL
reflex = dontCheck super.reflex;

# Couldn't find a target code interpreter. Try with -fexternal-interpreter
bsb-http-chunked = dontCheck super.bsb-http-chunked;
doctest-parallel = dontCheck super.doctest-parallel;
foldl = dontCheck super.foldl;

# https://gitlab.haskell.org/ghc/ghc/-/issues/14335
# <no location info>: error: Plugins require -fno-external-interpreter
infer-license = dontCheck super.infer-license;
inspection-testing = dontCheck super.inspection-testing;
large-records = dontCheck super.large-records;
vector = dontCheck super.vector;

# could not execute: hspec-discover
here = dontCheck super.here;
hspec-wai = dontCheck super.hspec-wai;
http-date = dontCheck super.http-date;
http-types = dontCheck super.http-types;
unliftio = dontCheck super.unliftio;
word8 = dontCheck super.word8;
yaml = dontCheck super.yaml;

# posix_spawnp: invalid argument (Exec format error)
file-lock = dontCheck super.file-lock;
safe-exceptions = dontCheck super.safe-exceptions;
warp = dontCheck super.warp;
zip-archive = dontCheck super.zip-archive;

# Mmap.hsc: In function ‘_hsc2hs_test13’:
# Mmap.hsc:54:20: error: storage size of ‘test_array’ isn’t constant
hashable = dontCheck super.hashable;

# hGetLine: end of file
doctest = dontCheck super.doctest;
xml-conduit = dontCheck super.xml-conduit;
}
6 changes: 5 additions & 1 deletion pkgs/development/haskell-modules/configuration-ghc-9.6.x.nix
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ in
haskeline = null;
hpc = null;
integer-gmp = null;
libiserv = null;
mtl = null;
parsec = null;
pretty = null;
Expand All @@ -60,6 +59,11 @@ in
xhtml = null;
Win32 = null;

# Was only ever released for a few exact versions of ghc
libiserv = unmarkBroken (doJailbreak super.libiserv);

iserv-proxy = addBuildDepends [ self.libiserv ] super.iserv-proxy;

# Becomes a core package in GHC >= 9.8
semaphore-compat = doDistribute self.semaphore-compat_1_0_0;

Expand Down
94 changes: 82 additions & 12 deletions pkgs/development/haskell-modules/configuration-ghcjs-9.x.nix
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,29 @@ in
with haskellLib;

# cabal2nix doesn't properly add dependencies conditional on arch(javascript)
self: super: {

(self: super: {
ghcjs-base = addBuildDepends (with self; [
aeson
attoparsec
dlist
hashable
primitive
scientific
unordered-containers
vector
]) super.ghcjs-base;
ghcjs-base = lib.pipe super.ghcjs-base [
dontCheck # <command line>: does not exist: test/compat.js
(addBuildDepends (
with self;
[
HUnit
aeson
attoparsec
dlist
hashable
primitive
quickcheck-unicode
scientific
test-framework
test-framework-hunit
test-framework-quickcheck2
unordered-containers
vector
]
))
];

ghcjs-dom = addBuildDepend self.ghcjs-dom-javascript super.ghcjs-dom;
ghcjs-dom-javascript = addBuildDepend self.ghcjs-base super.ghcjs-dom-javascript;
Expand Down Expand Up @@ -67,4 +78,63 @@ with haskellLib;

# See https://gitlab.haskell.org/ghc/ghc/-/issues/26019#note_621324, without this flag the build OOMs
SHA = haskellLib.appendConfigureFlag "--ghc-option=-fignore-interface-pragmas" super.SHA;
})

# Tests are extremely slow
scientific = dontCheck super.scientific;

# Tests hang
logict = dontCheck super.logict;

# error: no C compiler provided for this platform
servant-lucid = dontCheck super.servant-lucid;

# javascript-unknown-ghcjs-ghc-9.12.2: could not execute: hspec-discover
http-types = dontCheck super.http-types;

# *** Failed! Exception: 'createPipeInternal: unsupported operation (Operation is not supported)' (after 1 test):
QuickCheck = dontCheck super.QuickCheck;

# SyntaxError: Invalid or unexpected token
syb = dontCheck super.syb;

# uncaught exception in Haskell thread: ReferenceError: h$XXH3_64bits_withSeed is not defined
hashable = dontCheck super.hashable;

# uncaught exception in Haskell thread: ReferenceError: h$hs_text_short_is_valid_utf8 is not defined
text-short = dontCheck super.text-short;

# uncaught exception in Haskell main thread: ReferenceError: h$clock_getres is not defined
time-compat = dontCheck super.time-compat;

# uncaught exception in Haskell main thread: ReferenceError: h$getNumberOfProcessors is not defined
hedgehog = dontCheck super.hedgehog;

# uncaught exception in Haskell main thread: ReferenceError: h$readlink is not defined
adjunctions = dontCheck super.adjunctions;
aeson-gadt-th = dontCheck super.aeson-gadt-th;
aeson-qq = dontCheck super.aeson-qq;
base-orphans = dontCheck super.base-orphans;
bifunctors = dontCheck super.bifunctors;
constraints = dontCheck super.constraints;
distributive = dontCheck super.distributive;
doctest = dontCheck super.doctest;
generic-deriving = dontCheck super.generic-deriving;
hspec-discover = dontCheck super.hspec-discover;
hspec-hedgehog = dontCheck super.hspec-hedgehog;
http-api-data = dontCheck super.http-api-data;
invariant = dontCheck super.invariant;
lucid = dontCheck super.lucid;
markdown-unlit = dontCheck super.markdown-unlit;
newtype-generics = dontCheck super.newtype-generics;
records-sop = dontCheck super.records-sop;
reflection = dontCheck super.reflection;
reflex = dontCheck super.reflex;
resourcet = dontCheck super.resourcet;
safe-exceptions = dontCheck super.safe-exceptions;
servant = dontCheck super.servant;
should-not-typecheck = dontCheck super.should-not-typecheck;
stringbuilder = dontCheck super.stringbuilder;
th-compat = dontCheck super.th-compat;
th-orphans = dontCheck super.th-orphans;
zenc = dontCheck super.zenc;
}
3 changes: 0 additions & 3 deletions pkgs/development/haskell-modules/configuration-nix.nix
Original file line number Diff line number Diff line change
Expand Up @@ -1259,9 +1259,6 @@ builtins.intersectAttrs super {
'';
}) (addBuildTool pkgs.buildPackages.makeWrapper super.cut-the-crap);

# Compiling the readme throws errors and has no purpose in nixpkgs
aeson-gadt-th = disableCabalFlag "build-readme" super.aeson-gadt-th;

# Fix compilation of Setup.hs by removing the module declaration.
# See: https://github.com/tippenein/guid/issues/1
guid = overrideCabal (drv: {
Expand Down
4 changes: 4 additions & 0 deletions pkgs/development/haskell-modules/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
configurationArm ? import ./configuration-arm.nix,
configurationDarwin ? import ./configuration-darwin.nix,
configurationWindows ? import ./configuration-windows.nix,
configurationCross ? import ./configuration-cross.nix,
configurationJS ? import ./configuration-ghcjs-9.x.nix,
}:

Expand Down Expand Up @@ -46,6 +47,9 @@ let
++ lib.optionals stdenv.hostPlatform.isWindows [
(configurationWindows { inherit pkgs haskellLib; })
]
++ lib.optionals (stdenv.buildPlatform != stdenv.hostPlatform) [
(configurationCross { inherit pkgs haskellLib; })
]
++ lib.optionals stdenv.hostPlatform.isGhcjs [
(configurationJS { inherit pkgs haskellLib; })
];
Expand Down
82 changes: 78 additions & 4 deletions pkgs/development/haskell-modules/generic-builder.nix
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,73 @@
runCommandCC,
ghcWithHoogle,
ghcWithPackages,
haskellLib,
iserv-proxy,
nodejs,
writeShellScriptBin,
}:

let
isCross = stdenv.buildPlatform != stdenv.hostPlatform;

crossSupport = rec {
emulator = stdenv.hostPlatform.emulator buildPackages;

hasBuiltinTH = stdenv.hostPlatform.isGhcjs;

canProxyTH =
lib.versionAtLeast ghc.version "9.6" && stdenv.hostPlatform.emulatorAvailable buildPackages;

# Many suites use Template Haskell for test discovery, including QuickCheck
canCheck = hasBuiltinTH || canProxyTH;

# stdenv.make-derivation sets `doCheck = false` when the build platform can't directly execute the host platform
# which means the `checkPhase` ends up disabled for cross and we need to sneak it back in somehow
# TODO: avoid this workaround - add some sort of doCheckEmulated?
Copy link
Member Author

@alexfmpe alexfmpe Oct 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is pretty hacky, but I don't see another way to run tests by default unless we change make-derivation itself.
We could settle for passthru.tests though

checkPhaseSidecar = doCheck: drv: anchor: lib.trim ''
${anchor}
${lib.optionalString (doCheck && isCross) drv.checkPhase}
'';

iservWrapper =
let
buildProxy = lib.getExe' iserv-proxy.build "iserv-proxy";

wrapperScript =
enableProfiling:
let
overrides = haskellLib.overrideCabal {
enableLibraryProfiling = enableProfiling;
enableExecutableProfiling = enableProfiling;
};
hostProxy = lib.getExe' (overrides iserv-proxy.host) "iserv-proxy-interpreter";
in
buildPackages.writeShellScriptBin ("iserv-wrapper" + lib.optionalString enableProfiling "-prof") ''
set -euo pipefail
PORT=$((5000 + $RANDOM % 5000))
(>&2 echo "---> Starting interpreter on port $PORT")
${emulator} ${hostProxy} tmp $PORT &
RISERV_PID="$!"
trap "kill $RISERV_PID" EXIT # Needs cleanup when building without sandbox
${buildProxy} $@ 127.0.0.1 "$PORT"
(>&2 echo "---> killing interpreter...")
'';

# GHC will add `-prof` to the external interpreter when doing a profiled build.
# Since a single derivation can build with both profiling and non-profiling versions
# we need both versions made available
both = buildPackages.symlinkJoin {
name = "iserv-wrapper-both";
paths = builtins.map wrapperScript [
false
true
];
};

in
"${both}/bin/iserv-wrapper";
};

# Pass the "wrong" C compiler rather than none at all so packages that just
# use the C preproccessor still work, see
# https://github.com/haskell/cabal/issues/6466 for details.
Expand Down Expand Up @@ -67,7 +128,7 @@ in
buildFlags ? [ ],
haddockFlags ? [ ],
description ? null,
doCheck ? !isCross,
doCheck ? isCross -> crossSupport.canCheck,
doBenchmark ? false,
doHoogle ? true,
doHaddockQuickjump ? doHoogle,
Expand Down Expand Up @@ -205,10 +266,15 @@ in
# of `meta.pkgConfigModules`. This option defaults to false for now, since
# this metadata is far from complete in nixpkgs.
__onlyPropagateKnownPkgConfigModules ? false,

enableExternalInterpreter ? isCross && crossSupport.canProxyTH,
}@args:

assert editedCabalFile != null -> revision != null;

# We only use iserv-proxy for the external interpreter
assert enableExternalInterpreter -> crossSupport.canProxyTH;

# --enable-static does not work on windows. This is a bug in GHC.
# --enable-static will pass -staticlib to ghc, which only works for mach-o and elf.
assert stdenv.hostPlatform.isWindows -> enableStaticLibraries == false;
Expand Down Expand Up @@ -298,7 +364,15 @@ let
"--hsc2hs-option=--cross-compile"
(optionalString enableHsc2hsViaAsm "--hsc2hs-option=--via-asm")
]
++ optional (allPkgconfigDepends != [ ]) "--with-pkg-config=${pkg-config.targetPrefix}pkg-config";
++ optional (allPkgconfigDepends != [ ]) "--with-pkg-config=${pkg-config.targetPrefix}pkg-config"

++ optionals enableExternalInterpreter (
map (opt: "--ghc-option=${opt}") [
"-fexternal-interpreter"
"-pgmi"
crossSupport.iservWrapper
]
);

makeGhcOptions = opts: lib.concatStringsSep " " (map (opt: "--ghc-option=${opt}") opts);

Expand Down Expand Up @@ -541,7 +615,7 @@ let
export GHC_PACKAGE_PATH="''${NIX_GHC_PACKAGE_PATH_FOR_TEST}"
fi

exec "$@"
exec ${if (isCross && crossSupport.canCheck) then "node" else crossSupport.emulator} "$@"
'';

testTargetsString =
Expand Down Expand Up @@ -770,7 +844,7 @@ lib.fix (
''
+ ''
${setupCommand} build ${buildTarget}${buildFlagsString}
runHook postBuild
${crossSupport.checkPhaseSidecar doCheck drv "runHook postBuild"}
'';

inherit doCheck;
Expand Down
Loading
Loading