diff --git a/src/cffi/ffiplatform.py b/src/cffi/ffiplatform.py index adca28f1..3007f246 100644 --- a/src/cffi/ffiplatform.py +++ b/src/cffi/ffiplatform.py @@ -47,7 +47,7 @@ def _build(tmpdir, ext, compiler_verbose=0, debug=None): set_verbosity(compiler_verbose) dist.run_command('build_ext') cmd_obj = dist.get_command_obj('build_ext') - [soname] = cmd_obj.get_outputs() + soname = cmd_obj.get_ext_fullpath(ext.name) finally: set_threshold(old_level) except (CompileError, LinkError) as e: diff --git a/testing/cffi0/test_platform.py b/testing/cffi0/test_platform.py index 55446ec3..ed8c0fcd 100644 --- a/testing/cffi0/test_platform.py +++ b/testing/cffi0/test_platform.py @@ -1,4 +1,6 @@ import os +import pytest +from cffi import FFI from cffi.ffiplatform import maybe_relative_path, flatten @@ -23,3 +25,33 @@ def test_flatten(): assert flatten([4, 5]) == "2l4i5i" assert flatten({4: 5}) == "1d4i5i" assert flatten({"foo": ("bar", "baaz")}) == "1d3sfoo2l3sbar4sbaaz" + +@pytest.mark.thread_unsafe(reason="monkeypatches a shared distutils class method") +def test_compile_with_extra_build_ext_outputs(monkeypatch): + # Some setuptools/distutils versions can make build_ext.get_outputs() + # return more entries than the single extension we asked it to build + # (see https://github.com/python-cffi/cffi/issues/246, which is the + # same underlying unpacking crash reported in + # https://github.com/python-cffi/cffi/issues/229). Unpacking that list + # unconditionally used to raise a confusing + # "ValueError: too many values to unpack". + from cffi._shimmed_dist_utils import build_ext as real_build_ext + + original_get_outputs = real_build_ext.get_outputs + + def get_outputs_with_extra_entry(self): + return list(original_get_outputs(self)) + ['/nonexistent/other.so'] + + monkeypatch.setattr(real_build_ext, 'get_outputs', + get_outputs_with_extra_entry) + + # force a fresh module name/compile every run, so the monkeypatched + # get_outputs() above is actually exercised instead of reusing a + # previously-built module cached under the same checksum-derived name + tag = os.urandom(8).hex() + + ffi = FFI() + ffi.cdef("double test_platform_extra_outputs(double x);") + csrc = "double test_platform_extra_outputs(double x) { return x + 1.0; }" + lib = ffi.verify(csrc, tag=tag) + assert lib.test_platform_extra_outputs(41.0) == 42.0