You've already forked macports-ports
mirror of
https://github.com/macports/macports-ports.git
synced 2026-07-12 18:20:25 -07:00
cb9bdc4754
On macOS 12 (Monterey), dladdr, NSLibraryNameForModule and similar functions return the real path of the dynamic library instead of the path to the symlink in a virtualenv. This breaks support for virtualenv. By applying the same patch as Apple does for its Python version, which avoids using these functions whenever possible, support for virtualenv is restored. See also: https://github.com/apple-oss-distributions/python/blob/python-136.120.2/2.7/fix/getpath.c.ed Co-authored-by: Joshua Root <jmr@macports.org>
83 lines
3.2 KiB
Diff
83 lines
3.2 KiB
Diff
As of macOS 12, dladdr, NSLibraryNameForModule, and similar functions
|
|
will resolve symlinks, which breaks virtualenv. This works around that
|
|
issue by not using those functions if at all possible.
|
|
|
|
Adapted from https://github.com/apple-oss-distributions/python/blob/python-136.120.2/2.7/fix/getpath.c.ed
|
|
--- Modules/getpath.c.orig 2022-01-08 05:08:48.000000000 +1100
|
|
+++ Modules/getpath.c 2022-01-08 05:13:34.000000000 +1100
|
|
@@ -7,7 +7,7 @@
|
|
#include <string.h>
|
|
|
|
#ifdef __APPLE__
|
|
-#include <mach-o/dyld.h>
|
|
+#include <dlfcn.h>
|
|
#include <AvailabilityMacros.h>
|
|
#endif
|
|
|
|
@@ -380,9 +380,10 @@ calculate_path(void)
|
|
size_t prefixsz;
|
|
char *defpath = pythonpath;
|
|
#ifdef WITH_NEXT_FRAMEWORK
|
|
- NSModule pythonModule;
|
|
+ Dl_info addrinfo;
|
|
+ int first_pass = 1;
|
|
#endif
|
|
-#ifdef __APPLE__
|
|
+#if 0
|
|
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
|
|
uint32_t nsexeclength = MAXPATHLEN;
|
|
#else
|
|
@@ -397,7 +398,7 @@ calculate_path(void)
|
|
*/
|
|
if (strchr(prog, SEP))
|
|
strncpy(progpath, prog, MAXPATHLEN);
|
|
-#ifdef __APPLE__
|
|
+#if 0
|
|
/* On Mac OS X, if a script uses an interpreter of the form
|
|
* "#!/opt/python2.3/bin/python", the kernel only passes "python"
|
|
* as argv[0], which falls through to the $PATH search below.
|
|
@@ -410,7 +411,7 @@ calculate_path(void)
|
|
*/
|
|
else if(0 == _NSGetExecutablePath(progpath, &nsexeclength) && progpath[0] == SEP)
|
|
;
|
|
-#endif /* __APPLE__ */
|
|
+#endif /* notdef */
|
|
else if (path) {
|
|
while (1) {
|
|
char *delim = strchr(path, DELIM);
|
|
@@ -449,9 +450,18 @@ calculate_path(void)
|
|
** which is in the framework, not relative to the executable, which ma
|
|
** be outside of the framework. Except when we're in the build directory...
|
|
*/
|
|
- pythonModule = NSModuleForSymbol(NSLookupAndBindSymbol("_Py_Initialize"));
|
|
- /* Use dylib functions to find out where the framework was loaded from */
|
|
- buf = (char *)NSLibraryNameForModule(pythonModule);
|
|
+ /* dladdr() now returns the real path of the dylib, instead of the
|
|
+ ** path of the symlink. This breaks virtualenv. To fix this, we
|
|
+ ** skip using dladdr() during a first pass, and if that fails, then
|
|
+ ** we go back and do the dladdr(). It turns out that since we moved
|
|
+ ** Python.app to inside the Python.framework bundle, the call to
|
|
+ ** search_for_prefix() will now succeed without needing dladdr().
|
|
+ ** However, virtualenv copies the wrong binary when the prefix is
|
|
+ ** /usr, so if progpath begins with /usr/bin/, we skip the first pass.
|
|
+ */
|
|
+ if (strncmp(progpath, "/usr/bin/", 9) == 0) first_pass = 0;
|
|
+return_here_for_second_pass:
|
|
+ buf = first_pass ? NULL : (dladdr("_Py_Initialize", &addrinfo) ? (char *)addrinfo.dli_fname : NULL);
|
|
if (buf != NULL) {
|
|
/* We're in a framework. */
|
|
/* See if we might be in the build directory. The framework in the
|
|
@@ -504,6 +514,12 @@ calculate_path(void)
|
|
*/
|
|
|
|
if (!(pfound = search_for_prefix(argv0_path, home))) {
|
|
+#ifdef WITH_NEXT_FRAMEWORK
|
|
+ if (first_pass) {
|
|
+ first_pass = 0;
|
|
+ goto return_here_for_second_pass;
|
|
+ }
|
|
+#endif
|
|
if (!Py_FrozenFlag)
|
|
fprintf(stderr,
|
|
"Could not find platform independent libraries <prefix>\n");
|