Skip to content

Instantly share code, notes, and snippets.

@jvkersch
Created October 2, 2015 17:38
Show Gist options
  • Save jvkersch/402291f7d965c667b1ab to your computer and use it in GitHub Desktop.
Save jvkersch/402291f7d965c667b1ab to your computer and use it in GitHub Desktop.
diff --git a/Modules/getpath.c b/Modules/getpath.c
index de96d47..8487208 100644
--- a/Modules/getpath.c
+++ b/Modules/getpath.c
@@ -7,7 +7,7 @@
#include <string.h>
#ifdef __APPLE__
-#include <mach-o/dyld.h>
+#include <dlfcn.h>
#endif
/* Search in some common locations for the associated Python libraries.
@@ -402,9 +402,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__
+#ifdef notdef
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
uint32_t nsexeclength = MAXPATHLEN;
#else
@@ -419,7 +420,7 @@ calculate_path(void)
*/
if (strchr(prog, SEP))
strncpy(progpath, prog, MAXPATHLEN);
-#ifdef __APPLE__
+#ifdef notdef
/* 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.
@@ -432,7 +433,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);
@@ -471,9 +472,18 @@ calculate_path(void)
** which is in the framework, not relative to the executable, which may
** 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
@@ -526,6 +536,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");
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment