Package: python3-pybind11
Version: 2.9.1-1
Severity: normal
Tags: patch
Forwarded: https://github.com/pybind/pybind11/pull/3764

Until recently, the Python sysconfig module didn't know about Debian's
deb_system and posix_local schemes that were patched into
distutils.sysconfig. This changed in 3.10.2-3, to allow the deprecation
of distutils, upstream.

See https://bugs.launchpad.net/ubuntu/+source/python3.10/+bug/1960608
for some of the back-story here.

The effective change here is that with Python 3.10 as default, packages
using pybind11 are FTBFS because they can't find Python.h. e.g.
https://launchpad.net/ubuntu/+source/avogadrolibs/1.95.1-8

> CMake Error in python/CMakeLists.txt:
>   Imported target "pybind11::module" includes non-existent path
> 
>     "/usr/local/include/python3.10"
> 
>   in its INTERFACE_INCLUDE_DIRECTORIES.

I'm pointing to Ubuntu bugs here, because we're hitting these issues in
Ubuntu first, where Python 3.10 is the default Python 3. Debian hasn't
got there, yet.

The solutions here are two-fold:
1. Migrate from distutils.sysconfig to sysconfig. This needs to happen,
   upstream, before distutils is gone from stdlib.
2. Explicitly select the correct system scheme when looking for
   Python3's headers, rather than the default install-to-/usr/local
   scheme.

Attached are a pair of patches to address the issue. I've forwarded them
upstream in https://github.com/pybind/pybind11/pull/3764

SR
From 5262ff794498b45c12f23f64e9adef30d51e667f Mon Sep 17 00:00:00 2001
From: Stefano Rivera <stef...@rivera.za.net>
Date: Mon, 28 Feb 2022 12:49:51 -0400
Subject: [PATCH 1/2] Use sysconfig in Python >= 3.10

Rely on sysconfig for installation paths for Python >= 3.10. distutils
has been deprecated and will be removed.

Fixes: #3677
---
 tools/FindPythonLibsNew.cmake | 15 ++++++++++++---
 1 file changed, 12 insertions(+), 3 deletions(-)

diff --git a/tools/FindPythonLibsNew.cmake b/tools/FindPythonLibsNew.cmake
index 7aeffa44..31eeffa0 100644
--- a/tools/FindPythonLibsNew.cmake
+++ b/tools/FindPythonLibsNew.cmake
@@ -112,11 +112,20 @@ endif()
 # VERSION. VERSION will typically be like "2.7" on unix, and "27" on windows.
 execute_process(
   COMMAND
-    "${PYTHON_EXECUTABLE}" "-c" "from distutils import sysconfig as s;import sys;import struct;
+    "${PYTHON_EXECUTABLE}" "-c" "
+import sys;import struct;
+import sysconfig as s
+USE_SYSCONFIG = sys.version_info >= (3, 10)
+if not USE_SYSCONFIG:
+    from distutils import sysconfig as ds
 print('.'.join(str(v) for v in sys.version_info));
 print(sys.prefix);
-print(s.get_python_inc(plat_specific=True));
-print(s.get_python_lib(plat_specific=True));
+if USE_SYSCONFIG:
+    print(s.get_path('platinclude'))
+    print(s.get_path('platlib'))
+else:
+    print(ds.get_python_inc(plat_specific=True));
+    print(ds.get_python_lib(plat_specific=True));
 print(s.get_config_var('EXT_SUFFIX') or s.get_config_var('SO'));
 print(hasattr(sys, 'gettotalrefcount')+0);
 print(struct.calcsize('@P'));
-- 
2.34.1

From 697e8e1fca67bb48e477a61a9bbfa049c653ecd2 Mon Sep 17 00:00:00 2001
From: Stefano Rivera <stef...@rivera.za.net>
Date: Mon, 28 Feb 2022 13:11:45 -0400
Subject: [PATCH 2/2] Explicitly select the posix_prefix scheme for platinclude
 on Debian

Debian's default scheme is posix_local, for installing locally-built
packages to /usr/local/.  We want to find the Python headers in /usr/,
so search posix_prefix.
---
 tools/FindPythonLibsNew.cmake | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/tools/FindPythonLibsNew.cmake b/tools/FindPythonLibsNew.cmake
index 31eeffa0..6ad5fe15 100644
--- a/tools/FindPythonLibsNew.cmake
+++ b/tools/FindPythonLibsNew.cmake
@@ -121,7 +121,11 @@ if not USE_SYSCONFIG:
 print('.'.join(str(v) for v in sys.version_info));
 print(sys.prefix);
 if USE_SYSCONFIG:
-    print(s.get_path('platinclude'))
+    scheme = s.get_default_scheme()
+    if scheme == 'posix_local':
+        # Debian's default scheme installs to /usr/local/ but we want to find headers in /usr/
+        scheme = 'posix_prefix'
+    print(s.get_path('platinclude', scheme))
     print(s.get_path('platlib'))
 else:
     print(ds.get_python_inc(plat_specific=True));
-- 
2.34.1

Reply via email to