Skip to content

Commit

Permalink
install_name_tool in OSX Framework builds pypa#168
Browse files Browse the repository at this point in the history
shouldfix:  creating a virtualenv from an OSX
Framework build should no longer require XCode to
run successfully.

implementaion:  if ``install_name_tool`` missing,
download binaries from macosxforge, and install
them to a temp directory

rejected:  download and compile .c source.

TODOS:

*   review for python2/3 issues
*   cleanup of tempfiles?  Assume the system will do it?
*   test for robustness
*   review implications of not having XCode for packages, if any
*   integrate with pypa#54 pull or its descendents.  (trivial)

Possible Test Code:

    #!/bin/sh

    deactivate # virtualenv on system (Framework) python

    # assuming I have XCode or ``install_name_tool`` in path.
    python virtualenv.py t_install_name_tool  # creates with no issue
    t_install_name_tool/bin/python -c ""

    # remove it from path
    sudo mv /usr/bin/install_name_tool{,2}

    # should create with no issue, using tmpfile
    python virtualenv.py t_tmp_install_name_tool
    t_tmp_install_name_tool/bin/python -c ""

    # clean up
    sudo mv /usr/bin/install_name_tool{2,}
    command rm -rf t_{,tmp_}install_name_tool

The original patch was cleaned up, tested against
at Python 2.5, 2.6, 2.7, 3.2, and verified to work.

Signed-off-by: Yesudeep Mangalapilly <yesudeep@google.com>
  • Loading branch information
gregglind authored and yesudeep committed Mar 13, 2012
1 parent f9d6507 commit 1306777
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 1 deletion.
2 changes: 2 additions & 0 deletions AUTHORS.txt
Expand Up @@ -31,6 +31,7 @@ Douglas Creager
Ethan Jucovy
Gunnlaugur Thor Briem
Greg Haskins
Gregg Lind
Jason R. Coombs
Jeff Hammel
Jonathan Griffin
Expand All @@ -44,3 +45,4 @@ Ronny Pfannschmidt
Stefano Rivera
Tarek Ziadé
Vinay Sajip
Yesudeep Mangalapilly
67 changes: 66 additions & 1 deletion virtualenv.py
Expand Up @@ -1356,9 +1356,10 @@ def install_python(home_dir, lib_dir, inc_dir, bin_dir, site_packages, clear):
virtual_lib)

# And then change the install_name of the copied python executable
install_name_tool = get_install_name_tool()
try:
call_subprocess(
["install_name_tool", "-change",
[install_name_tool, "-change",
os.path.join(prefix, 'Python'),
'@executable_path/../.Python',
py_executable])
Expand Down Expand Up @@ -1439,6 +1440,7 @@ def install_python(home_dir, lib_dir, inc_dir, bin_dir, site_packages, clear):

return py_executable


def install_activate(home_dir, bin_dir, prompt=None):
home_dir = os.path.abspath(home_dir)
if sys.platform == 'win32' or is_jython and os._name == 'nt':
Expand Down Expand Up @@ -1548,6 +1550,69 @@ def is_executable(exe):
"""Checks a file is executable"""
return os.access(exe, os.X_OK)

def get_install_name_tool():
"""
Returns the command name of a working ``install_name_tool``, installing
one to a temp file, if necessary, or None on failure.
Returns:
string, name: of tool to use by ``call_subprocess``
None: if it was unable to install or find one.
"""
# Cleaned up patch with a fix for Python 2.5. Originally taken from:
# https://github.com/pypa/virtualenv/pull/212/files

# TODO: decide how robust this should be to various failure
# cases. Is None the correct response on failure, or should it
# debug more?

# TODO: Where should this get 'cleaned up', if it's a temp
# install? Perhaps this should return a tuple of (path, tempdir)?

import platform
import tarfile
import urllib

# Default case... on path from Xcode or something.
try:
call_subprocess(['install_name_tool'])
return 'install_name_tool'
except OSError:
logger.debug("Cannot find Xcode's install_name_tool.")

# The following code is not portable and breaks on either Python 2.5
# or Python 3.x when using virtualenvs generated by tox.
# try:
# call_subprocess(['install_name_tool'])
# return 'install_name_tool'
# except OSError as exc:
# logger.debug('%s', exc)

# Couldn't find the installed on, so, let's get one.
urls = {
'5': "http://src.macosforge.org/Roots/9A581/cctools.root.tar.gz",
'6': "http://src.macosforge.org/Roots/10A432/cctools.root.tar.gz",
'7': "http://src.macosforge.org/Roots/11A511a/cctools.root.tar.gz",
}
try:
url = urls[platform.mac_ver()[0].split('.')[1]]
except KeyError:
raise ValueError("your version of OS X wasn't planned for. "
"File a bug against: https://github.com/pypa/virtualenv/issues/168")

d = tempfile.mkdtemp()
tarname = "cctools.root.tar.gz"
urllib.urlretrieve(url, join(d, tarname))
tarfile.open(join(d, tarname)).extractall(d)
os.listdir(d)
tool_bin = join(d, 'usr', 'bin', 'install_name_tool')
if is_executable(tool_bin):
return tool_bin
else:
logger.debug('not executable: %s' % (tool_bin,))
return None


############################################################
## Relocating the environment:

Expand Down

0 comments on commit 1306777

Please sign in to comment.