From cac515eb3d8627c14dba53dbda0a1867326acc11 Mon Sep 17 00:00:00 2001 From: Daniele Nicolodi Date: Sun, 19 Jul 2026 21:27:08 +0200 Subject: [PATCH 1/8] TST: add Rust extension module using PyO3 This requires nightly Rust and unreleased Meson, and it currently bumps into a Meson warning: ``WARNING: Library entry portable_atomic has unexpected keys "doc-scrape-examples"``. --- tests/conftest.py | 4 + tests/packages/rust-pyo3/Cargo.lock | 132 ++++++++++++++++++ tests/packages/rust-pyo3/Cargo.toml | 15 ++ tests/packages/rust-pyo3/meson.build | 17 +++ tests/packages/rust-pyo3/pyproject.toml | 10 ++ tests/packages/rust-pyo3/src/lib.rs | 16 +++ .../packages/rust-pyo3/subprojects/.wraplock | 0 tests/test_wheel.py | 9 ++ 8 files changed, 203 insertions(+) create mode 100644 tests/packages/rust-pyo3/Cargo.lock create mode 100644 tests/packages/rust-pyo3/Cargo.toml create mode 100644 tests/packages/rust-pyo3/meson.build create mode 100644 tests/packages/rust-pyo3/pyproject.toml create mode 100644 tests/packages/rust-pyo3/src/lib.rs create mode 100644 tests/packages/rust-pyo3/subprojects/.wraplock diff --git a/tests/conftest.py b/tests/conftest.py index be9b52b6a..f4267cbe3 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -224,6 +224,10 @@ def __init__(self, source_dir, build_dir, meson_args=None, editable_verbose=None # keeps working. 'link-against-local-lib', + # The ``rust-pyo3`` package bumps into this Meson + # warning: ``WARNING: Library entry portable_atomic + # has unexpected keys "doc-scrape-examples"``. + 'rust-pyo3', }: if meson_args is None: meson_args = {} diff --git a/tests/packages/rust-pyo3/Cargo.lock b/tests/packages/rust-pyo3/Cargo.lock new file mode 100644 index 000000000..987d29276 --- /dev/null +++ b/tests/packages/rust-pyo3/Cargo.lock @@ -0,0 +1,132 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "libc" +version = "0.2.186" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" + +[[package]] +name = "once_cell" +version = "1.21.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" + +[[package]] +name = "portable-atomic" +version = "1.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d20d5497ef88037a52ff98267d066e7f11fcc5e99bbfbd58a42336193aacec3" + +[[package]] +name = "proc-macro2" +version = "1.0.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "pyo3" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd274650b21d4bfc26a0a47587962c1edb425f69287324355cd040c3ea66071c" +dependencies = [ + "libc", + "once_cell", + "portable-atomic", + "pyo3-build-config", + "pyo3-ffi", + "pyo3-macros", +] + +[[package]] +name = "pyo3-build-config" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5e2a7d2f0d013342f295c048ad19237add5154a55b1c5a254c0ec93d4109078" +dependencies = [ + "target-lexicon", +] + +[[package]] +name = "pyo3-ffi" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca85c467da1bbc8d866eea5deff9cf29ea5f7785054a17da36e65bda9c05845b" +dependencies = [ + "libc", + "pyo3-build-config", +] + +[[package]] +name = "pyo3-macros" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ac53762fd065daa3194dd09337a38bd793a188100fd1a9304c4ab312d901771" +dependencies = [ + "proc-macro2", + "pyo3-macros-backend", + "quote", + "syn", +] + +[[package]] +name = "pyo3-macros-backend" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ca3a1557399783172dc5bf39cfca835157732532cba56b71d2292161e53b362" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "pyo3-mesonpy" +version = "0.1.0" +dependencies = [ + "pyo3", +] + +[[package]] +name = "quote" +version = "1.0.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfbc457d0c7a0759a614551b11a6409e5951f6c7537be1f1b7682b9ae9230368" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "syn" +version = "2.0.119" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "872831b642d1a07999a962a351ed35b955ea2cfc8f3862091e2a240a84f17297" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "target-lexicon" +version = "0.13.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adb6935a6f5c20170eeceb1a3835a49e12e19d792f6dd344ccc76a985ca5a6ca" + +[[package]] +name = "unicode-ident" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" diff --git a/tests/packages/rust-pyo3/Cargo.toml b/tests/packages/rust-pyo3/Cargo.toml new file mode 100644 index 000000000..f1dbda72e --- /dev/null +++ b/tests/packages/rust-pyo3/Cargo.toml @@ -0,0 +1,15 @@ +# SPDX-FileCopyrightText: 2026 The meson-python developers +# +# SPDX-License-Identifier: MIT + +[package] +name = "rust-pyo3" +version = "1.0.0" +edition = "2024" + +[lib] +name = "rust_pyo3" +crate-type = ["cdylib"] + +[dependencies] +pyo3 = "0.29.0" diff --git a/tests/packages/rust-pyo3/meson.build b/tests/packages/rust-pyo3/meson.build new file mode 100644 index 000000000..ee2b45b73 --- /dev/null +++ b/tests/packages/rust-pyo3/meson.build @@ -0,0 +1,17 @@ +# SPDX-FileCopyrightText: 2026 The meson-python developers +# +# SPDX-License-Identifier: MIT + +project('rust-pyo3', 'c', 'rust', version: '1.0.0', meson_version: '>= 1.12.0', default_options: ['rust_std=2024']) + +py = import('python').find_installation(pure: false) +pkg = import('rust').workspace().package() + +py.extension_module( + 'rust_pyo3', + 'src/lib.rs', + rust_dependency_map : pkg.rust_dependency_map(), + rust_args: pkg.rust_args(), + dependencies : pkg.dependencies(), + install: true, +) diff --git a/tests/packages/rust-pyo3/pyproject.toml b/tests/packages/rust-pyo3/pyproject.toml new file mode 100644 index 000000000..8f494d51c --- /dev/null +++ b/tests/packages/rust-pyo3/pyproject.toml @@ -0,0 +1,10 @@ +# SPDX-FileCopyrightText: 2021 The meson-python developers +# +# SPDX-License-Identifier: MIT + +[build-system] +build-backend = "mesonpy" +requires = ["meson-python"] + +[tool.meson-python.args] +setup = ['--vsenv'] diff --git a/tests/packages/rust-pyo3/src/lib.rs b/tests/packages/rust-pyo3/src/lib.rs new file mode 100644 index 000000000..1b6bb9fc3 --- /dev/null +++ b/tests/packages/rust-pyo3/src/lib.rs @@ -0,0 +1,16 @@ +// SPDX-FileCopyrightText: 2026 The meson-python developers +// +// SPDX-License-Identifier: MIT + +use pyo3::prelude::*; + +#[pymodule] +mod rust_pyo3 { + use pyo3::prelude::*; + + /// Sum two numbers. + #[pyfunction] + fn sum(a: i64, b: i64) -> PyResult { + Ok(a + b) + } +} diff --git a/tests/packages/rust-pyo3/subprojects/.wraplock b/tests/packages/rust-pyo3/subprojects/.wraplock new file mode 100644 index 000000000..e69de29bb diff --git a/tests/test_wheel.py b/tests/test_wheel.py index 2fdf7a5a0..919408510 100644 --- a/tests/test_wheel.py +++ b/tests/test_wheel.py @@ -413,3 +413,12 @@ def test_limited_api_free_threaded(wheel_limited_api_free_threaded): assert name.group('pyver') == INTERPRETER assert name.group('abi') == 'abi3.abi3t' if FREE_THREADED_BUILD else 'abi3' assert name.group('plat') == PLATFORM + + +@pytest.mark.skipif(MESON_VERSION < (1, 12, 0), reason='meson too old') +@pytest.mark.skipif(not shutil.which('rustc'), reason='rust compiler not found') +@pytest.mark.skipif(sys.platform == 'win32' and not os.getenv('CI'), reason='requires MSVC') +def test_rust_pyo3(venv, wheel_rust_pyo3): + venv.pip('install', wheel_rust_pyo3) + output = venv.python('-c', 'import rust_pyo3; print(rust_pyo3.sum(1, 2))') + assert int(output) == 3 From 0a03df8b3d1fd79239823b60607b4ade21af0af3 Mon Sep 17 00:00:00 2001 From: Daniele Nicolodi Date: Sun, 19 Jul 2026 21:38:11 +0200 Subject: [PATCH 2/8] CI: Set up Rust compiler --- .github/workflows/tests.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 4f837e5af..2dc514002 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -136,6 +136,9 @@ jobs: run: python -m pip install ${{ matrix.dependencies }} if: ${{ matrix.dependencies }} + - name: Set up Rust compiler + run: rustup override set nightly + - name: Install run: python -m pip install . --group test From 21bc0cf6b03da6320e5763410ce72ccf18de7b36 Mon Sep 17 00:00:00 2001 From: Daniele Nicolodi Date: Mon, 20 Jul 2026 09:52:13 +0200 Subject: [PATCH 3/8] debug --- .github/workflows/tests.yml | 279 +----------------------------------- 1 file changed, 7 insertions(+), 272 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 2dc514002..8c943702d 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -34,288 +34,23 @@ concurrency: cancel-in-progress: true jobs: - test: - runs-on: ${{ matrix.os }} - strategy: - fail-fast: false - matrix: - os: - - ubuntu-latest - - windows-latest - - macos-latest - # GitHub Actions switched to macOS on amr64 by default. Keep - # a job running on macOS on x86-64 for a while longer. - - macos-15-intel - python: - - '3.9' - - '3.15' - meson: - - - dependencies: - - - include: - - os: ubuntu-latest - python: 'pypy-3.9' - - os: ubuntu-latest - python: 'pypy-3.11' - - os: ubuntu-latest - python: '3.10' - # Test with older supported Meson version. Meson up to - # version 1.2.3 requires distutils, which has been removed - # from the stdlib in Python 3.12, thus test with Pythn 3.11. - # To avoid having too many CI jobs, combine this with tests - # with the minimum version of other dependencies. - - os: ubuntu-latest - python: '3.11' - meson: '~=0.64.0' - - os: ubuntu-latest - python: '3.11' - meson: '~=1.0.0' - - os: ubuntu-latest - python: '3.11' - meson: '~=1.1.0' - - os: ubuntu-latest - python: '3.12' - meson: '~=1.2.3' - - os: ubuntu-latest - python: '3.12' - meson: '~=1.3.0' - - os: ubuntu-latest - python: '3.12' - meson: '~=1.4.0' - - os: ubuntu-latest - python: '3.12' - meson: '~=1.5.0' - dependencies: 'packaging==23.2 pyproject-metadata==0.9.0' - - os: ubuntu-latest - python: '3.12' - meson: '~=1.6.0' - dependencies: 'pyproject-metadata==0.9.0' - - os: ubuntu-latest - python: '3.12' - meson: '~=1.7.0' - dependencies: 'packaging==23.2' - - os: ubuntu-latest - python: '3.13' - meson: '~=1.8.0' - # Test with Meson master branch. - - os: ubuntu-latest - python: '3.14' - meson: '@git+https://github.com/mesonbuild/meson.git' - - os: windows-latest - python: '3.14' - meson: '@git+https://github.com/mesonbuild/meson.git' - - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Set up target Python - uses: actions/setup-python@v5 - with: - python-version: ${{ matrix.python }} - allow-prereleases: true - - - name: Install Ninja - run: sudo apt-get install ninja-build - if: ${{ runner.os == 'Linux' }} - - - name: Install Ninja - run: brew install ninja - if: ${{ runner.os == 'macOS' }} - - - name: Install Ninja - run: python -m pip install ninja - if: ${{ runner.os == 'Windows' }} - - - name: Install Meson - run: python -m pip install "meson ${{ matrix.meson }}" - if: ${{ matrix.meson }} - - - name: Install dependencies - run: python -m pip install ${{ matrix.dependencies }} - if: ${{ matrix.dependencies }} - - - name: Set up Rust compiler - run: rustup override set nightly - - - name: Install - run: python -m pip install . --group test - - - name: Run tests - run: python -m pytest --showlocals -vv --cov --cov-report=xml - - - name: Upload coverage report - uses: codecov/codecov-action@v4 - if: ${{ always() }} - env: - CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} - - msvc: + debug: runs-on: windows-latest strategy: fail-fast: false - matrix: - python: - - '3.11' - meson: - - - steps: - - name: Checkout - uses: actions/checkout@v4 + - uses: actions/checkout@v4 - - name: Set up target Python - uses: actions/setup-python@v5 + - uses: actions/setup-python@v5 with: python-version: ${{ matrix.python }} - - name: Install Ninja - run: python -m pip install ninja + - run: python -m pip install ninja - - name: Setup MSVC - uses: bus1/cabuild/action/msdevshell@e22aba57d6e74891d059d66501b6b5aed8123c4d # v1 + - uses: bus1/cabuild/action/msdevshell@e22aba57d6e74891d059d66501b6b5aed8123c4d # v1 with: architecture: x64 - - name: Install Meson - run: python -m pip install "meson ${{ matrix.meson }}" - if: ${{ matrix.meson }} - - - name: Install - run: python -m pip install . --group test - - - name: Run tests - run: python -m pytest --showlocals -vv - - cygwin: - runs-on: windows-latest - strategy: - fail-fast: false - matrix: - python: - - '3.9' - meson: - - - - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Setup Cygwin - uses: cygwin/cygwin-install-action@v2 - with: - packages: >- - python39 - python39-devel - python39-pip - python39-setuptools - cmake - gcc-core - gcc-g++ - git - make - ninja - - - name: Fix git dubious ownership - # This addresses the "fatal: detected dubious ownership in - # repository" and "fatal: not in a git directory" errors - # encountered when trying to run Cygwin git in a directory not - # owned by the current user. This happens when the tests run - # Cygwin git in a directory outside the Cygwin filesystem. - run: git config --global --add safe.directory '*' - shell: C:\cygwin\bin\env.exe CYGWIN_NOWINPATH=1 CHERE_INVOKING=1 C:\cygwin\bin\bash.exe -leo pipefail -o igncr {0} - - - name: Get pip cache path - id: pip-cache-path - run: echo "path=$(cygpath -w $(python -m pip cache dir))" >> $GITHUB_OUTPUT - shell: C:\cygwin\bin\env.exe CYGWIN_NOWINPATH=1 CHERE_INVOKING=1 C:\cygwin\bin\bash.exe -leo pipefail -o igncr {0} - - - name: Restore cache - # Cygwin Python cannot use binary wheels from PyPI. Building - # some dependencies takes considerable time. Caching the built - # wheels speeds up the CI job quite a bit. - uses: actions/cache@v4 - with: - path: ${{ steps.pip-cache-path.outputs.path }} - key: cygwin-pip-${{ github.sha }} - restore-keys: cygwin-pip- - - - name: Install Meson - run: python -m pip install "meson ${{ matrix.meson }}" - if: ${{ matrix.meson }} - shell: C:\cygwin\bin\env.exe CYGWIN_NOWINPATH=1 CHERE_INVOKING=1 C:\cygwin\bin\bash.exe -leo pipefail -o igncr {0} - - - name: Install - # Cygwin patches Python's ensurepip module to look for the - # wheels needed to initialize a new virtual environment in - # /usr/share/python-wheels/ but nothing in Cygwin actually - # puts the setuptools and pip wheels there. Fix this. - run: | - mkdir /usr/share/python-wheels/ - pushd /usr/share/python-wheels/ - python -m pip download setuptools pip - popd - python -m pip install . --group test - shell: C:\cygwin\bin\env.exe CYGWIN_NOWINPATH=1 CHERE_INVOKING=1 C:\cygwin\bin\bash.exe -leo pipefail -o igncr {0} - - - name: Run tests - run: python -m pytest --showlocals -vv - shell: C:\cygwin\bin\env.exe CYGWIN_NOWINPATH=1 CHERE_INVOKING=1 C:\cygwin\bin\bash.exe -leo pipefail -o igncr {0} - - homebrew: - runs-on: macos-latest - strategy: - fail-fast: false - matrix: - python: - - '3.9' - - '3.12' - meson: - - - - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Install Homebrew Python - run: | - brew install --overwrite python@${{ matrix.python }} - echo /opt/homebrew/opt/python@${{ matrix.python }}/libexec/bin/ >> $GITHUB_PATH - python${{ matrix.python }} -m pip config set global.break-system-packages true - - - name: Check Python version - run: python --version | grep ${{ matrix.python }} - - - name: Install Ninja - run: brew install ninja - - - name: Install Meson - run: python -m pip install "meson ${{ matrix.meson }}" - if: ${{ matrix.meson }} - - - name: Install - run: python -m pip install . --group test - - - name: Run tests - run: python -m pytest --showlocals -vv - - mypy: - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Setup Python - uses: actions/setup-python@v5 - with: - python-version: 3.9 - - - name: Install dependencies - run: python -m pip install . - - - name: Install mypy - run: python -m pip install mypy~=1.19 + - run: python -m pip install "meson @git+https://github.com/mesonbuild/meson.git" - - name: Run mypy - run: mypy -p mesonpy + - run: meson setup tests/packages/rust-pyo3 _build --vsenv || cat _build/meson-logs/meson-log.txt From 60447437d3ead401825dd8b3d6d3645c9598d54a Mon Sep 17 00:00:00 2001 From: Daniele Nicolodi Date: Mon, 20 Jul 2026 13:01:34 +0200 Subject: [PATCH 4/8] more debug --- .github/workflows/tests.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 8c943702d..30725abd7 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -53,4 +53,8 @@ jobs: - run: python -m pip install "meson @git+https://github.com/mesonbuild/meson.git" - - run: meson setup tests/packages/rust-pyo3 _build --vsenv || cat _build/meson-logs/meson-log.txt + - run: meson setup tests/packages/rust-pyo3 _build_rust --vsenv || cat _build_rust/meson-logs/meson-log.txt + - run: meson compile -C _build_rust -v || true + + - run: meson setup tests/packages/purelib-and-platlib _build_c + - run: meson compile -C _build_c -v From 5ba5b94140d5e2fcbb3b0a4870dd9c8ccb33c753 Mon Sep 17 00:00:00 2001 From: Daniele Nicolodi Date: Mon, 20 Jul 2026 13:14:53 +0200 Subject: [PATCH 5/8] debug --- .github/workflows/tests.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 30725abd7..540ea60c3 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -53,6 +53,8 @@ jobs: - run: python -m pip install "meson @git+https://github.com/mesonbuild/meson.git" + - run: rustup override set nightly + - run: meson setup tests/packages/rust-pyo3 _build_rust --vsenv || cat _build_rust/meson-logs/meson-log.txt - run: meson compile -C _build_rust -v || true From 3da41eabfd6cb8d0b87843694d2af5ba911c70e9 Mon Sep 17 00:00:00 2001 From: Daniele Nicolodi Date: Mon, 20 Jul 2026 13:20:46 +0200 Subject: [PATCH 6/8] debug --- .github/workflows/tests.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 540ea60c3..9c4bb0801 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -55,8 +55,8 @@ jobs: - run: rustup override set nightly - - run: meson setup tests/packages/rust-pyo3 _build_rust --vsenv || cat _build_rust/meson-logs/meson-log.txt + - run: meson setup tests/packages/rust-pyo3 _build_rust --vsenv -Dbuildtype=release - run: meson compile -C _build_rust -v || true - - run: meson setup tests/packages/purelib-and-platlib _build_c + - run: meson setup tests/packages/purelib-and-platlib _build_c -Dbuildtype=release - run: meson compile -C _build_c -v From ddc010cac7d3ffa56e06954c5e3aa2142fa889cf Mon Sep 17 00:00:00 2001 From: Daniele Nicolodi Date: Mon, 20 Jul 2026 22:12:21 +0200 Subject: [PATCH 7/8] fixup --- tests/packages/rust-pyo3/Cargo.lock | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/packages/rust-pyo3/Cargo.lock b/tests/packages/rust-pyo3/Cargo.lock index 987d29276..623686088 100644 --- a/tests/packages/rust-pyo3/Cargo.lock +++ b/tests/packages/rust-pyo3/Cargo.lock @@ -92,13 +92,6 @@ dependencies = [ "syn", ] -[[package]] -name = "pyo3-mesonpy" -version = "0.1.0" -dependencies = [ - "pyo3", -] - [[package]] name = "quote" version = "1.0.46" @@ -108,6 +101,13 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "rust-pyo3" +version = "1.0.0" +dependencies = [ + "pyo3", +] + [[package]] name = "syn" version = "2.0.119" From 4398766d164cd0cdc4426eb51e0e3c13f0bdc5c4 Mon Sep 17 00:00:00 2001 From: Daniele Nicolodi Date: Mon, 20 Jul 2026 22:12:55 +0200 Subject: [PATCH 8/8] packagefiles --- .../pyo3-0.29-rs/meson/meson.build | 1 + .../packagefiles/pyo3-ffi-0.29-rs/meson.build | 203 ++++++++++++++++++ .../pyo3-ffi-0.29-rs/meson.options | 31 +++ 3 files changed, 235 insertions(+) create mode 100644 tests/packages/rust-pyo3/subprojects/packagefiles/pyo3-0.29-rs/meson/meson.build create mode 100644 tests/packages/rust-pyo3/subprojects/packagefiles/pyo3-ffi-0.29-rs/meson.build create mode 100644 tests/packages/rust-pyo3/subprojects/packagefiles/pyo3-ffi-0.29-rs/meson.options diff --git a/tests/packages/rust-pyo3/subprojects/packagefiles/pyo3-0.29-rs/meson/meson.build b/tests/packages/rust-pyo3/subprojects/packagefiles/pyo3-0.29-rs/meson/meson.build new file mode 100644 index 000000000..3c9bad296 --- /dev/null +++ b/tests/packages/rust-pyo3/subprojects/packagefiles/pyo3-0.29-rs/meson/meson.build @@ -0,0 +1 @@ +extra_args = cargo_ws.subproject('pyo3-ffi', pkg_obj.api(), native: false).dependency().get_variable('cfgs').split() diff --git a/tests/packages/rust-pyo3/subprojects/packagefiles/pyo3-ffi-0.29-rs/meson.build b/tests/packages/rust-pyo3/subprojects/packagefiles/pyo3-ffi-0.29-rs/meson.build new file mode 100644 index 000000000..ac1d8fb79 --- /dev/null +++ b/tests/packages/rust-pyo3/subprojects/packagefiles/pyo3-ffi-0.29-rs/meson.build @@ -0,0 +1,203 @@ +project( + 'pyo3-ffi', + 'rust', + meson_version : '>= 1.12', + version : '0.29.0', + #default_options : {'warning_level' : '0'}, + license : 'MIT OR Apache-2.0' +) + +PY_MAX_VER = 15 + +rust = import('rust') +fs = import('fs') +cargo_ws = rust.workspace() +pkg_obj = cargo_ws.package('pyo3-ffi', native : false) + +# --- deprecated cargo features ----------------------------------------------- +features = pkg_obj.features() +message('Enabled features:', features) + +if features.contains('extension-module') + warning('the extension-module cargo feature is deprecated; ' + + 'use the extension_module Meson option instead or meson-python >= ...') +endif +if features.contains('generate-import-lib') + warning('the generate-import-lib cargo feature is deprecated; ' + + 'Windows linking is governed by the use_raw_dylib Meson option') +endif + +# --- conversion of build.rs starts here -------------------------------------- + +py_mod = import('python') +if get_option('python') == '' + py = py_mod.find_installation() +else + py = py_mod.find_installation(get_option('python')) +endif +py_minor = py.language_version().split('.')[1].to_int() + +is_windows = host_machine.system() == 'windows' +gil_disabled = py.get_variable('Py_GIL_DISABLED', 0) == 1 +py_debug = py.get_variable('Py_DEBUG', 0) == 1 + +extra_args = [] +extra_deps = [] + +# Implementation detection. Meson's python module has no direct +# `implementation` accessor so use SOABI. +soabi = py.get_variable('SOABI', 'cpython') +is_pypy = soabi.startswith('pypy') +extra_args += ['--check-cfg', 'cfg(PyPy)'] +extra_args += ['--check-cfg', 'cfg(GraalPy)'] +extra_args += ['--check-cfg', 'cfg(RustPython)'] +if is_pypy + extra_args += ['--cfg', 'PyPy'] +endif + +# --- version / ABI ----------------------------------------------------------- + +if features.contains('abi3t') + if not gil_disabled + error('abi3t required but Python is not free-threaded') + endif + abi = '3t' + abi3 = true +elif features.contains('abi3') + if gil_disabled + error('abi3 required but Python is free-threaded') + endif + abi = '3' + abi3 = true +else + abi = f'3@py_minor@' + (gil_disabled ? 't' : '') + abi3 = false +endif + +# Cumulative Py_3_X cfgs up to the interpreter version, or up to the abi3 +# floor when abi3 is in effect. This is the equivalent of allow_limited_api +# in py.extension_module() for C. +cfg_max = py_minor +extra_args += ['--check-cfg', 'cfg(Py_LIMITED_API)'] +if abi3 + if is_pypy + error('abi3 required but PyPy does not support it') + endif + if is_windows and py_debug + error('no stable-ABI python3.dll exists for debug CPython on Windows') + endif + + extra_args += ['--cfg', 'Py_LIMITED_API'] + foreach f : features + if f.startswith('abi3-py3') + floor = f.substring(8).to_int() # 'abi3-py312' -> 12 + elif f.startswith('abi3t-py3') + floor = f.substring(9).to_int() + else + continue + endif + cfg_max = floor < cfg_max ? floor : cfg_max + endforeach +endif + +extra_args += ['--check-cfg', 'cfg(Py_GIL_DISABLED)'] +if gil_disabled + extra_args += ['--cfg', 'Py_GIL_DISABLED'] +endif + +foreach m : range(8, cfg_max + 1) + extra_args += ['--cfg', f'Py_3_@m@'] +endforeach +foreach m : range(8, PY_MAX_VER + 1) + extra_args += ['--check-cfg', f'cfg(Py_3_@m@)'] +endforeach + +# --- debug CPython ----------------------------------------------------------- + +foreach flag : ['Py_DEBUG', 'Py_REF_DEBUG', 'Py_TRACE_REFS', 'COUNT_ALLOCS'] + extra_args += ['--check-cfg', f'cfg(py_sys_config,values("@flag@"))'] + if py.get_variable(flag, 0) == 1 + extra_args += ['--cfg', f'py_sys_config="@flag@"'] + endif +endforeach + +# --- Windows linking model --------------------------------------------------- + +use_raw_dylib = get_option('use_raw_dylib') \ + .require(is_windows, error_message : 'raw-dylib linking is Windows-only') \ + .disable_auto_if(not is_windows) \ + .allowed() + +extra_args += ['--check-cfg', 'cfg(pyo3_use_raw_dylib)'] +extra_args += ['--check-cfg', 'cfg(pyo3_dll,values(any()))'] +if is_windows + # DLL/import-lib base name; must match build.rs. + # abi3 CPython: python3 + # release CPython: python3XY (abi3: python3) + # free-threaded: python3XYt + # debug CPython: python3XY_d (no abi3 import lib/DLL exists + # for debug builds, guarded above) + # free-threaded + debug: python3XYt_d + if is_pypy + # mirror build.rs, which hardcodes the PyPy lib name (currently 3.11) + py_lib_name = f'libpypy3.@py_minor@-c' + else + py_lib_name = 'python' + abi + (py_debug ? '_d' : '') + endif + + if use_raw_dylib + # rustc synthesizes the import information itself + extra_args += [ + '--cfg', 'pyo3_use_raw_dylib', + '--cfg', f'pyo3_dll="@py_lib_name@.dll"', + ] + message(f'Using raw_dylib @py_lib_name@.dll') + else + # PYO3_USE_RAW_DYLIB=0 analogue. Meson does not generally pass -l/-L + # options for individual crates, but without -l at compile time, rustc + # emits direct references to extern statics and link.exe fails with + # unresolved PyModule_Type/PyExc_* on all data symbols. So this has + # to be hand-rolled instead of being just `extra_deps += py.dependency()`. + # Meson should actually leave -L/-l in place for external dependencies. + py_libs_dir = py.get_variable('installed_base', py.get_variable('base')) / 'libs' + if not fs.is_dir(py_libs_dir) + error(f'Python import library directory not found: @py_libs_dir@\n' + + 'This Python installation cannot be linked without raw-dylib; ' + + 'leave the use_raw_dylib option enabled.') + endif + extra_args += [ + '-L', f'native=@py_libs_dir@', + '-l', py_lib_name, + ] + message(f'Using import library @0@.lib'.format(py_libs_dir / py_lib_name)) + endif +else + # Unix: extension modules never link libpython (symbols come from the + # hosting interpreter; the superproject's py.extension_module() target owns + # the Python dependency), only embedding links it. + # + # FIXME: Setting pyo3-ffi:extension_module should be done by meson-python; + # for now, the default is true instead. + if not get_option('extension_module') + extra_deps += py.dependency(embed : true) + endif +endif + +# --------- + +lib = pkg_obj.library('pyo3_ffi', dependencies : extra_deps, rust_args : extra_args) +dep = declare_dependency( + link_with : lib, + variables : { + 'features' : ','.join(features), + + # other pyo3 crates can use these, though in general + # it doesn't matter much because of --cap-lints allow + 'cfgs' : ' '.join(extra_args), + 'python' : py.full_path(), + 'extension_module' : get_option('extension_module').to_string(), + 'raw_dylib' : use_raw_dylib.to_string(), + }, + version : pkg_obj.version() +) +pkg_obj.override_dependency(dep) diff --git a/tests/packages/rust-pyo3/subprojects/packagefiles/pyo3-ffi-0.29-rs/meson.options b/tests/packages/rust-pyo3/subprojects/packagefiles/pyo3-ffi-0.29-rs/meson.options new file mode 100644 index 000000000..22c5f9606 --- /dev/null +++ b/tests/packages/rust-pyo3/subprojects/packagefiles/pyo3-ffi-0.29-rs/meson.options @@ -0,0 +1,31 @@ +# Options for the pyo3-ffi subproject. + +option( + 'python', + type : 'string', + value : '', + description : 'Name/path passed to import(\'python\').find_installation(). ' + + 'Empty (default) means no argument, i.e. the interpreter running ' + + 'Meson / sys.executable. Superprojects (e.g. meson-python) may set ' + + 'this to pin a different interpreter.', +) + +option( + 'use_raw_dylib', + type : 'feature', + value : 'auto', + description : 'Use raw-dylib linking on Windows (Meson analogue of PYO3_USE_RAW_DYLIB). ' + + 'When disabled, a Python import library (/libs/pythonXY.lib) is required ' + + 'and is passed to rustc at pyo3-ffi compile time. Windows-only; auto = enabled.', +) + +option( + 'extension_module', + type : 'boolean', + value : true, # <--- should be value : false perhaps when supported by meson-python?? + yield : true, + description : 'Build for a Python extension module: do not link libpython on Unix ' + + '(Meson analogue of PYO3_BUILD_EXTENSION_MODULE). Superprojects building ' + + 'extensions with py.extension_module() should enable this; the extension ' + + 'target itself provides the Python dependency. Leave false for embedding.', +)