Skip to content

Commit a2135f1

Browse files
committed
Apply the getpath library name patch to 3.11+
Backport the changes to library_to_dict() (the function we're patching in 3.14) in Modules/getpath.c with the help of git checkout -p v3.14.0 -- Modules/getpath.c
1 parent 2b04093 commit a2135f1

File tree

6 files changed

+336
-5
lines changed

6 files changed

+336
-5
lines changed

cpython-unix/build-cpython.sh

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -623,8 +623,12 @@ fi
623623
# Adjust the Python startup logic (getpath.py) to properly locate the installation, even when
624624
# invoked through a symlink or through an incorrect argv[0]. Because this Python is relocatable, we
625625
# don't get to rely on the fallback to the compiled-in installation prefix.
626-
if [[ -n "${PYTHON_MEETS_MINIMUM_VERSION_3_14}" ]]; then
627-
patch -p1 -i "${ROOT}/patch-python-getpath-3.14.patch"
626+
if [[ -n "${PYTHON_MEETS_MINIMUM_VERSION_3_11}" ]]; then
627+
if [ -e "${ROOT}/patch-python-getpath-backport-${PYTHON_MAJMIN_VERSION}.patch" ]; then
628+
# Sync the getpath logic in older minor releases to the current version.
629+
patch -p1 -i "${ROOT}/patch-python-getpath-backport-${PYTHON_MAJMIN_VERSION}.patch"
630+
fi
631+
patch -p1 -i "${ROOT}/patch-python-getpath-library.patch"
628632
fi
629633

630634
# Another, similar change to getpath: When reading inside a venv use the base_executable path to
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
From fe34b57349c57df0f1443f622985b872807ad1a0 Mon Sep 17 00:00:00 2001
2+
From: Geoffrey Thomas <geofft@ldpreload.com>
3+
Date: Tue, 16 Dec 2025 09:33:06 -0500
4+
Subject: [PATCH 1/1] Backport relevant parts of 3.14 getpath.c to 3.11
5+
Forwarded: not-needed
6+
7+
---
8+
Modules/getpath.c | 42 ++++++++++++++++--------------------------
9+
configure.ac | 2 +-
10+
pyconfig.h.in | 3 +++
11+
3 files changed, 20 insertions(+), 27 deletions(-)
12+
13+
diff --git a/Modules/getpath.c b/Modules/getpath.c
14+
index 61d654065fd..7457f70109f 100644
15+
--- a/Modules/getpath.c
16+
+++ b/Modules/getpath.c
17+
@@ -18,6 +18,10 @@
18+
# include <mach-o/dyld.h>
19+
#endif
20+
21+
+#ifdef HAVE_DLFCN_H
22+
+# include <dlfcn.h>
23+
+#endif
24+
+
25+
/* Reference the precompiled getpath.py */
26+
#include "../Python/frozen_modules/getpath.h"
27+
28+
@@ -762,39 +766,25 @@ progname_to_dict(PyObject *dict, const char *key)
29+
static int
30+
library_to_dict(PyObject *dict, const char *key)
31+
{
32+
+/* macOS framework builds do not link against a libpython dynamic library, but
33+
+ instead link against a macOS Framework. */
34+
+#if defined(Py_ENABLE_SHARED) || defined(WITH_NEXT_FRAMEWORK)
35+
+
36+
#ifdef MS_WINDOWS
37+
extern HMODULE PyWin_DLLhModule;
38+
if (PyWin_DLLhModule) {
39+
return winmodule_to_dict(dict, key, PyWin_DLLhModule);
40+
}
41+
-#elif defined(WITH_NEXT_FRAMEWORK)
42+
- static char modPath[MAXPATHLEN + 1];
43+
- static int modPathInitialized = -1;
44+
- if (modPathInitialized < 0) {
45+
- modPathInitialized = 0;
46+
-
47+
- /* On Mac OS X we have a special case if we're running from a framework.
48+
- This is because the python home should be set relative to the library,
49+
- which is in the framework, not relative to the executable, which may
50+
- be outside of the framework. Except when we're in the build
51+
- directory... */
52+
- NSSymbol symbol = NSLookupAndBindSymbol("_Py_Initialize");
53+
- if (symbol != NULL) {
54+
- NSModule pythonModule = NSModuleForSymbol(symbol);
55+
- if (pythonModule != NULL) {
56+
- /* Use dylib functions to find out where the framework was loaded from */
57+
- const char *path = NSLibraryNameForModule(pythonModule);
58+
- if (path) {
59+
- strncpy(modPath, path, MAXPATHLEN);
60+
- modPathInitialized = 1;
61+
- }
62+
- }
63+
- }
64+
- }
65+
- if (modPathInitialized > 0) {
66+
- return decode_to_dict(dict, key, modPath);
67+
+#endif
68+
+
69+
+#if HAVE_DLADDR
70+
+ Dl_info libpython_info;
71+
+ if (dladdr(&Py_Initialize, &libpython_info) && libpython_info.dli_fname) {
72+
+ return decode_to_dict(dict, key, libpython_info.dli_fname);
73+
}
74+
#endif
75+
+#endif
76+
+
77+
return PyDict_SetItemString(dict, key, Py_None) == 0;
78+
}
79+
80+
diff --git a/configure.ac b/configure.ac
81+
index 7b4000fa9c3..e1c537fd153 100644
82+
--- a/configure.ac
83+
+++ b/configure.ac
84+
@@ -4594,7 +4594,7 @@ fi
85+
# checks for library functions
86+
AC_CHECK_FUNCS([ \
87+
accept4 alarm bind_textdomain_codeset chmod chown clock close_range confstr \
88+
- copy_file_range ctermid dup dup3 execv explicit_bzero explicit_memset \
89+
+ copy_file_range ctermid dladdr dup dup3 execv explicit_bzero explicit_memset \
90+
faccessat fchmod fchmodat fchown fchownat fdopendir fdwalk fexecve \
91+
fork fork1 fpathconf fstatat ftime ftruncate futimens futimes futimesat \
92+
gai_strerror getegid getentropy geteuid getgid getgrgid getgrgid_r \
93+
diff --git a/pyconfig.h.in b/pyconfig.h.in
94+
index a8c35bba448..422a1cd0878 100644
95+
--- a/pyconfig.h.in
96+
+++ b/pyconfig.h.in
97+
@@ -281,6 +281,9 @@
98+
/* Define if you have the 'dirfd' function or macro. */
99+
#undef HAVE_DIRFD
100+
101+
+/* Define to 1 if you have the 'dladdr' function. */
102+
+#undef HAVE_DLADDR
103+
+
104+
/* Define to 1 if you have the <dlfcn.h> header file. */
105+
#undef HAVE_DLFCN_H
106+
107+
--
108+
2.50.1 (Apple Git-155)
109+
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
From 3cf84081c92fe6ea1edc24aa579b34a0934b3c2d Mon Sep 17 00:00:00 2001
2+
From: Geoffrey Thomas <geofft@ldpreload.com>
3+
Date: Tue, 16 Dec 2025 09:32:12 -0500
4+
Subject: [PATCH 1/1] Backport relevant parts of 3.14 getpath.c to 3.12
5+
Forwarded: not-needed
6+
7+
---
8+
Modules/getpath.c | 42 +++++++++++++++---------------------------
9+
configure.ac | 2 +-
10+
pyconfig.h.in | 3 +++
11+
3 files changed, 19 insertions(+), 28 deletions(-)
12+
13+
diff --git a/Modules/getpath.c b/Modules/getpath.c
14+
index 0a310000751..9cea2d7bd20 100644
15+
--- a/Modules/getpath.c
16+
+++ b/Modules/getpath.c
17+
@@ -18,6 +18,10 @@
18+
# include <mach-o/dyld.h>
19+
#endif
20+
21+
+#ifdef HAVE_DLFCN_H
22+
+# include <dlfcn.h>
23+
+#endif
24+
+
25+
/* Reference the precompiled getpath.py */
26+
#include "../Python/frozen_modules/getpath.h"
27+
28+
@@ -752,41 +756,25 @@ progname_to_dict(PyObject *dict, const char *key)
29+
static int
30+
library_to_dict(PyObject *dict, const char *key)
31+
{
32+
+/* macOS framework builds do not link against a libpython dynamic library, but
33+
+ instead link against a macOS Framework. */
34+
+#if defined(Py_ENABLE_SHARED) || defined(WITH_NEXT_FRAMEWORK)
35+
+
36+
#ifdef MS_WINDOWS
37+
-#ifdef Py_ENABLE_SHARED
38+
extern HMODULE PyWin_DLLhModule;
39+
if (PyWin_DLLhModule) {
40+
return winmodule_to_dict(dict, key, PyWin_DLLhModule);
41+
}
42+
#endif
43+
-#elif defined(WITH_NEXT_FRAMEWORK)
44+
- static char modPath[MAXPATHLEN + 1];
45+
- static int modPathInitialized = -1;
46+
- if (modPathInitialized < 0) {
47+
- modPathInitialized = 0;
48+
-
49+
- /* On Mac OS X we have a special case if we're running from a framework.
50+
- This is because the python home should be set relative to the library,
51+
- which is in the framework, not relative to the executable, which may
52+
- be outside of the framework. Except when we're in the build
53+
- directory... */
54+
- NSSymbol symbol = NSLookupAndBindSymbol("_Py_Initialize");
55+
- if (symbol != NULL) {
56+
- NSModule pythonModule = NSModuleForSymbol(symbol);
57+
- if (pythonModule != NULL) {
58+
- /* Use dylib functions to find out where the framework was loaded from */
59+
- const char *path = NSLibraryNameForModule(pythonModule);
60+
- if (path) {
61+
- strncpy(modPath, path, MAXPATHLEN);
62+
- modPathInitialized = 1;
63+
- }
64+
- }
65+
- }
66+
- }
67+
- if (modPathInitialized > 0) {
68+
- return decode_to_dict(dict, key, modPath);
69+
+
70+
+#if HAVE_DLADDR
71+
+ Dl_info libpython_info;
72+
+ if (dladdr(&Py_Initialize, &libpython_info) && libpython_info.dli_fname) {
73+
+ return decode_to_dict(dict, key, libpython_info.dli_fname);
74+
}
75+
#endif
76+
+#endif
77+
+
78+
return PyDict_SetItemString(dict, key, Py_None) == 0;
79+
}
80+
81+
diff --git a/configure.ac b/configure.ac
82+
index 1a02d19f1b2..1177525f88f 100644
83+
--- a/configure.ac
84+
+++ b/configure.ac
85+
@@ -4920,7 +4920,7 @@ fi
86+
# checks for library functions
87+
AC_CHECK_FUNCS([ \
88+
accept4 alarm bind_textdomain_codeset chmod chown clock close_range confstr \
89+
- copy_file_range ctermid dup dup3 execv explicit_bzero explicit_memset \
90+
+ copy_file_range ctermid dladdr dup dup3 execv explicit_bzero explicit_memset \
91+
faccessat fchmod fchmodat fchown fchownat fdopendir fdwalk fexecve \
92+
fork fork1 fpathconf fstatat ftime ftruncate futimens futimes futimesat \
93+
gai_strerror getegid getentropy geteuid getgid getgrgid getgrgid_r \
94+
diff --git a/pyconfig.h.in b/pyconfig.h.in
95+
index df4d29fe549..f2f09a7ec8c 100644
96+
--- a/pyconfig.h.in
97+
+++ b/pyconfig.h.in
98+
@@ -280,6 +280,9 @@
99+
/* Define if you have the 'dirfd' function or macro. */
100+
#undef HAVE_DIRFD
101+
102+
+/* Define to 1 if you have the 'dladdr' function. */
103+
+#undef HAVE_DLADDR
104+
+
105+
/* Define to 1 if you have the <dlfcn.h> header file. */
106+
#undef HAVE_DLFCN_H
107+
108+
--
109+
2.50.1 (Apple Git-155)
110+
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
From 3342daa091b0a8e6cf15fdaaa2c6fc2f9dcc8a60 Mon Sep 17 00:00:00 2001
2+
From: Geoffrey Thomas <geofft@ldpreload.com>
3+
Date: Tue, 16 Dec 2025 09:29:55 -0500
4+
Subject: [PATCH 1/1] Backport relevant parts of 3.14 getpath.c to 3.13
5+
Forwarded: not-needed
6+
7+
---
8+
Modules/getpath.c | 38 +++++++++++++++-----------------------
9+
configure.ac | 2 +-
10+
pyconfig.h.in | 3 +++
11+
3 files changed, 19 insertions(+), 24 deletions(-)
12+
13+
diff --git a/Modules/getpath.c b/Modules/getpath.c
14+
index d0128b20fae..50612432027 100644
15+
--- a/Modules/getpath.c
16+
+++ b/Modules/getpath.c
17+
@@ -17,10 +17,13 @@
18+
#endif
19+
20+
#ifdef __APPLE__
21+
-# include <dlfcn.h>
22+
# include <mach-o/dyld.h>
23+
#endif
24+
25+
+#ifdef HAVE_DLFCN_H
26+
+# include <dlfcn.h>
27+
+#endif
28+
+
29+
/* Reference the precompiled getpath.py */
30+
#include "Python/frozen_modules/getpath.h"
31+
32+
@@ -803,36 +806,25 @@ progname_to_dict(PyObject *dict, const char *key)
33+
static int
34+
library_to_dict(PyObject *dict, const char *key)
35+
{
36+
+/* macOS framework builds do not link against a libpython dynamic library, but
37+
+ instead link against a macOS Framework. */
38+
+#if defined(Py_ENABLE_SHARED) || defined(WITH_NEXT_FRAMEWORK)
39+
+
40+
#ifdef MS_WINDOWS
41+
-#ifdef Py_ENABLE_SHARED
42+
extern HMODULE PyWin_DLLhModule;
43+
if (PyWin_DLLhModule) {
44+
return winmodule_to_dict(dict, key, PyWin_DLLhModule);
45+
}
46+
#endif
47+
-#elif defined(WITH_NEXT_FRAMEWORK)
48+
- static char modPath[MAXPATHLEN + 1];
49+
- static int modPathInitialized = -1;
50+
- if (modPathInitialized < 0) {
51+
- modPathInitialized = 0;
52+
-
53+
- /* On Mac OS X we have a special case if we're running from a framework.
54+
- This is because the python home should be set relative to the library,
55+
- which is in the framework, not relative to the executable, which may
56+
- be outside of the framework. Except when we're in the build
57+
- directory... */
58+
- Dl_info pythonInfo;
59+
- if (dladdr(&Py_Initialize, &pythonInfo)) {
60+
- if (pythonInfo.dli_fname) {
61+
- strncpy(modPath, pythonInfo.dli_fname, MAXPATHLEN);
62+
- modPathInitialized = 1;
63+
- }
64+
- }
65+
- }
66+
- if (modPathInitialized > 0) {
67+
- return decode_to_dict(dict, key, modPath);
68+
+
69+
+#if HAVE_DLADDR
70+
+ Dl_info libpython_info;
71+
+ if (dladdr(&Py_Initialize, &libpython_info) && libpython_info.dli_fname) {
72+
+ return decode_to_dict(dict, key, libpython_info.dli_fname);
73+
}
74+
#endif
75+
+#endif
76+
+
77+
return PyDict_SetItemString(dict, key, Py_None) == 0;
78+
}
79+
80+
diff --git a/configure.ac b/configure.ac
81+
index 94776540d1b..fbc6cfd0de4 100644
82+
--- a/configure.ac
83+
+++ b/configure.ac
84+
@@ -5217,7 +5217,7 @@ fi
85+
# checks for library functions
86+
AC_CHECK_FUNCS([ \
87+
accept4 alarm bind_textdomain_codeset chmod chown clock closefrom close_range confstr \
88+
- copy_file_range ctermid dup dup3 execv explicit_bzero explicit_memset \
89+
+ copy_file_range ctermid dladdr dup dup3 execv explicit_bzero explicit_memset \
90+
faccessat fchmod fchmodat fchown fchownat fdopendir fdwalk fexecve \
91+
fork fork1 fpathconf fstatat ftime ftruncate futimens futimes futimesat \
92+
gai_strerror getegid geteuid getgid getgrent getgrgid getgrgid_r \
93+
diff --git a/pyconfig.h.in b/pyconfig.h.in
94+
index e18a6426b06..10b0cc1dafd 100644
95+
--- a/pyconfig.h.in
96+
+++ b/pyconfig.h.in
97+
@@ -284,6 +284,9 @@
98+
/* Define if you have the 'dirfd' function or macro. */
99+
#undef HAVE_DIRFD
100+
101+
+/* Define to 1 if you have the 'dladdr' function. */
102+
+#undef HAVE_DLADDR
103+
+
104+
/* Define to 1 if you have the <dlfcn.h> header file. */
105+
#undef HAVE_DLFCN_H
106+
107+
--
108+
2.50.1 (Apple Git-155)
109+
File renamed without changes.

src/verify_distribution.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -300,9 +300,8 @@ def assertPythonWorks(path: Path, argv0: str = None):
300300
)
301301
assertPythonWorks(venv / "bin" / "python")
302302

303-
if sys.version_info[:2] >= (3, 14):
304-
with self.subTest(msg="weird argv[0]"):
305-
assertPythonWorks(sys.executable, argv0="/dev/null")
303+
with self.subTest(msg="weird argv[0]"):
304+
assertPythonWorks(sys.executable, argv0="/dev/null")
306305

307306

308307
if __name__ == "__main__":

0 commit comments

Comments
 (0)