13
13
14
14
EXTENSION_SUFFIXES = [x [0 ] for x in imp .get_suffixes ()]
15
15
del imp
16
+ import collections
16
17
import logging
17
18
import os
18
19
import platform
57
58
_32_BIT_INTERPRETER = sys .maxsize <= 2 ** 32
58
59
59
60
61
+ _LEGACY_MANYLINUX_MAP = {
62
+ # CentOS 7 w/ glibc 2.17 (PEP 599)
63
+ (2 , 17 ): "manylinux2014" ,
64
+ # CentOS 6 w/ glibc 2.12 (PEP 571)
65
+ (2 , 12 ): "manylinux2010" ,
66
+ # CentOS 5 w/ glibc 2.5 (PEP 513)
67
+ (2 , 5 ): "manylinux1" ,
68
+ }
69
+
70
+ # If glibc ever changes its major version, we need to know what the last
71
+ # minor version was, so we can build the complete list of all versions.
72
+ # For now, guess what the highest minor version might be, assume it will
73
+ # be 50 for testing. Once this actually happens, update the dictionary
74
+ # with the actual value.
75
+ _LAST_GLIBC_MINOR = collections .defaultdict (lambda : 50 ) # type: Dict[int, int]
76
+ glibcVersion = collections .namedtuple ("Version" , ["major" , "minor" ])
77
+
78
+
60
79
class Tag (object ):
61
80
"""
62
81
A representation of the tag triple for a wheel.
@@ -416,19 +435,35 @@ def mac_platforms(version=None, arch=None):
416
435
)
417
436
418
437
419
- # From PEP 513.
420
- def _is_manylinux_compatible (name , glibc_version ):
421
- # type: (str, GlibcVersion) -> bool
438
+ # From PEP 513, PEP 600
439
+ def _is_manylinux_compatible (name , arch , glibc_version ):
440
+ # type: (str, str, GlibcVersion) -> bool
441
+ sys_glibc = _get_glibc_version ()
442
+ if sys_glibc < glibc_version :
443
+ return False
422
444
# Check for presence of _manylinux module.
423
445
try :
424
446
import _manylinux # noqa
425
-
426
- return bool (getattr (_manylinux , name + "_compatible" ))
427
- except (ImportError , AttributeError ):
428
- # Fall through to heuristic check below.
447
+ except ImportError :
429
448
pass
430
-
431
- return _have_compatible_glibc (* glibc_version )
449
+ else :
450
+ if hasattr (_manylinux , "manylinux_compatible" ):
451
+ result = _manylinux .manylinux_compatible (
452
+ glibc_version [0 ], glibc_version [1 ], arch
453
+ )
454
+ if result is not None :
455
+ return bool (result )
456
+ else :
457
+ if glibc_version == (2 , 5 ):
458
+ if hasattr (_manylinux , "manylinux1_compatible" ):
459
+ return bool (_manylinux .manylinux1_compatible )
460
+ if glibc_version == (2 , 12 ):
461
+ if hasattr (_manylinux , "manylinux2010_compatible" ):
462
+ return bool (_manylinux .manylinux2010_compatible )
463
+ if glibc_version == (2 , 17 ):
464
+ if hasattr (_manylinux , "manylinux2014_compatible" ):
465
+ return bool (_manylinux .manylinux2014_compatible )
466
+ return True
432
467
433
468
434
469
def _glibc_version_string ():
@@ -505,10 +540,9 @@ def _glibc_version_string_ctypes():
505
540
return version_str
506
541
507
542
508
- # Separated out from have_compatible_glibc for easier unit testing.
509
- def _check_glibc_version (version_str , required_major , minimum_minor ):
510
- # type: (str, int, int) -> bool
511
- # Parse string and check against requested version.
543
+ def _parse_glibc_version (version_str ):
544
+ # type: (str) -> Tuple[int, int]
545
+ # Parse glibc version.
512
546
#
513
547
# We use a regexp instead of str.split because we want to discard any
514
548
# random junk that might come after the minor version -- this might happen
@@ -521,19 +555,23 @@ def _check_glibc_version(version_str, required_major, minimum_minor):
521
555
" got: %s" % version_str ,
522
556
RuntimeWarning ,
523
557
)
524
- return False
525
- return (
526
- int (m .group ("major" )) == required_major
527
- and int (m .group ("minor" )) >= minimum_minor
528
- )
558
+ return - 1 , - 1
559
+ return (int (m .group ("major" )), int (m .group ("minor" )))
560
+
529
561
562
+ _glibc_version = [] # type: List[Tuple[int, int]]
530
563
531
- def _have_compatible_glibc (required_major , minimum_minor ):
532
- # type: (int, int) -> bool
564
+
565
+ def _get_glibc_version ():
566
+ # type: () -> Tuple[int, int]
567
+ if _glibc_version :
568
+ return _glibc_version [0 ]
533
569
version_str = _glibc_version_string ()
534
570
if version_str is None :
535
- return False
536
- return _check_glibc_version (version_str , required_major , minimum_minor )
571
+ _glibc_version .append ((- 1 , - 1 ))
572
+ else :
573
+ _glibc_version .append (_parse_glibc_version (version_str ))
574
+ return _glibc_version [0 ]
537
575
538
576
539
577
# Python does not provide platform information at sufficient granularity to
@@ -651,7 +689,42 @@ def _have_compatible_manylinux_abi(arch):
651
689
return _is_linux_armhf ()
652
690
if arch == "i686" :
653
691
return _is_linux_i686 ()
654
- return True
692
+ return arch in {"x86_64" , "aarch64" , "ppc64" , "ppc64le" , "s390x" }
693
+
694
+
695
+ def _manylinux_tags (linux , arch ):
696
+ # type: (str, str) -> Iterator[str]
697
+ # Oldest glibc to be supported regardless of architecture is (2, 17).
698
+ too_old_glibc2 = glibcVersion (2 , 16 )
699
+ if arch in {"x86_64" , "i686" }:
700
+ # On x86/i686 also oldest glibc to be supported is (2, 5).
701
+ too_old_glibc2 = glibcVersion (2 , 4 )
702
+ current_glibc = glibcVersion (* _get_glibc_version ())
703
+ glibc_max_list = [current_glibc ]
704
+ # We can assume compatibility across glibc major versions.
705
+ # https://sourceware.org/bugzilla/show_bug.cgi?id=24636
706
+ #
707
+ # Build a list of maximum glibc versions so that we can
708
+ # output the canonical list of all glibc from current_glibc
709
+ # down to too_old_glibc2, including all intermediary versions.
710
+ for glibc_major in range (current_glibc .major - 1 , 1 , - 1 ):
711
+ glibc_max_list .append (glibcVersion (glibc_major , _LAST_GLIBC_MINOR [glibc_major ]))
712
+ for glibc_max in glibc_max_list :
713
+ if glibc_max .major == too_old_glibc2 .major :
714
+ min_minor = too_old_glibc2 .minor
715
+ else :
716
+ # For other glibc major versions oldest supported is (x, 0).
717
+ min_minor = - 1
718
+ for glibc_minor in range (glibc_max .minor , min_minor , - 1 ):
719
+ glibc_version = (glibc_max .major , glibc_minor )
720
+ tag = "manylinux_{}_{}" .format (* glibc_version )
721
+ if _is_manylinux_compatible (tag , arch , glibc_version ):
722
+ yield linux .replace ("linux" , tag )
723
+ # Handle the legacy manylinux1, manylinux2010, manylinux2014 tags.
724
+ if glibc_version in _LEGACY_MANYLINUX_MAP :
725
+ legacy_tag = _LEGACY_MANYLINUX_MAP [glibc_version ]
726
+ if _is_manylinux_compatible (legacy_tag , arch , glibc_version ):
727
+ yield linux .replace ("linux" , legacy_tag )
655
728
656
729
657
730
def _linux_platforms (is_32bit = _32_BIT_INTERPRETER ):
@@ -662,28 +735,10 @@ def _linux_platforms(is_32bit=_32_BIT_INTERPRETER):
662
735
linux = "linux_i686"
663
736
elif linux == "linux_aarch64" :
664
737
linux = "linux_armv7l"
665
- manylinux_support = []
666
738
_ , arch = linux .split ("_" , 1 )
667
739
if _have_compatible_manylinux_abi (arch ):
668
- if arch in {"x86_64" , "i686" , "aarch64" , "armv7l" , "ppc64" , "ppc64le" , "s390x" }:
669
- manylinux_support .append (
670
- ("manylinux2014" , (2 , 17 ))
671
- ) # CentOS 7 w/ glibc 2.17 (PEP 599)
672
- if arch in {"x86_64" , "i686" }:
673
- manylinux_support .append (
674
- ("manylinux2010" , (2 , 12 ))
675
- ) # CentOS 6 w/ glibc 2.12 (PEP 571)
676
- manylinux_support .append (
677
- ("manylinux1" , (2 , 5 ))
678
- ) # CentOS 5 w/ glibc 2.5 (PEP 513)
679
- manylinux_support_iter = iter (manylinux_support )
680
- for name , glibc_version in manylinux_support_iter :
681
- if _is_manylinux_compatible (name , glibc_version ):
682
- yield linux .replace ("linux" , name )
683
- break
684
- # Support for a later manylinux implies support for an earlier version.
685
- for name , _ in manylinux_support_iter :
686
- yield linux .replace ("linux" , name )
740
+ for tag in _manylinux_tags (linux , arch ):
741
+ yield tag
687
742
yield linux
688
743
689
744
0 commit comments