Nixos:我如何获得 python 以及包中包含的调试信息?

Nixos: How do I get get a python with debug info included with packages?

我正在尝试在 NixOS 上进行 cython 调试。我可以在 nix-shell 中轻松安装 cython(为简单起见而选择),如下所示:

$ nix-shell -p 'python27.withPackages( p: [ p.cython ])'

$ cat /nix/store/s0w3phb2saixi0a9bzk8pjbczjaz8d7r-python-2.7.14-env/bin/python
#! /nix/store/jgw8hxx7wzkyhb2dr9hwsd9h2caaasdc-bash-4.4-p12/bin/bash -e
export PYTHONHOME="/nix/store/s0w3phb2saixi0a9bzk8pjbczjaz8d7r-python-2.7.14-env"
export PYTHONNOUSERSITE="true"
exec "/nix/store/i3bx1iw2d0i3vh9sa1nf92ynlrw324w8-python-2.7.14/bin/python"  "${extraFlagsArray[@]}" "$@"

然后我们做一个正常的 nix-shell 只是 python 看看我们得到什么版本的 python。

[henry@bollum:~/Projects/eyeserver/nixshell]$ nix-shell -p 'python27'
$ which python
/nix/store/i3bx1iw2d0i3vh9sa1nf92ynlrw324w8-python-2.7.14/bin/python
#          ^^^^^^^
#          non-debug

一切都很好——我们在两种情况下都得到了非调试 python。如果我们 gdb 它,我们得到(没有找到调试符号)。请参阅最后一行。

$ gdb 
/nix/store/i3bx1iw2d0i3vh9sa1nf92ynlrw324w8-python-2.7.14/bin/python
GNU gdb (GDB) 8.0.1
Copyright (C) 2017 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later 
<http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-unknown-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from /nix/store/i3bx1iw2d0i3vh9sa1nf92ynlrw324w8-python-2.7.14/bin/python...(no debugging symbols found)...done.

当我们单独使用 python 上的 enableDebugging 时,我们会得到不同的结果。 $ nix-shell -p 'enableDebugging python27'

$ which python
/nix/store/a4wd8mcpqr54hmw0x95fw8fhvk8avh5a-python-2.7.14/bin/python
#          ^^^^^^
#          debug

$ gdb 
/nix/store/a4wd8mcpqr54hmw0x95fw8fhvk8avh5a-python-2.7.14/bin/python
GNU gdb (GDB) 8.0.1
...
Reading symbols from /nix/store/a4wd8mcpqr54hmw0x95fw8fhvk8avh5a-python-2.7.14/bin/python...done.

当我们尝试使用包含的 cython(或任何其他包)执行此操作时,问题就来了。
$ nix-shell -p '(enableDebugging python27).withPackages( p: [ p.cython ])'

$ cat `which python`
#! /nix/store/jgw8hxx7wzkyhb2dr9hwsd9h2caaasdc-bash-4.4-p12/bin/bash -e
export PYTHONHOME="/nix/store/s0w3phb2saixi0a9bzk8pjbczjaz8d7r-python-2.7.14-env"
export PYTHONNOUSERSITE="true"
exec "/nix/store/i3bx1iw2d0i3vh9sa1nf92ynlrw324w8-python-2.7.14/bin/python"  "${extraFlagsArray[@]}" "$@"
#                ^^^^^^^
#                non-debug
$ gdb /nix/store/i3bx1iw2d0i3vh9sa1nf92ynlrw324w8-python-2.7.14/bin/python
GNU gdb (GDB) 8.0.1
...
Reading symbols from /nix/store/i3bx1iw2d0i3vh9sa1nf92ynlrw324w8-python-2.7.14/bin/python...(no debugging symbols found)...done.
(gdb) 
quit

环境中 python 的版本现在是非调试版本,尝试调试它会很可怕(找不到调试符号)。这使得 gdb 对于调试 cython 程序的用处大大降低。

解决方案

with import <nixpkgs> {};

let
   self = enableDebugging python;
in [ gdb ((python.override{inherit self;}).withPackages(ps: with ps; [ cython ])) ]

包装器中引用的可执行文件现在具有调试符号。

背景

如果我们查看 pkgs/all-packages.nix,我们会看到 enableDebugging 函数的实现:

enableDebugging = pkg: pkg.override { stdenv = stdenvAdapters.keepDebugInfo pkg.stdenv; };

它覆盖单个推导以使用不同的 stdenv。在您的情况下,您想覆盖 Python 解释器,它依赖于使用 python.withPackages.

获得的推导

您对 enableDebugging python 的尝试是正确的,但是,python.withPackages 使用了对 python 的引用,这也需要更新。

@fridh 回答需要额外的小代码才能使其可用。

基本上你需要一个 shell.nix 这样的:

with import <nixpkgs> {};

let
   python = enableDebugging pkgs.python;
in
  stdenv.mkDerivation {
    name = "test";
    buildInputs = [ python ];
  }

然后当你输入nix-shell时,你可以运行 gdb -p <pid of python process>.

请注意,这只会调试 Python 解释器本身。这不会启用 gdb 的 python 扩展,允许您调试应用程序级别 python 代码。

enableDebugging 也不会传播到依赖项。如果您希望启用这些调试符号,则每个依赖项都需要自己的 enableDebugging。是否应该有递归启用调试的功能?