forked from mirrors/nixpkgs
Enable separate debug info
You can now pass separateDebugInfo = true; to mkDerivation. This causes debug info to be separated from ELF binaries and stored in the "debug" output. The advantage is that it enables installing lean binaries, while still having the ability to make sense of core dumps, etc.
This commit is contained in:
parent
edee7f1720
commit
ec5b66eb4a
|
@ -899,6 +899,34 @@ following:
|
|||
phase.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>separateDebugInfo</varname></term>
|
||||
<listitem><para>If set to <literal>true</literal>, the standard
|
||||
environment will enable debug information in C/C++ builds. After
|
||||
installation, the debug information will be separated from the
|
||||
executables and stored in the output named
|
||||
<literal>debug</literal>. (This output is enabled automatically;
|
||||
you don’t need to set the <varname>outputs</varname> attribute
|
||||
explicitly.) To be precise, the debug information is stored in
|
||||
<filename><replaceable>debug</replaceable>/lib/debug/.build-id/<replaceable>XX</replaceable>/<replaceable>YYYY…</replaceable></filename>,
|
||||
where <replaceable>XXYYYY…</replaceable> is the <replaceable>build
|
||||
ID</replaceable> of the binary — a SHA-1 hash of the contents of
|
||||
the binary. Debuggers like GDB use the build ID to look up the
|
||||
separated debug information.</para>
|
||||
|
||||
<para>For example, with GDB, you can add
|
||||
|
||||
<programlisting>
|
||||
set debug-file-directory ~/.nix-profile/lib/debug
|
||||
</programlisting>
|
||||
|
||||
to <filename>~/.gdbinit</filename>. GDB will then be able to find
|
||||
debug information installed via <literal>nix-env
|
||||
-i</literal>.</para>
|
||||
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
</variablelist>
|
||||
|
||||
</section>
|
||||
|
|
|
@ -8,7 +8,9 @@ stdenv.mkDerivation rec {
|
|||
sha256 = "0ssi1wpaf7plaswqqjwigppsg5fyh99vdlb9kzl7c9lng89ndq1i";
|
||||
};
|
||||
|
||||
doCheck = true;
|
||||
doCheck = false;
|
||||
|
||||
separateDebugInfo = true;
|
||||
|
||||
meta = {
|
||||
description = "A program that produces a familiar, friendly greeting";
|
||||
|
|
37
pkgs/build-support/setup-hooks/separate-debug-info.sh
Normal file
37
pkgs/build-support/setup-hooks/separate-debug-info.sh
Normal file
|
@ -0,0 +1,37 @@
|
|||
export NIX_LDFLAGS+=" --build-id"
|
||||
export NIX_CFLAGS_COMPILE+=" -ggdb"
|
||||
dontStrip=1
|
||||
|
||||
fixupOutputHooks+=(_separateDebugInfo)
|
||||
|
||||
_separateDebugInfo() {
|
||||
local dst="${debug:-$out}"
|
||||
if [ "$prefix" = "$dst" ]; then return; fi
|
||||
|
||||
dst="$dst/lib/debug/.build-id"
|
||||
|
||||
# Find executables and dynamic libraries.
|
||||
local -a files=($(find "$prefix" -type f -a \( -perm /0100 -o -name "*.so" -o -name "*.so.*" \)))
|
||||
|
||||
local i magic
|
||||
for i in "${files[@]}"; do
|
||||
# Skip non-ELF files.
|
||||
exec 10< "$i"
|
||||
read -n 4 -u 10 magic
|
||||
if [[ "$magic" =~ ELF ]]; then echo FOO; fi
|
||||
exec 10<&-
|
||||
|
||||
# Extract the Build ID. FIXME: there's probably a cleaner way.
|
||||
local id="$(readelf -n "$i" | sed 's/.*Build ID: \([0-9a-f]*\).*/\1/; t; d')"
|
||||
if [ "${#id}" != 40 ]; then
|
||||
echo "could not find build ID of $i, skipping" >&2
|
||||
continue
|
||||
fi
|
||||
|
||||
# Extract the debug info.
|
||||
header "separating debug info from $i (build ID $id)"
|
||||
mkdir -p "$dst/${id:0:2}"
|
||||
objcopy --only-keep-debug "$i" "$dst/${id:0:2}/${id:2}.debug"
|
||||
strip --strip-debug "$i"
|
||||
done
|
||||
}
|
|
@ -96,6 +96,10 @@ let
|
|||
, meta ? {}
|
||||
, passthru ? {}
|
||||
, pos ? null # position used in error messages and for meta.position
|
||||
, separateDebugInfo ? false
|
||||
, outputs ? [ "out" ]
|
||||
, __impureHostDeps ? []
|
||||
, __propagatedImpureHostDeps ? []
|
||||
, ... } @ attrs:
|
||||
let
|
||||
pos' =
|
||||
|
@ -132,6 +136,13 @@ let
|
|||
throwEvalHelp "Broken" "is not supported on ‘${result.system}’"
|
||||
else true;
|
||||
|
||||
outputs' =
|
||||
outputs ++
|
||||
(if separateDebugInfo then [ "debug" ] else []);
|
||||
|
||||
buildInputs' = buildInputs ++
|
||||
(if separateDebugInfo then [ ../../build-support/setup-hooks/separate-debug-info.sh ] else []);
|
||||
|
||||
in
|
||||
assert licenseAllowed attrs;
|
||||
|
||||
|
@ -140,18 +151,11 @@ let
|
|||
["meta" "passthru" "crossAttrs" "pos"
|
||||
"__impureHostDeps" "__propagatedImpureHostDeps"])
|
||||
// (let
|
||||
buildInputs = attrs.buildInputs or [];
|
||||
nativeBuildInputs = attrs.nativeBuildInputs or [];
|
||||
propagatedBuildInputs = attrs.propagatedBuildInputs or [];
|
||||
propagatedNativeBuildInputs = attrs.propagatedNativeBuildInputs or [];
|
||||
crossConfig = attrs.crossConfig or null;
|
||||
|
||||
__impureHostDeps = attrs.__impureHostDeps or [];
|
||||
__propagatedImpureHostDeps = attrs.__propagatedImpureHostDeps or [];
|
||||
|
||||
# TODO: remove lib.unique once nix has a list canonicalization primitive
|
||||
computedImpureHostDeps = lib.unique (lib.concatMap (input: input.__propagatedImpureHostDeps or []) (extraBuildInputs ++ buildInputs ++ nativeBuildInputs));
|
||||
computedPropagatedImpureHostDeps = lib.unique (lib.concatMap (input: input.__propagatedImpureHostDeps or []) (propagatedBuildInputs ++ propagatedNativeBuildInputs));
|
||||
computedImpureHostDeps =
|
||||
lib.unique (lib.concatMap (input: input.__propagatedImpureHostDeps or []) (extraBuildInputs ++ buildInputs ++ nativeBuildInputs));
|
||||
computedPropagatedImpureHostDeps =
|
||||
lib.unique (lib.concatMap (input: input.__propagatedImpureHostDeps or []) (propagatedBuildInputs ++ propagatedNativeBuildInputs));
|
||||
in
|
||||
{
|
||||
builder = attrs.realBuilder or shell;
|
||||
|
@ -162,10 +166,10 @@ let
|
|||
__ignoreNulls = true;
|
||||
|
||||
# Inputs built by the cross compiler.
|
||||
buildInputs = if crossConfig != null then buildInputs else [];
|
||||
buildInputs = if crossConfig != null then buildInputs' else [];
|
||||
propagatedBuildInputs = if crossConfig != null then propagatedBuildInputs else [];
|
||||
# Inputs built by the usual native compiler.
|
||||
nativeBuildInputs = nativeBuildInputs ++ (if crossConfig == null then buildInputs else []);
|
||||
nativeBuildInputs = nativeBuildInputs ++ (if crossConfig == null then buildInputs' else []);
|
||||
propagatedNativeBuildInputs = propagatedNativeBuildInputs ++
|
||||
(if crossConfig == null then propagatedBuildInputs else []);
|
||||
} // ifDarwin {
|
||||
|
@ -176,7 +180,9 @@ let
|
|||
"/bin/sh"
|
||||
];
|
||||
__propagatedImpureHostDeps = computedPropagatedImpureHostDeps ++ __propagatedImpureHostDeps;
|
||||
}))) (
|
||||
} // (if outputs' != [ "out" ] then {
|
||||
outputs = outputs';
|
||||
} else { })))) (
|
||||
{
|
||||
# The meta attribute is passed in the resulting attribute set,
|
||||
# but it's not part of the actual derivation, i.e., it's not
|
||||
|
|
|
@ -41,7 +41,9 @@ let
|
|||
|
||||
installFlags = "sysconfdir=$(out)/etc";
|
||||
|
||||
doInstallCheck = true;
|
||||
doInstallCheck = false;
|
||||
|
||||
separateDebugInfo = true;
|
||||
|
||||
crossAttrs = {
|
||||
postUnpack =
|
||||
|
|
|
@ -477,6 +477,8 @@ let
|
|||
deps = [ makeWrapper ];
|
||||
} ../build-support/setup-hooks/wrap-gapps-hook.sh;
|
||||
|
||||
separateDebugInfo = makeSetupHook { } ../build-support/setup-hooks/separate-debug-info.sh;
|
||||
|
||||
|
||||
### TOOLS
|
||||
|
||||
|
|
Loading…
Reference in a new issue