Repository: spack/spack

Issue:
install libpython.py when installing python
 install libpython.py when installing python

### Rationale

Installing this gdb extension would dramatically improve the debugging experience  with python with C extensions.

### Description

libpython.py is a gdb extension written by the python core developers which provides several helper functions for debugging python c extensions using gdb such as `py-bt` which translates the full C backtrace in to a python readable back trace.  Right now we don't install it. According to the documentation, it is generated when the python library is built.

https://devguide.python.org/gdb/

### Additional information

There are a few other packages which provide gdb extensions such as gcc's libstdc++, so an appealing way to solve this would be to make gdb extendable and have python extend gdb to provide this file, however, this would create a circular dependency between gdb and python since gdb depends on python to provide the embedded interpreter within gdb and this file is meaningless without the gdb and the gdb module.  I'm not sure how to resolve this.

@adamjstewart ping'ing you as requested.  I'm not in a hurry to fix this before the new year.


### General information

- [X] I have run `spack --version` and reported the version of Spack

0.16.0-220-cf37e9276

- [X] I have searched the issues of this repo and believe this is not a duplicate




Discussion:
@robertu94 I looked into this. According to the docs you linked, it seems like the only way to activate Python support is to set `add-auto-load-safe-path` in your `~/.gdbinit`, correct? We try to avoid modifying any files outside of the Spack installation prefix in order to make Spack easy to uninstall. Unless `gdb` has some default `gdbinit` file we can overwrite (I couldn't find one), the best we can do is to make sure that the `python` install copies `python-gdb.py` to the installation prefix so you can set it manually. Spack doesn't yet have a "caveats" thing like Homebrew does, although there are a couple PRs to add it. We could add a `tty.info` telling you where to set it, but it won't be displayed unless someone builds with `--verbose`.
@adamjstewart I'm okay with having to modify the file myself to enable this.  I just need the file to be installed with the spack prefix in the first place.

On a side note, it is [also possible](https://sourceware.org/gdb/onlinedocs/gdb/Auto_002dloading-safe-path.html) to set a spack-built gdb's default auto-load-safe-path at configure time for gdb using `--with-auto-load-dir`, but I think the default safe paths are `$debugdir` and `$datadir` which I believe default to `$prefix/lib/debug` and `$prefix/share/gdb` respectively.  I'd have to experiment more to confirm this.
That looks promising! Any thoughts on the best place to put `python-gdb.py`? Maybe in `$prefix/share/gdb` if there isn't already a default location in the Makefile somewhere. I'll try to put together a PR to make all of this work and let you test it.
According to [this](https://stackoverflow.com/questions/40391404/loading-python-support-in-gdb) it looks like the `$prefix/bin` directory is a good choice.
pyenv does the same thing: https://github.com/pyenv/pyenv/pull/1289

Resolving patch:
diff --git a/var/spack/repos/builtin/packages/gdb/package.py b/var/spack/repos/builtin/packages/gdb/package.py
--- a/var/spack/repos/builtin/packages/gdb/package.py
+++ b/var/spack/repos/builtin/packages/gdb/package.py
@@ -4,6 +4,7 @@
 # SPDX-License-Identifier: (Apache-2.0 OR MIT)
 
 from spack import *
+import os
 
 
 class Gdb(AutotoolsPackage, GNUMirrorPackage):
@@ -15,22 +16,25 @@ class Gdb(AutotoolsPackage, GNUMirrorPackage):
     homepage = "https://www.gnu.org/software/gdb"
     gnu_mirror_path = "gdb/gdb-7.10.tar.gz"
 
-    version('9.2', sha256='38ef247d41ba7cc3f6f93a612a78bab9484de9accecbe3b0150a3c0391a3faf0')
-    version('9.1', sha256='fcda54d4f35bc53fb24b50009a71ca98410d71ff2620942e3c829a7f5d614252')
-    version('8.3.1', sha256='26ce655216cd03f4611518a7a1c31d80ec8e884c16715e9ba8b436822e51434b')
-    version('8.3', sha256='b2266ec592440d0eec18ee1790f8558b3b8a2845b76cc83a872e39b501ce8a28')
-    version('8.2.1', sha256='0107985f1edb8dddef6cdd68a4f4e419f5fec0f488cc204f0b7d482c0c6c9282')
-    version('8.2', sha256='847e4b65e5a7b872e86019dd59659029e2b06cae962e0ef345f169dcb4b851b8')
-    version('8.1', sha256='e54a2322da050e4b00785370a282b9b8f0b25861ec7cfbbce0115e253eea910e')
-    version('8.0.1', sha256='52017d33cab5b6a92455a1a904046d075357abf24153470178c0aadca2d479c5')
-    version('8.0', sha256='8968a19e14e176ee026f0ca777657c43456514ad41bb2bc7273e8c4219555ac9')
+    maintainers = ['robertu94']
+
+    version('10.1',   sha256='f12f388b99e1408c01308c3f753313fafa45517740c81ab7ed0d511b13e2cf55')
+    version('9.2',    sha256='38ef247d41ba7cc3f6f93a612a78bab9484de9accecbe3b0150a3c0391a3faf0')
+    version('9.1',    sha256='fcda54d4f35bc53fb24b50009a71ca98410d71ff2620942e3c829a7f5d614252')
+    version('8.3.1',  sha256='26ce655216cd03f4611518a7a1c31d80ec8e884c16715e9ba8b436822e51434b')
+    version('8.3',    sha256='b2266ec592440d0eec18ee1790f8558b3b8a2845b76cc83a872e39b501ce8a28')
+    version('8.2.1',  sha256='0107985f1edb8dddef6cdd68a4f4e419f5fec0f488cc204f0b7d482c0c6c9282')
+    version('8.2',    sha256='847e4b65e5a7b872e86019dd59659029e2b06cae962e0ef345f169dcb4b851b8')
+    version('8.1',    sha256='e54a2322da050e4b00785370a282b9b8f0b25861ec7cfbbce0115e253eea910e')
+    version('8.0.1',  sha256='52017d33cab5b6a92455a1a904046d075357abf24153470178c0aadca2d479c5')
+    version('8.0',    sha256='8968a19e14e176ee026f0ca777657c43456514ad41bb2bc7273e8c4219555ac9')
     version('7.12.1', sha256='142057eacecfb929d52b561eb47a1103c7d504cec3f659dd8a5ae7bc378f7e77')
-    version('7.11', sha256='9382f5534aa0754169e1e09b5f1a3b77d1fa8c59c1e57617e06af37cb29c669a')
+    version('7.11',   sha256='9382f5534aa0754169e1e09b5f1a3b77d1fa8c59c1e57617e06af37cb29c669a')
     version('7.10.1', sha256='ff14f8050e6484508c73cbfa63731e57901478490ca1672dc0b5e2b03f6af622')
-    version('7.10', sha256='50690e6d6b7917a6544190ec9401eaafb555e3cef8981709ea9870296c383ce5')
-    version('7.9.1', sha256='4994ad986726ac4128a6f1bd8020cd672e9a92aa76b80736563ef992992764ef')
-    version('7.9', sha256='d282508cb7df0cb8b2cf659032ce1bede7b5725796e3ac90f3cd9d65844a65f2')
-    version('7.8.2', sha256='fd9a9784ca24528aac8a4e6b8d7ae7e8cf0784e128cd67a185c986deaf6b9929')
+    version('7.10',   sha256='50690e6d6b7917a6544190ec9401eaafb555e3cef8981709ea9870296c383ce5')
+    version('7.9.1',  sha256='4994ad986726ac4128a6f1bd8020cd672e9a92aa76b80736563ef992992764ef')
+    version('7.9',    sha256='d282508cb7df0cb8b2cf659032ce1bede7b5725796e3ac90f3cd9d65844a65f2')
+    version('7.8.2',  sha256='fd9a9784ca24528aac8a4e6b8d7ae7e8cf0784e128cd67a185c986deaf6b9929')
 
     variant('python', default=True, description='Compile with Python support')
     variant('xz', default=True, description='Compile with lzma support')
@@ -45,7 +49,7 @@ class Gdb(AutotoolsPackage, GNUMirrorPackage):
     depends_on('texinfo', type='build')
 
     # Optional dependencies
-    depends_on('python', when='+python')
+    depends_on('python+debug', when='+python', type=('build', 'link', 'run'))
     depends_on('xz', when='+xz')
     depends_on('source-highlight', when='+source-highlight')
     depends_on('ncurses', when='+tui')
@@ -53,7 +57,10 @@ class Gdb(AutotoolsPackage, GNUMirrorPackage):
     build_directory = 'spack-build'
 
     def configure_args(self):
-        args = []
+        args = [
+            '--with-system-gdbinit={0}'.format(self.prefix.etc.gdbinit)
+        ]
+
         if '+python' in self.spec:
             args.append('--with-python')
             args.append('LDFLAGS={0}'.format(
@@ -75,3 +82,12 @@ def configure_args(self):
             args.append('--enable-tui')
 
         return args
+
+    @run_after('install')
+    def gdbinit(self):
+        if '+python' in self.spec:
+            tool = self.spec['python'].command.path + '-gdb.py'
+            if os.path.exists(tool):
+                mkdir(self.prefix.etc)
+                with open(self.prefix.etc.gdbinit, 'w') as gdbinit:
+                    gdbinit.write('add-auto-load-safe-path {0}\n'.format(tool))
diff --git a/var/spack/repos/builtin/packages/python/package.py b/var/spack/repos/builtin/packages/python/package.py
--- a/var/spack/repos/builtin/packages/python/package.py
+++ b/var/spack/repos/builtin/packages/python/package.py
@@ -619,6 +619,13 @@ def symlink(self):
             os.symlink(os.path.join(prefix.bin, 'python3-config'),
                        os.path.join(prefix.bin, 'python-config'))
 
+    @run_after('install')
+    def install_python_gdb(self):
+        # https://devguide.python.org/gdb/
+        src = os.path.join('Tools', 'gdb', 'libpython.py')
+        if os.path.exists(src):
+            install(src, self.command.path + '-gdb.py')
+
     @run_after('install')
     @on_package_attributes(run_tests=True)
     def import_tests(self):


Test patch: