mirror of
https://github.com/ilyakooo0/haskell.nix.git
synced 2024-09-11 06:55:40 +03:00
Enable debug info on linux targets (#1050)
* Add `.debug` to build any component with DWARF dugug info on linux (ghc >=8.10.2). * Pass `enableDWARF` to `shellFor` for to get a shell where all the components are the `.debug` ones.
This commit is contained in:
parent
27a5268093
commit
bab2eaea62
@ -1,4 +1,4 @@
|
||||
{ pkgs, stdenv, buildPackages, ghc, lib, gobject-introspection ? null, haskellLib, makeConfigFiles, haddockBuilder, ghcForComponent, hsPkgs, compiler, runCommand, libffi, gmp, zlib, ncurses, numactl, nodejs }:
|
||||
{ pkgs, stdenv, buildPackages, ghc, lib, gobject-introspection ? null, haskellLib, makeConfigFiles, haddockBuilder, ghcForComponent, hsPkgs, compiler, runCommand, libffi, gmp, zlib, ncurses, numactl, nodejs }@defaults:
|
||||
lib.makeOverridable (
|
||||
let self =
|
||||
{ componentId
|
||||
@ -77,6 +77,16 @@ let self =
|
||||
}@drvArgs:
|
||||
|
||||
let
|
||||
# Ignore attempts to include DWARF info when it is not possible
|
||||
enableDWARF = drvArgs.enableDWARF or false
|
||||
&& stdenv.hostPlatform.isLinux
|
||||
&& !haskellLib.isCrossHost
|
||||
&& !stdenv.hostPlatform.isMusl
|
||||
&& builtins.compareVersions defaults.ghc.version "8.10.2" >= 0;
|
||||
|
||||
ghc = if enableDWARF then defaults.ghc.dwarf else defaults.ghc;
|
||||
setup = if enableDWARF then drvArgs.setup.dwarf else drvArgs.setup;
|
||||
|
||||
# TODO fix cabal wildcard support so hpack wildcards can be mapped to cabal wildcards
|
||||
canCleanSource = !(cabal-generator == "hpack" && !(package.cleanHpack or false));
|
||||
# In order to support relative references to other packages we need to use
|
||||
@ -109,7 +119,7 @@ let
|
||||
|
||||
configFiles = makeConfigFiles {
|
||||
inherit (package) identifier;
|
||||
inherit component fullName flags needsProfiling;
|
||||
inherit component fullName flags needsProfiling enableDWARF;
|
||||
};
|
||||
|
||||
enableFeature = enable: feature:
|
||||
@ -178,7 +188,7 @@ let
|
||||
++ (ghc.extraConfigureFlags or [])
|
||||
++ lib.optional enableDebugRTS "--ghc-option=-debug"
|
||||
++ lib.optional enableTSanRTS "--ghc-option=-tsan"
|
||||
++ lib.optional enableDWARF "--ghc-option=-g"
|
||||
++ lib.optional enableDWARF "--ghc-option=-g3"
|
||||
++ lib.optionals useLLVM [
|
||||
"--ghc-option=-fPIC" "--gcc-option=-fPIC"
|
||||
]
|
||||
@ -195,7 +205,7 @@ let
|
||||
# work in the nix-shell. See ../doc/removing-with-package-wrapper.md.
|
||||
shellWrappers = ghcForComponent {
|
||||
componentName = fullName;
|
||||
inherit configFiles;
|
||||
inherit configFiles enableDWARF;
|
||||
};
|
||||
|
||||
# In order to let shell hooks make package-specific things like Hoogle databases
|
||||
@ -280,10 +290,11 @@ let
|
||||
config = component;
|
||||
srcSubDir = cleanSrc.subDir;
|
||||
srcSubDirPath = cleanSrc.root + cleanSrc.subDir;
|
||||
inherit configFiles executableToolDepends exeName;
|
||||
inherit configFiles executableToolDepends exeName enableDWARF;
|
||||
exePath = drv + "/bin/${exeName}";
|
||||
env = shellWrappers;
|
||||
profiled = self (drvArgs // { enableLibraryProfiling = true; });
|
||||
dwarf = self (drvArgs // { enableDWARF = true; });
|
||||
} // lib.optionalAttrs (haskellLib.isLibrary componentId) ({
|
||||
inherit haddock;
|
||||
inherit (haddock) haddockDir; # This is null if `doHaddock = false`
|
||||
|
@ -7,14 +7,17 @@
|
||||
# database.
|
||||
|
||||
{ lib, stdenv, ghc, runCommand, lndir, makeWrapper, haskellLib
|
||||
}:
|
||||
}@defaults:
|
||||
|
||||
{ componentName # Full derivation name of the component
|
||||
, configFiles # The component's "config" derivation
|
||||
, postInstall ? ""
|
||||
, enableDWARF
|
||||
}:
|
||||
|
||||
let
|
||||
ghc = if enableDWARF then defaults.ghc.dwarf else defaults.ghc;
|
||||
|
||||
inherit (configFiles) targetPrefix ghcCommand ghcCommandCaps packageCfgDir;
|
||||
libDir = "$out/${configFiles.libDir}";
|
||||
docDir = "$out/share/doc/ghc/html";
|
||||
|
@ -54,6 +54,7 @@ let
|
||||
shellWrappers = ghcForComponent {
|
||||
componentName = fullName;
|
||||
configFiles = docsConfigFiles;
|
||||
inherit (componentDrv) enableDWARF;
|
||||
};
|
||||
|
||||
drv = stdenv.mkDerivation (commonAttrs // {
|
||||
|
@ -1,8 +1,10 @@
|
||||
{ stdenv, lib, haskellLib, ghc, nonReinstallablePkgs, runCommand, writeText, writeScript }:
|
||||
{ stdenv, lib, haskellLib, ghc, nonReinstallablePkgs, runCommand, writeText, writeScript }@defaults:
|
||||
|
||||
{ identifier, component, fullName, flags ? {}, needsProfiling ? false, chooseDrv ? drv: drv }:
|
||||
{ identifier, component, fullName, flags ? {}, needsProfiling ? false, enableDWARF ? false, chooseDrv ? drv: drv }:
|
||||
|
||||
let
|
||||
ghc = if enableDWARF then defaults.ghc.dwarf else defaults.ghc;
|
||||
|
||||
flagsAndConfig = field: xs: lib.optionalString (xs != []) ''
|
||||
echo ${lib.concatStringsSep " " (map (x: "--${field}=${x}") xs)} >> $out/configure-flags
|
||||
echo "${field}: ${lib.concatStringsSep " " xs}" >> $out/cabal.config
|
||||
@ -47,9 +49,10 @@ let
|
||||
# TODO investigate why this is needed
|
||||
# TODO find out why p ? configFiles helps (for instance for `R1909.aarch64-unknown-linux-gnu.tests.cabal-22.run.x86_64-linux`)
|
||||
libDeps = map chooseDrv (
|
||||
(if needsProfiling then (x: map (p: p.profiled or p) x) else x: x)
|
||||
(if enableDWARF then (x: map (p: p.dwarf or p) x) else x: x)
|
||||
((if needsProfiling then (x: map (p: p.profiled or p) x) else x: x)
|
||||
(lib.filter (p: (p ? configFiles) && p.configFiles.targetPrefix == ghc.targetPrefix)
|
||||
(map getLibComponent component.depends))
|
||||
(map getLibComponent component.depends)))
|
||||
);
|
||||
cfgFiles =
|
||||
let xs = map
|
||||
|
@ -1,12 +1,13 @@
|
||||
{ pkgs, stdenv, lib, buildPackages, haskellLib, ghc, nonReinstallablePkgs, hsPkgs, makeSetupConfigFiles, pkgconfig }:
|
||||
|
||||
{ component, package, name, src, flags ? {}, revision ? null, patches ? [], defaultSetupSrc
|
||||
let self =
|
||||
{ component, package, name, src, enableDWARF ? false, flags ? {}, revision ? null, patches ? [], defaultSetupSrc
|
||||
, preUnpack ? component.preUnpack, postUnpack ? component.postUnpack
|
||||
, prePatch ? null, postPatch ? null
|
||||
, preBuild ? component.preBuild , postBuild ? component.postBuild
|
||||
, preInstall ? component.preInstall , postInstall ? component.postInstall
|
||||
, cleanSrc ? haskellLib.cleanCabalComponent package component "setup" src
|
||||
}:
|
||||
}@drvArgs:
|
||||
|
||||
let
|
||||
cleanSrc' = haskellLib.rootAndSubDir cleanSrc;
|
||||
@ -17,7 +18,7 @@ let
|
||||
|
||||
configFiles = makeSetupConfigFiles {
|
||||
inherit (package) identifier;
|
||||
inherit fullName flags component;
|
||||
inherit fullName flags component enableDWARF;
|
||||
};
|
||||
hooks = haskellLib.optionalHooks {
|
||||
inherit
|
||||
@ -50,6 +51,7 @@ let
|
||||
srcSubDirPath = cleanSrc'.root + cleanSrc'.subDir;
|
||||
cleanSrc = cleanSrc';
|
||||
inherit configFiles;
|
||||
dwarf = self (drvArgs // { enableDWARF = true; });
|
||||
};
|
||||
|
||||
meta = {
|
||||
@ -94,4 +96,4 @@ let
|
||||
// (lib.optionalAttrs (patches != []) { patches = map (p: if builtins.isFunction p then p { inherit (package.identifier) version; inherit revision; } else p) patches; })
|
||||
// hooks
|
||||
);
|
||||
in drv
|
||||
in drv; in self
|
||||
|
@ -16,6 +16,7 @@
|
||||
, exactDeps ? false
|
||||
, tools ? {}
|
||||
, packageSetupDeps ? true
|
||||
, enableDWARF ? false
|
||||
, ... } @ args:
|
||||
|
||||
let
|
||||
@ -93,6 +94,7 @@ let
|
||||
postInstall = lib.optionalString withHoogle' ''
|
||||
ln -s ${hoogleIndex}/bin/hoogle $out/bin
|
||||
'';
|
||||
inherit enableDWARF;
|
||||
};
|
||||
|
||||
hoogleIndex = let
|
||||
|
@ -1,6 +1,12 @@
|
||||
This file contains a summary of changes to Haskell.nix and `nix-tools`
|
||||
that will impact users.
|
||||
|
||||
## Feb 22, 2021
|
||||
* Add `.debug` to build any component with DWARF dugug info on linux
|
||||
(ghc >=8.10.2).
|
||||
* Pass `enableDWARF` to `shellFor` for to get a shell where all the
|
||||
components are the `.debug` ones.
|
||||
|
||||
## Feb 18, 2021
|
||||
* `ghcOptions` has been moved from package and is now a list of strings.
|
||||
old: packages.x.package.ghcOptions = "someGHCoption";
|
||||
|
@ -9,6 +9,7 @@
|
||||
, useLLVM, llvmPackages
|
||||
, targetCC
|
||||
, enableIntegerSimple, targetGmp
|
||||
, enableDWARF, elfutils
|
||||
, ncurses, targetLibffi, libiconv
|
||||
, disableLargeAddressSpace
|
||||
, buildMK
|
||||
@ -112,7 +113,11 @@ stdenv.mkDerivation (rec {
|
||||
"CFLAGS=-fuse-ld=gold"
|
||||
"CONF_GCC_LINKER_OPTS_STAGE1=-fuse-ld=gold"
|
||||
"CONF_GCC_LINKER_OPTS_STAGE2=-fuse-ld=gold"
|
||||
] ;
|
||||
] ++ lib.optionals enableDWARF [
|
||||
"--enable-dwarf-unwind"
|
||||
"--with-libdw-includes=${lib.getDev elfutils}/include"
|
||||
"--with-libdw-libraries=${lib.getLib elfutils}/lib"
|
||||
];
|
||||
|
||||
outputs = [ "out" ];
|
||||
phases = [ "unpackPhase" "patchPhase" ]
|
||||
|
@ -3,11 +3,12 @@
|
||||
# haskell.nix ships its own version of the ghc expression as it needs more
|
||||
# control over the expression to isolate it against varying <nixpkgs> and
|
||||
# allow us to customize it to the way haskell.nix works.
|
||||
let self =
|
||||
{ stdenv, lib, haskell-nix, targetPackages
|
||||
|
||||
# build-tools
|
||||
, bootPkgs
|
||||
, autoconf, automake, coreutils, fetchurl, fetchpatch, perl, python3, m4, sphinx, numactl
|
||||
, autoconf, automake, coreutils, fetchurl, fetchpatch, perl, python3, m4, sphinx, numactl, elfutils
|
||||
, autoreconfHook
|
||||
, bash
|
||||
|
||||
@ -37,6 +38,8 @@
|
||||
|
||||
, enableLibraryProfiling ? true
|
||||
|
||||
, enableDWARF ? false
|
||||
|
||||
, # Whether to build terminfo. Musl fails to build terminfo as ncurses seems to be linked to glibc
|
||||
enableTerminfo ? !stdenv.targetPlatform.isWindows && !stdenv.targetPlatform.isMusl
|
||||
|
||||
@ -59,7 +62,7 @@
|
||||
|
||||
# extra values we want to have available as passthru values.
|
||||
, extra-passthru ? {}
|
||||
}:
|
||||
}@args:
|
||||
|
||||
assert !enableIntegerSimple -> gmp != null;
|
||||
|
||||
@ -103,6 +106,9 @@ let
|
||||
'' + lib.optionalString enableRelocatedStaticLibs ''
|
||||
GhcLibHcOpts += -fPIC
|
||||
GhcRtsHcOpts += -fPIC
|
||||
'' + lib.optionalString enableDWARF ''
|
||||
GhcLibHcOpts += -g3
|
||||
GhcRtsHcOpts += -g3
|
||||
'' + lib.optionalString targetPlatform.useAndroidPrebuilt ''
|
||||
EXTRA_CC_OPTS += -std=gnu99
|
||||
'' + lib.optionalString (!enableTerminfo) ''
|
||||
@ -149,6 +155,7 @@ let
|
||||
useLLVM llvmPackages
|
||||
targetCC
|
||||
enableIntegerSimple targetGmp
|
||||
enableDWARF elfutils
|
||||
ncurses targetLibffi libiconv
|
||||
disableLargeAddressSpace
|
||||
buildMK
|
||||
@ -315,6 +322,12 @@ stdenv.mkDerivation (rec {
|
||||
|
||||
# Used to detect non haskell-nix compilers (accidental use of nixpkgs compilers can lead to unexpected errors)
|
||||
isHaskellNixCompiler = true;
|
||||
|
||||
# The same GHC, but with debug enabled (if it can be)
|
||||
dwarf = lib.makeOverridable self (args // {
|
||||
enableDWARF = stdenv.targetPlatform.isLinux
|
||||
&& builtins.compareVersions ghc-version "8.10.2" >= 0;
|
||||
});
|
||||
} // extra-passthru;
|
||||
|
||||
meta = {
|
||||
@ -328,4 +341,5 @@ stdenv.mkDerivation (rec {
|
||||
dontStrip = true;
|
||||
dontPatchELF = true;
|
||||
noAuditTmpdir = true;
|
||||
})
|
||||
});
|
||||
in self
|
||||
|
@ -21,7 +21,9 @@ final: prev: with prev;
|
||||
&& !lib.hasPrefix "ghcjs" name
|
||||
&& !lib.hasSuffix "Binary" name;
|
||||
overrideCompiler = compiler:
|
||||
(compiler.override ghcPkgOverrides).overrideAttrs ghcDrvOverrides;
|
||||
((compiler.override ghcPkgOverrides).overrideAttrs ghcDrvOverrides) // {
|
||||
dwarf = overrideCompiler compiler.dwarf;
|
||||
};
|
||||
in
|
||||
lib.recursiveUpdate prev.haskell-nix {
|
||||
compiler = lib.mapAttrs (_name: overrideCompiler)
|
||||
|
4
test/cabal-simple-debug/Main.hs
Normal file
4
test/cabal-simple-debug/Main.hs
Normal file
@ -0,0 +1,4 @@
|
||||
module Main where
|
||||
|
||||
main :: IO ()
|
||||
main = putStrLn "Hello, Haskell!"
|
2
test/cabal-simple-debug/Setup.hs
Normal file
2
test/cabal-simple-debug/Setup.hs
Normal file
@ -0,0 +1,2 @@
|
||||
import Distribution.Simple
|
||||
main = defaultMain
|
37
test/cabal-simple-debug/cabal-simple.cabal
Normal file
37
test/cabal-simple-debug/cabal-simple.cabal
Normal file
@ -0,0 +1,37 @@
|
||||
cabal-version: >=1.10
|
||||
-- Initial package description 'cabal-simple.cabal' generated by 'cabal
|
||||
-- init'. For further documentation, see
|
||||
-- http://haskell.org/cabal/users-guide/
|
||||
|
||||
name: cabal-simple
|
||||
version: 0.1.0.0
|
||||
-- synopsis:
|
||||
-- description:
|
||||
-- bug-reports:
|
||||
license: PublicDomain
|
||||
author: Rodney Lorrimar
|
||||
maintainer: rodney.lorrimar@iohk.io
|
||||
-- category:
|
||||
build-type: Simple
|
||||
|
||||
library
|
||||
-- exposed-modules:
|
||||
-- other-modules:
|
||||
-- other-extensions:
|
||||
build-depends: base
|
||||
, extra
|
||||
, safe
|
||||
, aeson
|
||||
-- hs-source-dirs:
|
||||
default-language: Haskell2010
|
||||
|
||||
executable cabal-simple
|
||||
main-is: Main.hs
|
||||
-- other-modules:
|
||||
-- other-extensions:
|
||||
build-depends: base
|
||||
, cabal-simple
|
||||
, extra
|
||||
, optparse-applicative
|
||||
-- hs-source-dirs:
|
||||
default-language: Haskell2010
|
47
test/cabal-simple-debug/default.nix
Normal file
47
test/cabal-simple-debug/default.nix
Normal file
@ -0,0 +1,47 @@
|
||||
# Test a package set
|
||||
{ stdenv, lib, util, cabalProject', haskellLib, recurseIntoAttrs, testSrc, compiler-nix-name, dwarfdump }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
project = cabalProject' {
|
||||
inherit compiler-nix-name;
|
||||
src = testSrc "cabal-simple-debug";
|
||||
};
|
||||
|
||||
packages = project.hsPkgs;
|
||||
|
||||
in recurseIntoAttrs {
|
||||
ifdInputs = {
|
||||
inherit (project) plan-nix;
|
||||
};
|
||||
run = stdenv.mkDerivation {
|
||||
name = "cabal-simple-debug-test";
|
||||
|
||||
buildCommand = ''
|
||||
exe="${(packages.cabal-simple.components.exes.cabal-simple.dwarf).exePath}"
|
||||
|
||||
size=$(command stat --format '%s' "$exe")
|
||||
printf "size of executable $exe is $size. \n" >& 2
|
||||
|
||||
# fixme:
|
||||
printf "checking whether executable included DWARF debug info... " >& 2
|
||||
(${dwarfdump}/bin/dwarfdump $exe || true) | grep -c 'libraries/base/[A-Za-z0-9/]*\.hs'
|
||||
(${dwarfdump}/bin/dwarfdump $exe || true) | grep -c '\/Main\.hs'
|
||||
|
||||
touch $out
|
||||
'';
|
||||
|
||||
meta = {
|
||||
platforms = platforms.all;
|
||||
# DWARF only works on linux with GHC 8.10.2 and newer
|
||||
disabled = compiler-nix-name == "ghc865" || compiler-nix-name == "ghc884"
|
||||
|| !stdenv.hostPlatform.isLinux || haskellLib.isCrossHost || stdenv.hostPlatform.isMusl;
|
||||
};
|
||||
|
||||
passthru = {
|
||||
# Used for debugging with nix repl
|
||||
inherit project packages;
|
||||
};
|
||||
};
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
{ haskellNix ? import ../default.nix { inherit checkMaterialization; }
|
||||
, pkgs ? import nixpkgs nixpkgsArgs
|
||||
, nixpkgs ? haskellNix.sources.nixpkgs
|
||||
, nixpkgs ? haskellNix.sources.nixpkgs-unstable
|
||||
, nixpkgsArgs ? haskellNix.nixpkgsArgs
|
||||
, ifdLevel ? 1000
|
||||
, compiler-nix-name
|
||||
@ -212,6 +212,10 @@ let
|
||||
# githash runs git from TH code and this needs a cross compiled git exe
|
||||
# to work correctly. Cross compiling git is currently brocken.
|
||||
githash = haskell-nix.callPackage ./githash { inherit compiler-nix-name; testSrc = testSrcWithGitDir; };
|
||||
} // lib.optionalAttrs (
|
||||
stdenv.hostPlatform.isLinux && !pkgs.haskell-nix.haskellLib.isCrossHost && !stdenv.hostPlatform.isMusl
|
||||
&& !(__elem compiler-nix-name ["ghc865" "ghc884"])) {
|
||||
cabal-simple-debug = callTest ./cabal-simple-debug { inherit util compiler-nix-name; };
|
||||
};
|
||||
|
||||
# This is the same as allTests, but filter out all the key/vaules from the
|
||||
|
Loading…
Reference in New Issue
Block a user