From 67f9b607a920786ca6a2043233df4f678d999a0a Mon Sep 17 00:00:00 2001 From: Wang Xuerui Date: Wed, 25 Dec 2013 18:51:01 +0800 Subject: [PATCH] Properly support libdirs of explicit bitnesses. Formerly this is limited to lib64 on 64-bit systems; more configurations such as Gentoo on MIPS N32 (which uses /usr/lib32; /usr/lib is for O32 ABI) are supported now. --- virtualenv.py | 64 +++++++++++++++++++++++++++++++++++---------- virtualenv_embedded/site.py | 55 ++++++++++++++++++++++++++------------ 2 files changed, 88 insertions(+), 31 deletions(-) diff --git a/virtualenv.py b/virtualenv.py index 5f18232..a62995f 100755 --- a/python/virtualenv/virtualenv.py +++ b/python/virtualenv/virtualenv.py @@ -1157,7 +1157,10 @@ def install_python(home_dir, lib_dir, inc_dir, bin_dir, site_packages, clear, sy else: prefix = sys.prefix mkdir(lib_dir) - fix_lib64(lib_dir, symlink) + + # Account for libdir of explicit bitness. + is_bitness_explicit, libdir_bitness = fix_libdir_bitness(lib_dir, symlink) + stdlib_dirs = [os.path.dirname(os.__file__)] if is_win: stdlib_dirs.append(join(os.path.dirname(stdlib_dirs[0]), 'DLLs')) @@ -1192,6 +1195,14 @@ def install_python(home_dir, lib_dir, inc_dir, bin_dir, site_packages, clear, sy site_dir = os.path.dirname(site_filename_dst) writefile(site_filename_dst, SITE_PY) writefile(join(site_dir, 'orig-prefix.txt'), prefix) + + # We need to record the bitness of original libdir, or the virtualenv + # site.py will not be able to insert the correct system package paths. + # Assuming that the simplicity of orig-prefix.txt may be relied upon by + # external programs, we have to write a new file here. + if is_bitness_explicit: + writefile(join(site_dir, 'libdir-bitness.txt'), libdir_bitness) + site_packages_filename = join(site_dir, 'no-global-site-packages.txt') if not site_packages: writefile(site_packages_filename, '') @@ -1549,36 +1560,56 @@ def fix_local_scheme(home_dir, symlink=True): copyfile(os.path.abspath(os.path.join(home_dir, subdir_name)), \ os.path.join(local_path, subdir_name), symlink) -def fix_lib64(lib_dir, symlink=True): +def fix_libdir_bitness(lib_dir, symlink=True): """ - Some platforms (particularly Gentoo on x64) put things in lib64/pythonX.Y - instead of lib/pythonX.Y. If this is such a platform we'll just create a - symlink so lib64 points to lib + Some platforms (such as Gentoo on x64 or on MIPS ABI n32/n64) put things + in lib{64,32}/pythonX.Y instead of lib/pythonX.Y. If this is such a + platform we'll just create a symlink so libXX points to lib. """ + + # Common bitnesses. + for bitness in '64', '32', 'x32': + if _do_fix_libdir_bitness(lib_dir, symlink, bitness): + return True, bitness + + return False, None + +def _do_fix_libdir_bitness(lib_dir, symlink, bitness): + target_dirname = 'lib' + bitness + logger.debug("Trying to symlink libdir '%s' to lib" % (target_dirname, )) + if [p for p in distutils.sysconfig.get_config_vars().values() - if isinstance(p, basestring) and 'lib64' in p]: + if isinstance(p, basestring) and target_dirname in p]: # PyPy's library path scheme is not affected by this. # Return early or we will die on the following assert. + # Pretend we have succeeded and report the correct bitness back, + # because later on the bitness information is still needed by site.py + # inside the virtualenv, to find the correct system package path. if is_pypy: - logger.debug('PyPy detected, skipping lib64 symlinking') - return + logger.debug('PyPy detected, skipping %s symlinking' % (target_dirname, )) + return True - logger.debug('This system uses lib64; symlinking lib64 to lib') + logger.debug('This system uses %s; symlinking %s to lib' % ( + target_dirname, + target_dirname, + )) assert os.path.basename(lib_dir) == 'python%s' % sys.version[:3], ( "Unexpected python lib dir: %r" % lib_dir) lib_parent = os.path.dirname(lib_dir) top_level = os.path.dirname(lib_parent) lib_dir = os.path.join(top_level, 'lib') - lib64_link = os.path.join(top_level, 'lib64') + target_lib_link = os.path.join(top_level, target_dirname) assert os.path.basename(lib_parent) == 'lib', ( "Unexpected parent dir: %r" % lib_parent) - if os.path.lexists(lib64_link): - return + if os.path.lexists(target_lib_link): + return True if symlink: - os.symlink('lib', lib64_link) + os.symlink('lib', target_lib_link) else: - copyfile('lib', lib64_link) + copyfile('lib', target_lib_link) + # Seems not affected, continue checking + return False def resolve_interpreter(exe): """ @@ -1999,6 +2030,11 @@ n6kJTcsp4tG42yeT7nQbtdUFwgVJjwDSUYEAC8F0dKOTILrlLO/xC70bnNd0Ha97whQ6UkHJYj5H cA/j+zX4tbtTIfGjujOKpj83aHOgXnIQbvYduNXEC4UMm4T21Bs+GHABuCa7v//LR/TvpjHa7oe7 /Grb6lVvHSD7spj5iplBLRKZxxEYGdCbY9LWWC5hBB2voWno6DJUMzfkC3T8KJsWL9umDQY5szPt AVijEPwfucjncQ== +CDKnFwi6c88xITGnRQVv4Ovd1ctjc8CH/I6vLUFC2Z0jyzy7srKjd97zanUnZimmlD6LHrd1LKNa +XFtQ2bIb8lA7JWIDXqzOO2JII+d9f26p7uH8bxijNqaG9Y5hSmL8rJzQtKyiOoW7eTLpTrcRW10g +XCD4CCAdEQiwEExHNloJ21uuuhi/UMbNvKYbsu1TXt/aFZS86XIE99AWfINfuzsV9j+qO6Oo+3OD +NgeqJYfNzTYFt7JoslMltKfe8MGAacB3JPT3f/mI/t2zHNP9cJd3ZFod9dblskeCmeiYqdcikX4c +gJIBuTkmaY3lS3qj47VQDR1thmrmhnyBBiFlt+P99+Qmksk7UxaAUQre/wFK8wT0 """) ##file activate.sh diff --git a/virtualenv_embedded/site.py b/virtualenv_embedded/site.py index 7969769..b9ee086 100644 --- a/python/virtualenv/virtualenv_embedded/site.py +++ b/python/virtualenv/virtualenv_embedded/site.py @@ -206,7 +206,7 @@ def addsitedir(sitedir, known_paths=None): known_paths = None return known_paths -def addsitepackages(known_paths, sys_prefix=sys.prefix, exec_prefix=sys.exec_prefix): +def addsitepackages(known_paths, sys_prefix=sys.prefix, exec_prefix=sys.exec_prefix, bitness=None): """Add site-packages (and possibly site-python) to sys.path""" prefixes = [os.path.join(sys_prefix, "local"), sys_prefix] if exec_prefix != sys_prefix: @@ -236,13 +236,14 @@ def addsitepackages(known_paths, sys_prefix=sys.prefix, exec_prefix=sys.exec_pre "site-packages"), os.path.join(prefix, "lib", "site-python"), os.path.join(prefix, "python" + sys.version[:3], "lib-dynload")] - lib64_dir = os.path.join(prefix, "lib64", "python" + sys.version[:3], "site-packages") - if (os.path.exists(lib64_dir) and - os.path.realpath(lib64_dir) not in [os.path.realpath(p) for p in sitedirs]): - if _is_64bit: - sitedirs.insert(0, lib64_dir) - else: - sitedirs.append(lib64_dir) + + if bitness is not None: + libXX = "lib" + bitness + libXX_dir = os.path.join(prefix, libXX, "python" + sys.version[:3], "site-packages") + if (os.path.exists(libXX_dir) and + os.path.realpath(libXX_dir) not in [os.path.realpath(p) for p in sitedirs]): + sitedirs.insert(0, libXX_dir) + try: # sys.getobjects only available in --with-pydebug build sys.getobjects @@ -549,7 +550,7 @@ def execsitecustomize(): except ImportError: pass -def virtual_install_main_packages(): +def virtual_install_main_packages(bitness=None): f = open(os.path.join(os.path.dirname(__file__), 'orig-prefix.txt')) sys.real_prefix = f.read().strip() f.close() @@ -583,12 +584,20 @@ def virtual_install_main_packages(): else: paths = [os.path.join(sys.real_prefix, 'lib', 'python'+sys.version[:3])] hardcoded_relative_dirs = paths[:] # for the special 'darwin' case below - lib64_path = os.path.join(sys.real_prefix, 'lib64', 'python'+sys.version[:3]) - if os.path.exists(lib64_path): - if _is_64bit: - paths.insert(0, lib64_path) - else: - paths.append(lib64_path) + + if bitness is not None: + libXX = 'lib' + bitness + libXX_path = os.path.join(sys.real_prefix, libXX, 'python'+sys.version[:3]) + if os.path.exists(libXX_path): + # Originally the code here checked if the current system is 64-bit, + # and chose to append the path instead of prepending if the system + # turns out to be 32-bit. + # Unfortunately this will fail on some multilib MIPS systems with + # N32 as default ABI, where /usr/lib32 is the expected libdir and + # /usr/lib for O32. + # We'd rather be safe here... + paths.insert(0, libXX_path) + # This is hardcoded in the Python executable, but relative to # sys.prefix. Debian change: we need to add the multiarch triplet # here, which is where the real stuff lives. As per PEP 421, in @@ -667,7 +676,19 @@ def execusercustomize(): def main(): global ENABLE_USER_SITE - virtual_install_main_packages() + + # Account for system libdirs of explicit bitness. + libdir_bitness = None + bitness_file = os.path.join(os.path.dirname(__file__), 'libdir-bitness.txt') + if os.path.exists(bitness_file): + # Read the bitness recorded on virtualenv creation. + bitness_fp = open(bitness_file) + try: + libdir_bitness = bitness_fp.read().strip() + finally: + bitness_fp.close() + + virtual_install_main_packages(libdir_bitness) abs__file__() paths_in_sys = removeduppaths() if (os.name == "posix" and sys.path and @@ -680,7 +701,7 @@ def main(): ENABLE_USER_SITE = False if ENABLE_USER_SITE is None: ENABLE_USER_SITE = check_enableusersite() - paths_in_sys = addsitepackages(paths_in_sys) + paths_in_sys = addsitepackages(paths_in_sys, bitness=libdir_bitness) paths_in_sys = addusersitepackages(paths_in_sys) if GLOBAL_SITE_PACKAGES: paths_in_sys = virtual_addsitepackages(paths_in_sys) -- 2.4.10