diff --git a/.github/workflows/build_python.yml b/.github/workflows/build_python.yml index d756115f..7bb1ee80 100644 --- a/.github/workflows/build_python.yml +++ b/.github/workflows/build_python.yml @@ -100,8 +100,10 @@ jobs: -DLIBREMIDI_CI=1 - name: Build + shell: bash run: | - cmake --build build --config Debug + export ASAN_OPTIONS=detect_leaks=0 + ${{matrix.config.environment}} cmake --build build --config Debug - name: Test if: runner.os == 'Windows' diff --git a/bindings/python/CMakeLists.txt b/bindings/python/CMakeLists.txt index 3238741c..933b026a 100644 --- a/bindings/python/CMakeLists.txt +++ b/bindings/python/CMakeLists.txt @@ -11,7 +11,8 @@ set(LIBREMIDI_NEEDS_READERWRITERQUEUE 1) add_subdirectory(../.. libremidi-src) -find_package(Python 3.9 COMPONENTS Interpreter Development.Module REQUIRED) +find_package(Python 3.10 COMPONENTS Interpreter Development.Module REQUIRED) +find_package(Python 3.10 COMPONENTS Development.SABIModule QUIET) if(NOT readerwriterqueue_FOUND AND NOT TARGET readerwriterqueue) FetchContent_Declare( @@ -30,12 +31,26 @@ FetchContent_Declare( ) FetchContent_MakeAvailable(nanobind) -nanobind_add_module(pylibremidi pylibremidi.cpp) + +if(Python_VERSION VERSION_GREATER_EQUAL "3.12") + nanobind_add_module(pylibremidi STABLE_ABI NB_STATIC pylibremidi.cpp) +else() + nanobind_add_module(pylibremidi NB_STATIC pylibremidi.cpp) +endif() target_link_libraries(pylibremidi PUBLIC libremidi readerwriterqueue Boost::headers Boost::variant2 Boost::container) +nanobind_add_stub( + pylibremidi_stub + MODULE pylibremidi + OUTPUT pylibremidi.pyi + PYTHON_PATH $ + DEPENDS pylibremidi +) + install(TARGETS pylibremidi LIBRARY DESTINATION .) install( - FILES __init__.py + FILES ${CMAKE_CURRENT_BINARY_DIR}/pylibremidi.pyi DESTINATION . + OPTIONAL ) diff --git a/bindings/python/__init__.py b/bindings/python/__init__.py deleted file mode 100644 index 6eb86461..00000000 --- a/bindings/python/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from ._core import * diff --git a/pyproject.toml b/pyproject.toml index 47eda085..1f64ff11 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -113,8 +113,30 @@ cmake.source-dir = "./bindings/python" # Setuptools-style build caching in a local directory build-dir = "build/{wheel_tag}" -# Build stable ABI wheels for CPython 3.10+ -wheel.py-api = "cp310" - [tool.cibuildwheel] +# Build for Python 3.10, 3.11 (version-specific) and 3.12+ (stable ABI) +build = "cp310-* cp311-* cp312-*" +config-settings = "cmake.build-type=Release" + +# Skip 32-bit builds, musl, and PyPy +skip = "*-win32 *-manylinux_i686 *-musllinux_* pp*" + +[tool.cibuildwheel.linux] +archs = ["x86_64", "aarch64"] +# Use manylinux_2_28 for pipewire availability (AlmaLinux 8 based) +manylinux-x86_64-image = "manylinux_2_28" +manylinux-aarch64-image = "manylinux_2_28" +before-all = "dnf install -y alsa-lib-devel pipewire-devel jack-audio-connection-kit-devel" + +[tool.cibuildwheel.macos] +archs = ["x86_64", "arm64"] + +[tool.cibuildwheel.windows] +archs = ["AMD64", "ARM64"] + +# For Python 3.12+, use stable ABI +[[tool.cibuildwheel.overrides]] +select = "cp312-*" config-settings = "cmake.build-type=Release" +inherit.environment = "append" +environment = { SKBUILD_WHEEL_PY_API = "cp312" }