Contents

GDB

< Gt r = “12”/>: brew maintainer < gt r = “10”/> needs to merge upstream, and from the end of the article, it is obviously impossible to merge. My PR will not be lost there, just download the patch from < gt r = “11”/> and apply it yourself.

Python is faith. Versions are also part of faith.

Just kidding. The reason why I have to compile it myself is because a gdb plugin does not support Py2.x. What’s more, 3 is more to my taste than 2 in some details. The brew formula only supports the optional link brew version of python2, and there is no 3, so I have to study it myself.

In fact, what surprised me the most is that some mainstream distributions (such as Ubuntu) have linked gdb to python3, but no one has researched it for several years, no one has mentioned it, and I can’t find it online - when will the mac be so diao?

The version used at the time of writing this article is < gt r = “13”/>.

Check wrong

If you don’t want to see it, you can skip to the next chapter on how to fix the error and compile successfully.

I first checked the formula with < gt r = “14”/>, and found that it specifies < gt r = “15”/> to implement the python linked to brew. I tried to add a 3 at the end. Report such an error.

 checking whether to use python... /usr/local/opt/python3
 checking for python2.7... no
 checking for python2.6... no
 checking for python2.5... no
 checking for python2.4... no
 configure: error: no usable python found at /usr/local/opt/python3
 make[1]: *** [configure-gdb] Error 1
 make: *** [all] Error 2

Tell me that py3 is not available. This error is generated during configure, and configure is generated with autoconf [^ 1]. So I searched for “no usable python” in configure.ac script and located it in the following position.

  if test "${have_libpython}" = no; then
    case "${with_python}" in
    yes)
      AC_MSG_ERROR([python is missing or unusable])
      ;;
    auto)
      AC_MSG_WARN([python is missing or unusable; some features may be unavailable.])
      ;;
    *)
      AC_MSG_ERROR([no usable python found at ${with_python}])
      ;;
    esac

Since < gt r = “16”/> is the parameter we just specified, then < gt r = “17”/> is the available python path detected by the system.

Scroll up a little further and find that the location where this variable is set is on line 895, as a test result to test whether the compilation parameters obtained from python-config are available,

    case "${python_version}" in
    python*)
      AC_TRY_LIBPYTHON(${python_version}, have_libpython,
                       ${python_includes}, ${python_libs})
      ;;

The source of the compile parameters is on line 838 of the configure.ac.

    python_includes=`${python_prog} ${srcdir}/python/python-config.py --includes`
    python_libs=`${python_prog} ${srcdir}/python/python-config.py --ldflags`
    python_prefix=`${python_prog} ${srcdir}/python/python-config.py --exec-prefix`

Comparing its results with the original flags, it is still a little different.

$ python3 python/python-config.py --ldflags
-L/usr/local/opt/python3/Frameworks/Python.framework/Versions/3.6/lib/python3.6/config-3.6m-darwin -ldl -framework CoreFoundation -lpython3.6m -Wl,-stack_size,1000000 -framework CoreFoundation Python.framework/Versions/3.6/Python

$ python3-config --ldflags
-L/usr/local/opt/python3/Frameworks/Python.framework/Versions/3.6/lib/python3.6/config-3.6m-darwin -lpython3.6m -ldl -framework CoreFoundation
# 下面是ubuntu的输出
~$ python3-config --ldflags
-L/usr/lib/python3.5/config-3.5m-x86_64-linux-gnu -L/usr/lib -lpython3.5m -lpthread -ldl  -lutil -lm  -Xlinker -export-dynamic -Wl,-O1 -Wl,-Bsymbolic-functions

Forcibly replace this python-config with python’s own, compile it, and just give gdb’s formula < gt r = “18”/>. Later, I compared the formula written by gdb itself with the official python-config of python. Except for the details, most of them are similar. There is only one sentence.

@@ -72,7 +72,7 @@ for opt in opt_flags:
                     libs.insert(0, '-L' + getvar('LIBPL'))
                 elif os.name == 'nt':
                     libs.insert(0, '-L' + sysconfig.PREFIX + '/libs')
-            if getvar('LINKFORSHARED') is not None:
+            if not getvar('PYTHONFRAMEWORK'):
                 libs.extend(getvar('LINKFORSHARED').split())
         print (to_unix_path(' '.join(libs)))

There is also a patch similar to [^ 2] on the Internet. Just delete these 10 and 11 lines. I don’t think it’s appropriate to not follow the official one.

Traceability

In fact, I am more interested in why two redundant codes are necessary to implement the same function? Why don’t you trust official tools? I have long heard that many distributions have already released gdb with python3 integration. The brew maintainer said: Wait for the upstream update. However, after so many years, the default is still python2.

So I came down from ppa and researched the source code of the ubuntu version of gdb, and found that in addition to src, there is also a folder patch. There is a python-config.patch in it, which is written in much the same way as my patch. (Surprise! The pioneer of history!) I went down to changelog [^ 3] to see which version added python3 support.

+  * debian/patches: Update for new upstream version
+    - Remove patches subsumed by new upstream version/tarball:
+      + ppc64le.diff
+      + hurd-new-RPC-reply-stub-functions.patch
+      + hurd-adapt-to-changed-MIG-output.patch
+      + hurd-adjust-to-startup-with-shell-changes.patch
+      + hurd-make-MIG-output-parsing-more-robust.patch
+      + kfreebsd_bug752390.diff
+      + restore-run.1.patch
+    - Adjust patches to work with new upstream version:
+      + gdb-fortran-main.patch: Update for upstream changes
+      + python-config.patch: Remove parts applied upstream
+
+  [ Héctor Orón Martínez ]
+  * Switch gdb to python3 (Closes: #752581)
+    + Add gdb-python2 package for use with python2-only scripts
+  * Enable babeltrace on supported arches
+
+  [ Samuel Bronson ]
+  * Make gdb-python2 provide gdb.
+  * Totally rewrite the NEWS entry about the Python changes.
+    + And split out most of the new text to README.python_switch.
+
+ -- Samuel Bronson <naesten@gmail.com>  Tue, 26 Aug 2014 15:34:03 -0400
+
 gdb (7.8-0ubuntu2) utopic; urgency=medium

Version 7.8-0ubuntu2. Remarks still: Modified the patch that was merged upstream. But why is it still .patch when merged upstream? Take a look at the beginning: debian/patches. 😯… Dare you have big eyebrows and big eyes, the code is still third-hand?

Let’s look at the debian code again, they have a dedicated < gt r = “19”/> service, from there you can find patches written by all debian contributors. So, the linux boss is not ubuntu, and in the end, don’t you still have to look at debian’s face? Here I only found the patches contained in a few release versions. The earliest version to add this patch is < gt r = “20”/>, you can see the time: 2013-08-14. It’s a year earlier than Ubuntu. It seems that Ubuntu is not very fast and bleeding-edge!

So what have gdb developers been doing all these years? In fact, they know faster than Hong Kong journalists. As early as December 2012, five days before Christmas, an ubuntu developer submitted a similar patch for gdb-7.5 on the mailing list. However! Why hasn’t this been merged? Check out the conversation on the mailing list [^ 4]:

From: Matthias Klose <doko at ubuntu dot com>
Date: Thu, 20 Dec 2012 17:13:14 +0100

Am 20.12.2012 16:59, schrieb Joel Brobecker:
> Can you tell us what problem you are trying to solve?

cross building in a multiarch environment, where the host libraries are
installed, and a <host>-python-config is shipped as part of the system python.
This <host>-python-config is a backport of http://bugs.python.org/issue16235
(not yet applied upstream).

==========
From: Joel Brobecker <brobecker at adacore dot com>
Date: Fri, 21 Dec 2012 11:57:21 +0400
I think that this was the plan, yes; but Doug Evans would probably
know more, as he is the main author of this code (I only fiddled
with it).

==========
From: Doug Evans <dje at google dot com>
Date: Fri, 21 Dec 2012 09:30:47 -0800

The patch is fine with me.
[The plan wasn't to shift and call the "real" python-config ... at the
time there was no real python-config for cross builds.]

==========
From: Joel Brobecker <brobecker at adacore dot com>
Date: Fri, 21 Dec 2012 21:50:59 +0400
Can we make this new behavior optional? The "real" python-config
is broken for several platforms, and having our own that we can
control was very convenient.

==========
From: Doug Evans <dje at google dot com>
Date: Sat, 22 Dec 2012 11:33:08 -0800
I certainly don't want to break your use-case.

I need to look at the patch again (but I probably won't get to it
until next week).

He shrank and waited for Lao Tzu to go to work on Monday. Note the time: Sat, 22 Dec. Well, Saturday. I’m counting, the 23rd, Sunday. 24! 25! 26! Christmas, three days, small, long, fake!

So in a happy and peaceful atmosphere, the bug was so forgotten (´・_・`)

Repair

By the way, there seems to be a sentence I didn’t say at the beginning… The bugs and fixes encountered in this article are only for the mac system (pro test 10.12.6). If you have been installing software with apt-get, it has already helped you Wipe your butt clean. What’s more, the python-config of mac is a python script, while the one under ubuntu is a shell script, and the code is generated, so even if you really want to change it, it is not a solution.

Put the following patch into a text file (eg < gt r = “21”/>), then put this file in the gdb source directory and run < gt r = “22”/>. Then compile normally. This file has not been changed in many versions, so it probably works.

diff --git a/gdb/python/python-config.py b/gdb/python/python-config.py
index c2b2969..554dac9 100644
--- a/gdb/python/python-config.py
+++ b/gdb/python/python-config.py
@@ -72,7 +72,7 @@ for opt in opt_flags:
                     libs.insert(0, '-L' + getvar('LIBPL'))
                 elif os.name == 'nt':
                     libs.insert(0, '-L' + sysconfig.PREFIX + '/libs')
-            if getvar('LINKFORSHARED') is not None:
+            if not getvar('PYTHONFRAMEWORK'):
                 libs.extend(getvar('LINKFORSHARED').split())
         print (to_unix_path(' '.join(libs)))

References