Skip to content

Commit 0af040c

Browse files
committed
musllinux test updates and wheels, py3.11 beta wheels
1 parent 475bad7 commit 0af040c

File tree

12 files changed

+97
-24
lines changed

12 files changed

+97
-24
lines changed

.github/workflows/ci.yaml

Lines changed: 32 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ jobs:
3333
- spec: cp38-manylinux_x86_64
3434
- spec: cp39-manylinux_x86_64
3535
- spec: cp310-manylinux_x86_64
36+
- spec: cp311-manylinux_x86_64
3637
- spec: cp27-manylinux_i686
3738
cibw_version: cibuildwheel<2.0 # py2.7 is not supported on CIBW 2.0+
3839
manylinux_img: manylinux1 # build really old Pythons on manylinux1
@@ -42,32 +43,41 @@ jobs:
4243
- spec: cp38-manylinux_i686
4344
- spec: cp39-manylinux_i686
4445
- spec: cp310-manylinux_i686
46+
- spec: cp311-manylinux_i686
47+
- spec: cp39-musllinux_x86_64
48+
- spec: cp310-musllinux_x86_64
49+
- spec: cp311-musllinux_x86_64
50+
- spec: cp39-musllinux_i686
51+
- spec: cp310-musllinux_i686
52+
- spec: cp311-musllinux_i686
4553
steps:
4654
- name: clone repo
4755
uses: actions/checkout@v2
4856

4957
- name: build/test wheels
5058
env:
59+
CFLAGS: -Dffi_call=cffistatic_ffi_call # override name for ffi_call to break hard if we linked against someone else's libffi
5160
CIBW_ARCHS_LINUX: auto
5261
CIBW_BUILD: ${{ matrix.spec }}
5362
CIBW_BEFORE_BUILD: |
5463
set -eux && \
5564
curl -L -O https://github.com/libffi/libffi/archive/v3.4.2.tar.gz && \
5665
tar zxf v3.4.2.tar.gz && cd libffi-3.4.2 && \
5766
./autogen.sh && \
58-
./configure --without-gcc-arch --disable-docs && \
67+
./configure --without-gcc-arch --disable-docs --with-pic --enable-shared=no && \
5968
make && \
6069
make install && \
61-
ldconfig
62-
# TODO: update default to '' once CIBW 2.1.3 ships: https://github.com/pypa/cibuildwheel/pull/829
63-
CIBW_MANYLINUX_X86_64_IMAGE: ${{ matrix.manylinux_img || 'manylinux2010' }}
64-
CIBW_MANYLINUX_I686_IMAGE: ${{ matrix.manylinux_img || 'manylinux2010' }}
70+
ldconfig || true
71+
CIBW_ENVIRONMENT_PASS_LINUX: CFLAGS # ensure that the build container can see our overridden build config
72+
CIBW_MANYLINUX_X86_64_IMAGE: ${{ matrix.manylinux_img || '' }}
73+
CIBW_MANYLINUX_I686_IMAGE: ${{ matrix.manylinux_img || '' }}
74+
CIBW_PRERELEASE_PYTHONS: 'True'
6575
CIBW_TEST_REQUIRES: pytest
66-
CIBW_TEST_COMMAND: python -m pytest {project}/c {project}/testing
76+
CIBW_TEST_COMMAND: PYTHONUNBUFFERED=1 python -m pytest {project}
6777
run: |
6878
python -m pip install --upgrade "${{ matrix.cibw_version || 'cibuildwheel' }}"
6979
70-
# actually build libyaml + wheel (using env tweaks above)
80+
# actually build libffi + wheel (using env tweaks above)
7181
python -m cibuildwheel --output-dir dist .
7282
7383
@@ -94,6 +104,7 @@ jobs:
94104
- spec: cp38-macosx_x86_64
95105
- spec: cp39-macosx_x86_64
96106
- spec: cp310-macosx_x86_64
107+
- spec: cp311-macosx_x86_64
97108
# build for arm64 under a hacked macOS 12 self-hosted x86_64-on-arm64 runner until arm64 is fully supported
98109
# FIXME: ? cp38-macosx_arm64 requires special handling and fails some test_zdist tests under cibw 2.1.2, skip it (so Apple's XCode python3 won't have a wheel)
99110
- spec: cp39-macosx_arm64
@@ -107,6 +118,14 @@ jobs:
107118
runs_on: [self-hosted, macOS]
108119
run_wrapper: arch -arm64 bash --noprofile --norc -eo pipefail {0}
109120
sdkroot: macosx11.3
121+
122+
- spec: cp311-macosx_arm64
123+
deployment_target: '11.0'
124+
runs_on: [self-hosted, macOS]
125+
run_wrapper: arch -arm64 bash --noprofile --norc -eo pipefail {0}
126+
sdkroot: macosx11.3
127+
128+
110129
steps:
111130
- name: clone repo
112131
uses: actions/checkout@v2
@@ -119,8 +138,9 @@ jobs:
119138
- name: build/test wheels
120139
env:
121140
CIBW_BUILD: ${{ matrix.spec }}
141+
CIBW_PRERELEASE_PYTHONS: 'True'
122142
CIBW_TEST_REQUIRES: pytest
123-
CIBW_TEST_COMMAND: pip install pip --upgrade; cd {project}; pytest
143+
CIBW_TEST_COMMAND: pip install pip --upgrade; cd {project}; PYTHONUNBUFFERED=1 pytest
124144
run: |
125145
if [[ -n "${{ matrix.deployment_target || '' }}" ]]
126146
then
@@ -141,7 +161,7 @@ jobs:
141161
if-no-files-found: error
142162

143163
windows:
144-
runs-on: windows-2016
164+
runs-on: windows-2019
145165
strategy:
146166
matrix:
147167
include:
@@ -152,13 +172,15 @@ jobs:
152172
- spec: cp38-win_amd64
153173
- spec: cp39-win_amd64
154174
- spec: cp310-win_amd64
175+
- spec: cp311-win_amd64
155176
- spec: cp27-win32
156177
cibw_version: cibuildwheel==1.10 # last release with proper py2.7 Windows support
157178
- spec: cp36-win32
158179
- spec: cp37-win32
159180
- spec: cp38-win32
160181
- spec: cp39-win32
161182
- spec: cp310-win32
183+
- spec: cp311-win32
162184
steps:
163185
- name: clone repo
164186
uses: actions/checkout@v2
@@ -180,6 +202,7 @@ jobs:
180202
- name: build/test wheels
181203
env:
182204
CIBW_BUILD: ${{ matrix.spec }}
205+
CIBW_PRERELEASE_PYTHONS: 'True'
183206
run: |
184207
python -m pip install --upgrade pip
185208
pip install "${{ matrix.cibw_version || 'cibuildwheel'}}"

c/test_c.py

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,15 @@
11
import py
22
import pytest
3+
import sys
4+
5+
is_musl = False
6+
if sys.platform == 'linux':
7+
try:
8+
from packaging.tags import platform_tags
9+
is_musl = any(t.startswith('musllinux') for t in platform_tags())
10+
del platform_tags
11+
except ImportError:
12+
pass
313

414
def _setup_path():
515
import os, sys
@@ -93,7 +103,8 @@ def test_all_rtld_symbols():
93103
if sys.platform.startswith("linux"):
94104
RTLD_NODELETE
95105
RTLD_NOLOAD
96-
RTLD_DEEPBIND
106+
if not is_musl:
107+
RTLD_DEEPBIND
97108

98109
def test_new_primitive_type():
99110
py.test.raises(KeyError, new_primitive_type, "foo")
@@ -1296,7 +1307,7 @@ def test_read_variable_as_unknown_length_array():
12961307
def test_write_variable():
12971308
## FIXME: this test assumes glibc specific behavior, it's not compliant with C standard
12981309
## https://bugs.pypy.org/issue1643
1299-
if not sys.platform.startswith("linux"):
1310+
if not sys.platform.startswith("linux") or is_musl:
13001311
py.test.skip("untested")
13011312
BVoidP = new_pointer_type(new_void_type())
13021313
ll = find_and_load_library('c')

setup.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,11 @@ def use_homebrew_for_libffi():
156156
include_dirs.append('/usr/local/include')
157157
library_dirs.append('/usr/local/lib')
158158

159+
forced_extra_objs = os.environ.get('CFFI_FORCE_STATIC', [])
160+
if forced_extra_objs:
161+
forced_extra_objs = forced_extra_objs.split(';')
162+
163+
159164
if __name__ == '__main__':
160165
from setuptools import setup, Distribution, Extension
161166

@@ -209,6 +214,7 @@ def has_ext_modules(self):
209214
library_dirs=library_dirs,
210215
extra_compile_args=extra_compile_args,
211216
extra_link_args=extra_link_args,
217+
extra_objects=forced_extra_objs,
212218
)] if cpython else [],
213219

214220
install_requires=[

testing/cffi0/test_function.py

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,21 +5,29 @@
55
import ctypes.util
66
from cffi.backend_ctypes import CTypesBackend
77
from testing.udir import udir
8-
from testing.support import FdWriteCapture, StdErrCapture
8+
from testing.support import FdWriteCapture, StdErrCapture, is_musl
99
from .backend_tests import needs_dlopen_none
1010

1111
try:
1212
from StringIO import StringIO
1313
except ImportError:
1414
from io import StringIO
1515

16+
try:
17+
from packaging.tags import platform_tags
18+
_platform_tags_cached = set(platform_tags())
19+
_is_musl = any(t.startswith('musllinux') for t in _platform_tags_cached)
20+
except ImportError:
21+
_is_musl = False
1622

1723
lib_m = 'm'
1824
if sys.platform == 'win32':
1925
#there is a small chance this fails on Mingw via environ $CC
2026
import distutils.ccompiler
2127
if distutils.ccompiler.get_default_compiler() == 'msvc':
2228
lib_m = 'msvcrt'
29+
elif is_musl:
30+
lib_m = 'c'
2331

2432
class TestFunction(object):
2533
Backend = CTypesBackend
@@ -165,11 +173,15 @@ def test_vararg(self):
165173
ffi.cast("long long", 168))
166174
ffi.C.fprintf(ffi.C.stderr, b"hello %p\n", ffi.NULL)
167175
res = fd.getvalue()
176+
if is_musl:
177+
nil_repr = b'0'
178+
else:
179+
nil_repr = b'(nil)'
168180
assert res == (b"hello with no arguments\n"
169181
b"hello, world!\n"
170182
b"hello, world2!\n"
171183
b"hello int 42 long 84 long long 168\n"
172-
b"hello (nil)\n")
184+
b"hello " + nil_repr + b"\n")
173185

174186
def test_must_specify_type_of_vararg(self):
175187
ffi = FFI(backend=self.Backend())
@@ -265,7 +277,7 @@ def test_passing_array(self):
265277
assert res == 5
266278

267279
def test_write_variable(self):
268-
if not sys.platform.startswith('linux'):
280+
if not sys.platform.startswith('linux') or _is_musl:
269281
py.test.skip("probably no symbol 'stdout' in the lib")
270282
ffi = FFI(backend=self.Backend())
271283
ffi.cdef("""

testing/cffi0/test_ownlib.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
import subprocess, weakref
33
from cffi import FFI
44
from cffi.backend_ctypes import CTypesBackend
5-
from testing.support import u
5+
from testing.support import u, is_musl
66

77

88
SOURCE = """\
@@ -388,7 +388,7 @@ def test_modify_struct_value(self):
388388
def test_dlopen_handle(self):
389389
if self.module is None:
390390
py.test.skip("fix the auto-generation of the tiny test lib")
391-
if sys.platform == 'win32':
391+
if sys.platform == 'win32' or is_musl:
392392
py.test.skip("uses 'dl' explicitly")
393393
if self.__class__.Backend is CTypesBackend:
394394
py.test.skip("not for the ctypes backend")

testing/cffi0/test_parsing.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import py, sys, re
22
from cffi import FFI, FFIError, CDefError, VerificationError
33
from .backend_tests import needs_dlopen_none
4+
from testing.support import is_musl
45

56

67
class FakeBackend(object):
@@ -80,6 +81,9 @@ def __init__(self, BType, name):
8081
import distutils.ccompiler
8182
if distutils.ccompiler.get_default_compiler() == 'msvc':
8283
lib_m = 'msvcrt'
84+
elif is_musl:
85+
lib_m = 'c'
86+
8387

8488
def test_simple():
8589
ffi = FFI(backend=FakeBackend())

testing/cffi0/test_unicode_literals.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,17 @@
99
#
1010
import sys, math
1111
from cffi import FFI
12+
from testing.support import is_musl
13+
1214

1315
lib_m = "m"
1416
if sys.platform == 'win32':
1517
#there is a small chance this fails on Mingw via environ $CC
1618
import distutils.ccompiler
1719
if distutils.ccompiler.get_default_compiler() == 'msvc':
1820
lib_m = 'msvcrt'
21+
elif is_musl:
22+
lib_m = 'c'
1923

2024

2125
def test_cast():

testing/cffi0/test_verify.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import sys, os, math, weakref
44
from cffi import FFI, VerificationError, VerificationMissing, model, FFIError
55
from testing.support import *
6-
from testing.support import extra_compile_args
6+
from testing.support import extra_compile_args, is_musl
77

88

99
lib_m = ['m']
@@ -1609,7 +1609,7 @@ def test_keepalive_ffi():
16091609
assert func() == 42
16101610

16111611
def test_FILE_stored_in_stdout():
1612-
if not sys.platform.startswith('linux'):
1612+
if not sys.platform.startswith('linux') or is_musl:
16131613
py.test.skip("likely, we cannot assign to stdout")
16141614
ffi = FFI()
16151615
ffi.cdef("int printf(const char *, ...); FILE *setstdout(FILE *);")

testing/cffi1/test_cffi_binary.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
import py, sys, os
22
import _cffi_backend
3+
from testing.support import is_musl
34

45
def test_no_unknown_exported_symbols():
56
if not hasattr(_cffi_backend, '__file__'):
67
py.test.skip("_cffi_backend module is built-in")
7-
if not sys.platform.startswith('linux'):
8+
if not sys.platform.startswith('linux') or is_musl:
89
py.test.skip("linux-only")
910
g = os.popen("objdump -T '%s'" % _cffi_backend.__file__, 'r')
1011
for line in g:
@@ -17,6 +18,9 @@ def test_no_unknown_exported_symbols():
1718
name = line.split()[-1]
1819
if name.startswith('_') or name.startswith('.'):
1920
continue
20-
if name not in ('init_cffi_backend', 'PyInit__cffi_backend'):
21+
# a statically-linked libffi will always appear here without header hackage, ignore it if it's internal
22+
if name.startswith('ffi_') and 'Base' in line:
23+
continue
24+
if name not in ('init_cffi_backend', 'PyInit__cffi_backend', 'cffistatic_ffi_call'):
2125
raise Exception("Unexpected exported name %r" % (name,))
2226
g.close()

testing/cffi1/test_re_python.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from cffi import FFI
44
from cffi import recompiler, ffiplatform, VerificationMissing
55
from testing.udir import udir
6-
from testing.support import u
6+
from testing.support import u, is_musl
77

88

99
def setup_module(mod):
@@ -269,7 +269,7 @@ def test_selfref():
269269
def test_dlopen_handle():
270270
import _cffi_backend
271271
from re_python_pysrc import ffi
272-
if sys.platform == 'win32':
272+
if sys.platform == 'win32' or is_musl:
273273
py.test.skip("uses 'dl' explicitly")
274274
ffi1 = FFI()
275275
ffi1.cdef("""void *dlopen(const char *filename, int flags);

0 commit comments

Comments
 (0)