Skip to content

Commit

Permalink
Pull in ~pristine copies of pep425tags/glibc from our vendored setupt…
Browse files Browse the repository at this point in the history
…ools.
  • Loading branch information
jsirois committed Mar 28, 2019
1 parent 6e35c5f commit b4e0d55
Show file tree
Hide file tree
Showing 3 changed files with 319 additions and 337 deletions.
99 changes: 53 additions & 46 deletions pex/glibc.py
Original file line number Diff line number Diff line change
@@ -1,61 +1,64 @@
# This file was copied from the pip project master branch on 2016/12/05
# NB: Copied from our vendored setuptools' version at:
# pex/vendor/_vendored/setuptools/setuptools/glibc.py
# Modifications are marked with `# NB: Modified from ...`

# This file originally from pip:
# https://github.com/pypa/pip/blob/8f4f15a5a95d7d5b511ceaee9ed261176c181970/src/pip/_internal/utils/glibc.py
from __future__ import absolute_import

import ctypes
import platform
import re

from pex import pex_warnings
from pex import pex_warnings # NB: Modified from `import warnings`


def glibc_version_string():
"Returns glibc version string, or None if not using glibc."
"Returns glibc version string, or None if not using glibc."

# ctypes.CDLL(None) internally calls dlopen(NULL), and as the dlopen
# manpage says, "If filename is NULL, then the returned handle is for the
# main program". This way we can let the linker do the work to figure out
# which libc our process is actually using.
process_namespace = ctypes.CDLL(None)
try:
gnu_get_libc_version = process_namespace.gnu_get_libc_version
except AttributeError:
# Symbol doesn't exist -> therefore, we are not linked to
# glibc.
return None
# ctypes.CDLL(None) internally calls dlopen(NULL), and as the dlopen
# manpage says, "If filename is NULL, then the returned handle is for the
# main program". This way we can let the linker do the work to figure out
# which libc our process is actually using.
process_namespace = ctypes.CDLL(None)
try:
gnu_get_libc_version = process_namespace.gnu_get_libc_version
except AttributeError:
# Symbol doesn't exist -> therefore, we are not linked to
# glibc.
return None

# Call gnu_get_libc_version, which returns a string like "2.5"
gnu_get_libc_version.restype = ctypes.c_char_p
version_str = gnu_get_libc_version()
# py2 / py3 compatibility:
if not isinstance(version_str, str):
version_str = version_str.decode("ascii")
# Call gnu_get_libc_version, which returns a string like "2.5"
gnu_get_libc_version.restype = ctypes.c_char_p
version_str = gnu_get_libc_version()
# py2 / py3 compatibility:
if not isinstance(version_str, str):
version_str = version_str.decode("ascii")

return version_str
return version_str


# Separated out from have_compatible_glibc for easier unit testing
def check_glibc_version(version_str, required_major, minimum_minor):
# Parse string and check against requested version.
#
# We use a regexp instead of str.split because we want to discard any
# random junk that might come after the minor version -- this might happen
# in patched/forked versions of glibc (e.g. Linaro's version of glibc
# uses version strings like "2.20-2014.11"). See gh-3588.
m = re.match(r"(?P<major>[0-9]+)\.(?P<minor>[0-9]+)", version_str)
if not m:
pex_warnings.warn("Expected glibc version with 2 components major.minor,"
" got: %s" % version_str)
return False
return (int(m.group("major")) == required_major and
int(m.group("minor")) >= minimum_minor)
# Parse string and check against requested version.
#
# We use a regexp instead of str.split because we want to discard any
# random junk that might come after the minor version -- this might happen
# in patched/forked versions of glibc (e.g. Linaro's version of glibc
# uses version strings like "2.20-2014.11"). See gh-3588.
m = re.match(r"(?P<major>[0-9]+)\.(?P<minor>[0-9]+)", version_str)
if not m:
# NB: Modified from `warnings.warn(..., RuntimeError)`
pex_warnings.warn("Expected glibc version with 2 components major.minor,"
" got: %s" % version_str)
return False
return (int(m.group("major")) == required_major and
int(m.group("minor")) >= minimum_minor)


def have_compatible_glibc(required_major, minimum_minor):
version_str = glibc_version_string()
if version_str is None:
return False
return check_glibc_version(version_str, required_major, minimum_minor)
version_str = glibc_version_string()
if version_str is None:
return False
return check_glibc_version(version_str, required_major, minimum_minor)


# platform.libc_ver regularly returns completely nonsensical glibc
Expand All @@ -76,9 +79,13 @@ def have_compatible_glibc(required_major, minimum_minor):
# misleading. Solution: instead of using platform, use our code that actually
# works.
def libc_ver():
glibc_version = glibc_version_string()
if glibc_version is None:
# For non-glibc platforms, fall back on platform.libc_ver
return platform.libc_ver()
else:
return ("glibc", glibc_version)
"""Try to determine the glibc version
Returns a tuple of strings (lib, version) which default to empty strings
in case the lookup fails.
"""
glibc_version = glibc_version_string()
if glibc_version is None:
return ("", "")
else:
return ("glibc", glibc_version)
Loading

0 comments on commit b4e0d55

Please sign in to comment.