19
19
from elftools .elf .elffile import ELFFile
20
20
21
21
from auditwheel .architecture import Architecture
22
+ from auditwheel .libc import Libc
22
23
from auditwheel .policy import WheelPolicies
23
24
24
25
logger = logging .getLogger (__name__ )
25
26
26
- ENCODING = "utf-8"
27
- PLATFORM = Architecture . get_native_architecture (). value
27
+ NATIVE_PLATFORM = Architecture . get_native_architecture (). value
28
+ PLATFORM = os . environ . get ( "AUDITWHEEL_ARCH" , NATIVE_PLATFORM )
28
29
MANYLINUX1_IMAGE_ID = f"quay.io/pypa/manylinux1_{ PLATFORM } :latest"
29
30
MANYLINUX2010_IMAGE_ID = f"quay.io/pypa/manylinux2010_{ PLATFORM } :latest"
30
31
MANYLINUX2014_IMAGE_ID = f"quay.io/pypa/manylinux2014_{ PLATFORM } :latest"
31
32
MANYLINUX_2_28_IMAGE_ID = f"quay.io/pypa/manylinux_2_28_{ PLATFORM } :latest"
33
+ MANYLINUX_2_31_IMAGE_ID = f"quay.io/pypa/manylinux_2_31_{ PLATFORM } :latest"
32
34
MANYLINUX_2_34_IMAGE_ID = f"quay.io/pypa/manylinux_2_34_{ PLATFORM } :latest"
33
35
if PLATFORM in {"i686" , "x86_64" }:
34
36
MANYLINUX_IMAGES = {
35
37
"manylinux_2_5" : MANYLINUX1_IMAGE_ID ,
36
38
"manylinux_2_12" : MANYLINUX2010_IMAGE_ID ,
37
39
"manylinux_2_17" : MANYLINUX2014_IMAGE_ID ,
38
- "manylinux_2_28" : MANYLINUX_2_28_IMAGE_ID ,
39
- "manylinux_2_34" : MANYLINUX_2_34_IMAGE_ID ,
40
40
}
41
+ if PLATFORM == "x86_64" :
42
+ MANYLINUX_IMAGES .update (
43
+ {
44
+ "manylinux_2_28" : MANYLINUX_2_28_IMAGE_ID ,
45
+ "manylinux_2_34" : MANYLINUX_2_34_IMAGE_ID ,
46
+ }
47
+ )
41
48
POLICY_ALIASES = {
42
49
"manylinux_2_5" : ["manylinux1" ],
43
50
"manylinux_2_12" : ["manylinux2010" ],
44
51
"manylinux_2_17" : ["manylinux2014" ],
45
52
}
53
+ elif PLATFORM == "armv7l" :
54
+ MANYLINUX_IMAGES = {"manylinux_2_31" : MANYLINUX_2_31_IMAGE_ID }
55
+ POLICY_ALIASES = {}
46
56
else :
47
57
MANYLINUX_IMAGES = {
48
58
"manylinux_2_17" : MANYLINUX2014_IMAGE_ID ,
49
59
"manylinux_2_28" : MANYLINUX_2_28_IMAGE_ID ,
50
- "manylinux_2_34" : MANYLINUX_2_34_IMAGE_ID ,
51
60
}
61
+ if os .environ .get ("AUDITWHEEL_QEMU" , "" ) != "true" :
62
+ MANYLINUX_IMAGES .update ({"manylinux_2_34" : MANYLINUX_2_34_IMAGE_ID })
52
63
POLICY_ALIASES = {
53
64
"manylinux_2_17" : ["manylinux2014" ],
54
65
}
67
78
"manylinux_2_12" : "devtoolset-8" ,
68
79
"manylinux_2_17" : "devtoolset-10" ,
69
80
"manylinux_2_28" : "gcc-toolset-14" ,
81
+ "manylinux_2_31" : "devtoolset-not-present" ,
70
82
"manylinux_2_34" : "gcc-toolset-14" ,
71
83
"musllinux_1_2" : "devtoolset-not-present" ,
72
84
}
@@ -265,6 +277,12 @@ def docker_start(
265
277
client = docker .from_env ()
266
278
267
279
dvolumes = {host : {"bind" : ctr , "mode" : "rw" } for (ctr , host ) in volumes .items ()}
280
+ goarch = {
281
+ "x86_64" : "amd64" ,
282
+ "i686" : "386" ,
283
+ "aarch64" : "arm64" ,
284
+ "armv7l" : "arm/v7" ,
285
+ }.get (PLATFORM , PLATFORM )
268
286
269
287
logger .info ("Starting container with image %r" , image )
270
288
con = client .containers .run (
@@ -273,6 +291,7 @@ def docker_start(
273
291
detach = True ,
274
292
volumes = dvolumes ,
275
293
environment = env_variables ,
294
+ platform = f"linux/{ goarch } " ,
276
295
)
277
296
logger .info ("Started container %s" , con .id [:12 ])
278
297
return con
@@ -316,7 +335,7 @@ def docker_exec(
316
335
) -> str :
317
336
logger .info ("docker exec %s: %r" , container .id [:12 ], cmd )
318
337
ec , output = container .exec_run (cmd , workdir = cwd , environment = env )
319
- output = output .decode (ENCODING )
338
+ output = output .decode ("utf-8" )
320
339
if ec != expected_retcode :
321
340
print (output )
322
341
raise CalledProcessError (ec , cmd , output = output )
@@ -386,12 +405,16 @@ def build_numpy(container: AnyLinuxContainer, output_dir: Path) -> str:
386
405
# https://github.com/numpy/numpy/issues/27932
387
406
fix_hwcap = "echo '#define HWCAP_S390_VX 2048' >> /usr/include/bits/hwcap.h"
388
407
container .exec (f'sh -c "{ fix_hwcap } "' )
389
- elif container .policy .startswith (( "manylinux_2_28_" , "manylinux_2_34_" )):
390
- container . exec ( "dnf install -y openblas-devel " )
391
- else :
408
+ elif container .policy .startswith (
409
+ ( "manylinux_2_5_" , "manylinux_2_12_" , "manylinux_2_17_ " )
410
+ ) :
392
411
if tuple (int (part ) for part in NUMPY_VERSION .split ("." )[:2 ]) >= (1 , 26 ):
393
412
pytest .skip ("numpy>=1.26 requires openblas" )
394
413
container .exec ("yum install -y atlas atlas-devel" )
414
+ elif container .policy .startswith ("manylinux_2_31_" ):
415
+ container .exec ("apt-get install -y libopenblas-dev" )
416
+ else :
417
+ container .exec ("dnf install -y openblas-devel" )
395
418
396
419
cached_wheel = container .cache_dir / ORIGINAL_NUMPY_WHEEL
397
420
orig_wheel = output_dir / ORIGINAL_NUMPY_WHEEL
@@ -466,7 +489,6 @@ def test_numpy(self, anylinux: AnyLinuxContainer, python: PythonContainer) -> No
466
489
if policy .startswith ("musllinux_" ):
467
490
python .exec ("apk add musl-dev gfortran" )
468
491
else :
469
- python .exec ("apt-get update -yqq" )
470
492
python .exec ("apt-get install -y gfortran" )
471
493
if tuple (int (part ) for part in NUMPY_VERSION .split ("." )[:2 ]) >= (1 , 26 ):
472
494
python .pip_install ("meson ninja" )
@@ -498,6 +520,8 @@ def test_with_binary_executable(
498
520
policy = anylinux .policy
499
521
if policy .startswith ("musllinux_" ):
500
522
anylinux .exec ("apk add gsl-dev" )
523
+ elif policy .startswith ("manylinux_2_31_" ):
524
+ anylinux .exec ("apt-get install -y libgsl-dev" )
501
525
else :
502
526
anylinux .exec ("yum install -y gsl-devel" )
503
527
@@ -768,9 +792,8 @@ class TestManylinux(Anylinux):
768
792
@pytest .fixture (scope = "session" )
769
793
def docker_python_img (self ):
770
794
"""The glibc Python base image with up-to-date pip"""
771
- with tmp_docker_image (
772
- MANYLINUX_PYTHON_IMAGE_ID , ["pip install -U pip" ]
773
- ) as img_id :
795
+ commnds = ["pip install -U pip" , "apt-get update -yqq" ]
796
+ with tmp_docker_image (MANYLINUX_PYTHON_IMAGE_ID , commnds ) as img_id :
774
797
yield img_id
775
798
776
799
@pytest .fixture (scope = "session" , params = MANYLINUX_IMAGES .keys ())
@@ -780,25 +803,23 @@ def any_manylinux_img(self, request):
780
803
Plus up-to-date pip, setuptools and pytest-cov
781
804
"""
782
805
policy = request .param
783
- support_check_map = {
806
+ check_set = {
784
807
"manylinux_2_5" : {"38" , "39" },
785
808
"manylinux_2_12" : {"38" , "39" , "310" },
786
- }
787
- check_set = support_check_map .get (policy )
809
+ }.get (policy )
788
810
if check_set and PYTHON_ABI_MAJ_MIN not in check_set :
789
811
pytest .skip (f"{ policy } images do not support cp{ PYTHON_ABI_MAJ_MIN } " )
790
812
791
813
base = MANYLINUX_IMAGES [policy ]
792
814
env = {"PATH" : PATH [policy ]}
793
- with tmp_docker_image (
794
- base ,
795
- [
796
- 'git config --global --add safe.directory "/auditwheel_src"' ,
797
- "pip install -U pip setuptools pytest-cov" ,
798
- "pip install -U -e /auditwheel_src" ,
799
- ],
800
- env ,
801
- ) as img_id :
815
+ commands = [
816
+ 'git config --global --add safe.directory "/auditwheel_src"' ,
817
+ "pip install -U pip setuptools pytest-cov" ,
818
+ "pip install -U -e /auditwheel_src" ,
819
+ ]
820
+ if policy == "manylinux_2_31" :
821
+ commands .append ("apt-get update -yqq" )
822
+ with tmp_docker_image (base , commands , env ) as img_id :
802
823
yield policy , img_id
803
824
804
825
@pytest .mark .parametrize ("with_dependency" , ["0" , "1" ])
@@ -824,7 +845,7 @@ def test_image_dependencies(
824
845
test_path , env = {"WITH_DEPENDENCY" : with_dependency }
825
846
)
826
847
827
- wheel_policy = WheelPolicies ()
848
+ wheel_policy = WheelPolicies (libc = Libc . GLIBC , arch = Architecture ( PLATFORM ) )
828
849
policy = wheel_policy .get_policy_by_name (policy_name )
829
850
older_policies = [
830
851
f"{ p } _{ PLATFORM } "
@@ -905,7 +926,9 @@ def test_compat(
905
926
906
927
def test_zlib_blacklist (self , anylinux : AnyLinuxContainer ) -> None :
907
928
policy = anylinux .policy
908
- if policy .startswith (("manylinux_2_17_" , "manylinux_2_28_" , "manylinux_2_34_" )):
929
+ if policy .startswith (
930
+ ("manylinux_2_17_" , "manylinux_2_28_" , "manylinux_2_31_" , "manylinux_2_34_" )
931
+ ):
909
932
pytest .skip (f"{ policy } image has no blacklist symbols in libz.so.1" )
910
933
911
934
test_path = "/auditwheel_src/tests/integration/testzlib"
@@ -925,9 +948,8 @@ class TestMusllinux(Anylinux):
925
948
@pytest .fixture (scope = "session" )
926
949
def docker_python_img (self ):
927
950
"""The alpine Python base image with up-to-date pip"""
928
- with tmp_docker_image (
929
- MUSLLINUX_PYTHON_IMAGE_ID , ["pip install -U pip" ]
930
- ) as img_id :
951
+ commands = ["pip install -U pip" ]
952
+ with tmp_docker_image (MUSLLINUX_PYTHON_IMAGE_ID , commands ) as img_id :
931
953
yield img_id
932
954
933
955
@pytest .fixture (scope = "session" , params = MUSLLINUX_IMAGES .keys ())
@@ -939,13 +961,10 @@ def any_manylinux_img(self, request):
939
961
policy = request .param
940
962
base = MUSLLINUX_IMAGES [policy ]
941
963
env = {"PATH" : PATH [policy ]}
942
- with tmp_docker_image (
943
- base ,
944
- [
945
- 'git config --global --add safe.directory "/auditwheel_src"' ,
946
- "pip install -U pip setuptools pytest-cov" ,
947
- "pip install -U -e /auditwheel_src" ,
948
- ],
949
- env ,
950
- ) as img_id :
964
+ commands = [
965
+ 'git config --global --add safe.directory "/auditwheel_src"' ,
966
+ "pip install -U pip setuptools pytest-cov" ,
967
+ "pip install -U -e /auditwheel_src" ,
968
+ ]
969
+ with tmp_docker_image (base , commands , env ) as img_id :
951
970
yield policy , img_id
0 commit comments