diff --git a/.github/workflows/pixi.lock b/.github/workflows/pixi.lock index 6d9754a3a..49fb18134 100644 --- a/.github/workflows/pixi.lock +++ b/.github/workflows/pixi.lock @@ -18,13 +18,14 @@ environments: - conda: https://prefix.dev/conda-forge/linux-aarch64/c-ares-1.34.8-h29ee22c_2.conda - conda: https://prefix.dev/conda-forge/linux-aarch64/c-compiler-2.0.0-h1f08cd5_0.conda - conda: https://prefix.dev/conda-forge/linux-aarch64/cmake-4.4.2-hcbeb305_2.conda - - conda: https://prefix.dev/conda-forge/linux-aarch64/conda-gcc-specs-15.3.0-hbdd0822_4.conda + - conda: https://prefix.dev/conda-forge/linux-aarch64/conda-gcc-specs-15.3.0-hbdd0822_7.conda - conda: https://prefix.dev/conda-forge/linux-aarch64/cxx-compiler-2.0.0-hf41333a_0.conda - conda: https://prefix.dev/conda-forge/linux-aarch64/cython-3.3.0-py314h1eee2f1_0.conda - - conda: https://prefix.dev/conda-forge/linux-aarch64/gcc-15.3.0-hfdd745d_4.conda - - conda: https://prefix.dev/conda-forge/linux-aarch64/gcc_impl_linux-aarch64-15.3.0-hfe63468_4.conda - - conda: https://prefix.dev/conda-forge/linux-aarch64/gxx-15.3.0-hfdd745d_4.conda - - conda: https://prefix.dev/conda-forge/linux-aarch64/gxx_impl_linux-aarch64-15.3.0-hcb04d1e_4.conda + - conda: https://prefix.dev/conda-forge/linux-aarch64/gcc-15.3.0-hfdd745d_7.conda + - conda: https://prefix.dev/conda-forge/linux-aarch64/gcc_impl_linux-aarch64-15.3.0-h543efd9_7.conda + - conda: https://prefix.dev/conda-forge/linux-aarch64/geos-3.15.0-h4125222_1.conda + - conda: https://prefix.dev/conda-forge/linux-aarch64/gxx-15.3.0-hfdd745d_7.conda + - conda: https://prefix.dev/conda-forge/linux-aarch64/gxx_impl_linux-aarch64-15.3.0-hcb04d1e_7.conda - conda: https://prefix.dev/conda-forge/linux-aarch64/icu-78.3-py311h3512406_2.conda - conda: https://prefix.dev/conda-forge/linux-aarch64/keyutils-1.6.3-h5bc82ec_1.conda - conda: https://prefix.dev/conda-forge/linux-aarch64/krb5-1.22.2-h095d8e5_2.conda @@ -40,7 +41,7 @@ environments: - conda: https://prefix.dev/conda-forge/linux-aarch64/libmpdec-4.0.0-he30d5cf_2.conda - conda: https://prefix.dev/conda-forge/linux-aarch64/libnghttp2-1.68.1-ha4b982d_1.conda - conda: https://prefix.dev/conda-forge/linux-aarch64/libpsl-0.23.1-hb8431ed_1.conda - - conda: https://prefix.dev/conda-forge/linux-aarch64/libsanitizer-15.3.0-he541324_4.conda + - conda: https://prefix.dev/conda-forge/linux-aarch64/libsanitizer-15.3.0-he541324_7.conda - conda: https://prefix.dev/conda-forge/linux-aarch64/libsqlite-3.53.4-h399dd60_1.conda - conda: https://prefix.dev/conda-forge/linux-aarch64/libssh2-1.11.1-h7572e3e_1.conda - conda: https://prefix.dev/conda-forge/linux-aarch64/libstdcxx-16.2.0-hef695bb_4.conda @@ -63,8 +64,8 @@ environments: - conda: https://prefix.dev/conda-forge/noarch/importlib-metadata-9.0.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/iniconfig-2.3.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/kernel-headers_linux-aarch64-4.18.0-h05a177a_9.conda - - conda: https://prefix.dev/conda-forge/noarch/libgcc-devel_linux-aarch64-15.3.0-h6e7e4e0_104.conda - - conda: https://prefix.dev/conda-forge/noarch/libstdcxx-devel_linux-aarch64-15.3.0-h0e8df58_104.conda + - conda: https://prefix.dev/conda-forge/noarch/libgcc-devel_linux-aarch64-15.3.0-h6e7e4e0_107.conda + - conda: https://prefix.dev/conda-forge/noarch/libstdcxx-devel_linux-aarch64-15.3.0-h0e8df58_107.conda - conda: https://prefix.dev/conda-forge/noarch/meson-1.12.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/packaging-26.3-pyhc364b38_0.conda - conda: https://prefix.dev/conda-forge/noarch/pip-26.2.1-pyh145f28c_0.conda @@ -82,6 +83,69 @@ environments: - conda: https://prefix.dev/conda-forge/noarch/tzdata-2026c-h151e31d_0.conda - conda: https://prefix.dev/conda-forge/noarch/wheel-0.48.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/zipp-4.1.0-pyhcf101f3_0.conda + system-compilers: + channels: + - url: https://prefix.dev/conda-forge/ + packages: + linux-aarch64: + - conda: https://prefix.dev/conda-forge/linux-aarch64/_openmp_mutex-4.5-20_gnu.conda + - conda: https://prefix.dev/conda-forge/linux-aarch64/bzip2-1.0.8-h4777abc_10.conda + - conda: https://prefix.dev/conda-forge/linux-aarch64/c-ares-1.34.8-h29ee22c_2.conda + - conda: https://prefix.dev/conda-forge/linux-aarch64/cmake-4.4.2-hcbeb305_2.conda + - conda: https://prefix.dev/conda-forge/linux-aarch64/cython-3.3.0-py314h1eee2f1_0.conda + - conda: https://prefix.dev/conda-forge/linux-aarch64/geos-3.15.0-h4125222_1.conda + - conda: https://prefix.dev/conda-forge/linux-aarch64/icu-78.3-py311h3512406_2.conda + - conda: https://prefix.dev/conda-forge/linux-aarch64/keyutils-1.6.3-h5bc82ec_1.conda + - conda: https://prefix.dev/conda-forge/linux-aarch64/krb5-1.22.2-h095d8e5_2.conda + - conda: https://prefix.dev/conda-forge/linux-aarch64/ld_impl_linux-aarch64-2.46.1-default_h1979696_102.conda + - conda: https://prefix.dev/conda-forge/linux-aarch64/libcurl-8.21.0-h86273da_5.conda + - conda: https://prefix.dev/conda-forge/linux-aarch64/libedit-3.1.20250104-pl5321hc48eb74_1.conda + - conda: https://prefix.dev/conda-forge/linux-aarch64/libev-4.33-h80f16a2_3.conda + - conda: https://prefix.dev/conda-forge/linux-aarch64/libexpat-2.8.1-hfae3067_1.conda + - conda: https://prefix.dev/conda-forge/linux-aarch64/libffi-3.7.0-h376a255_0.conda + - conda: https://prefix.dev/conda-forge/linux-aarch64/libgcc-16.2.0-h205dda4_4.conda + - conda: https://prefix.dev/conda-forge/linux-aarch64/libgomp-16.2.0-h8acb6b2_4.conda + - conda: https://prefix.dev/conda-forge/linux-aarch64/liblzma-5.8.3-he30d5cf_1.conda + - conda: https://prefix.dev/conda-forge/linux-aarch64/libmpdec-4.0.0-he30d5cf_2.conda + - conda: https://prefix.dev/conda-forge/linux-aarch64/libnghttp2-1.68.1-ha4b982d_1.conda + - conda: https://prefix.dev/conda-forge/linux-aarch64/libpsl-0.23.1-hb8431ed_1.conda + - conda: https://prefix.dev/conda-forge/linux-aarch64/libsqlite-3.53.4-h399dd60_1.conda + - conda: https://prefix.dev/conda-forge/linux-aarch64/libssh2-1.11.1-h7572e3e_1.conda + - conda: https://prefix.dev/conda-forge/linux-aarch64/libstdcxx-16.2.0-hef695bb_4.conda + - conda: https://prefix.dev/conda-forge/linux-aarch64/libuuid-2.42.2-h1022ec0_0.conda + - conda: https://prefix.dev/conda-forge/linux-aarch64/libuv-1.52.1-h80f16a2_1.conda + - conda: https://prefix.dev/conda-forge/linux-aarch64/libzlib-1.3.2-hdc9db2a_3.conda + - conda: https://prefix.dev/conda-forge/linux-aarch64/ncurses-6.6-h2b6f883_1.conda + - conda: https://prefix.dev/conda-forge/linux-aarch64/ninja-1.13.2-hdc560ac_1.conda + - conda: https://prefix.dev/conda-forge/linux-aarch64/openssl-3.6.3-h546c87b_1.conda + - conda: https://prefix.dev/conda-forge/linux-aarch64/patchelf-0.19.1-hfb11796_1.conda + - conda: https://prefix.dev/conda-forge/linux-aarch64/pkg-config-0.29.2-h36a561e_1011.conda + - conda: https://prefix.dev/conda-forge/linux-aarch64/python-3.14.7-h6bfacdd_100_cp314.conda + - conda: https://prefix.dev/conda-forge/linux-aarch64/readline-8.3-ha7194a6_1.conda + - conda: https://prefix.dev/conda-forge/linux-aarch64/rhash-1.4.6-he30d5cf_2.conda + - conda: https://prefix.dev/conda-forge/linux-aarch64/tk-8.6.13-noxft_hf03c496_4.conda + - conda: https://prefix.dev/conda-forge/linux-aarch64/zstd-1.5.7-h9d15635_7.conda + - conda: https://prefix.dev/conda-forge/noarch/ca-certificates-2026.7.22-hbd8a1cb_0.conda + - conda: https://prefix.dev/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_1.conda + - conda: https://prefix.dev/conda-forge/noarch/exceptiongroup-1.3.1-pyhd8ed1ab_0.conda + - conda: https://prefix.dev/conda-forge/noarch/importlib-metadata-9.0.0-pyhcf101f3_0.conda + - conda: https://prefix.dev/conda-forge/noarch/iniconfig-2.3.0-pyhd8ed1ab_0.conda + - conda: https://prefix.dev/conda-forge/noarch/meson-1.12.0-pyhcf101f3_0.conda + - conda: https://prefix.dev/conda-forge/noarch/packaging-26.3-pyhc364b38_0.conda + - conda: https://prefix.dev/conda-forge/noarch/pip-26.2.1-pyh145f28c_0.conda + - conda: https://prefix.dev/conda-forge/noarch/pluggy-1.6.0-pyhf9edf01_1.conda + - conda: https://prefix.dev/conda-forge/noarch/pygments-2.21.0-pyhcf101f3_0.conda + - conda: https://prefix.dev/conda-forge/noarch/pyproject-metadata-0.12.1-pyhd8ed1ab_0.conda + - conda: https://prefix.dev/conda-forge/noarch/pyproject_hooks-1.2.0-pyhd8ed1ab_1.conda + - conda: https://prefix.dev/conda-forge/noarch/pytest-9.1.1-pyhc364b38_2.conda + - conda: https://prefix.dev/conda-forge/noarch/pytest-mock-3.15.1-pyhd8ed1ab_0.conda + - conda: https://prefix.dev/conda-forge/noarch/python-build-1.5.0-pyhc364b38_0.conda + - conda: https://prefix.dev/conda-forge/noarch/python_abi-3.14-8_cp314.conda + - conda: https://prefix.dev/conda-forge/noarch/tomli-2.4.1-pyhcf101f3_0.conda + - conda: https://prefix.dev/conda-forge/noarch/typing_extensions-4.16.0-pyhcf101f3_0.conda + - conda: https://prefix.dev/conda-forge/noarch/tzdata-2026c-h151e31d_0.conda + - conda: https://prefix.dev/conda-forge/noarch/wheel-0.48.0-pyhd8ed1ab_0.conda + - conda: https://prefix.dev/conda-forge/noarch/zipp-4.1.0-pyhcf101f3_0.conda packages: - conda: https://prefix.dev/conda-forge/linux-aarch64/_openmp_mutex-4.5-20_gnu.conda build_number: 20 @@ -164,15 +228,16 @@ packages: run_exports: {} size: 25496912 timestamp: 1787209719745 -- conda: https://prefix.dev/conda-forge/linux-aarch64/conda-gcc-specs-15.3.0-hbdd0822_4.conda - sha256: d61e8e35090eac2af977f40d9b068fde2c3fdc3494f93230d955947709e4b581 - md5: afa5c705e03c6afce0228ff2283d6309 +- conda: https://prefix.dev/conda-forge/linux-aarch64/conda-gcc-specs-15.3.0-hbdd0822_7.conda + sha256: 972da393305529c4db79f3d8f34291586dd8767bbb5e75ff84e4fe2a365240eb + md5: 5f1cec36f1dbe50c6d8c9ccf84a8be8c depends: - gcc_impl_linux-aarch64 >=15.3.0,<15.3.1.0a0 license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL run_exports: {} - size: 32418 - timestamp: 1787617791870 + size: 32657 + timestamp: 1790302403105 - conda: https://prefix.dev/conda-forge/linux-aarch64/cxx-compiler-2.0.0-hf41333a_0.conda sha256: 0616c1e5f97cbcb505f0daa119ca8c9975caca02c84c5bc4ceb0ef65bf7648a3 md5: ce387759a5f3908b1273247b8660a048 @@ -195,55 +260,71 @@ packages: run_exports: {} size: 3955136 timestamp: 1787435574078 -- conda: https://prefix.dev/conda-forge/linux-aarch64/gcc-15.3.0-hfdd745d_4.conda - sha256: fc89612ee4e163923ba713a8814114e8c402054e79b85e32b75d1c38031b4362 - md5: 96724903f974e2151a077ec588bf9d7e +- conda: https://prefix.dev/conda-forge/linux-aarch64/gcc-15.3.0-hfdd745d_7.conda + sha256: 83761e8fe27e7ffc9134662bee77523f011299d7a781cceb3ee0300474748aa8 + md5: 3ee778b8a6192bf8f61687c3c44fb6c9 depends: - conda-gcc-specs - - gcc_impl_linux-aarch64 15.3.0 hfe63468_4 + - gcc_impl_linux-aarch64 15.3.0 h543efd9_7 license: BSD-3-Clause + license_family: BSD run_exports: {} - size: 29466 - timestamp: 1787617883836 -- conda: https://prefix.dev/conda-forge/linux-aarch64/gcc_impl_linux-aarch64-15.3.0-hfe63468_4.conda - sha256: 6039029f4ce021e0c49fb47824e981ba5d2863498c0855f78a73dc09a75cf151 - md5: a6a25fd37f554f88b36a0d03af7775fa + size: 29585 + timestamp: 1790302501803 +- conda: https://prefix.dev/conda-forge/linux-aarch64/gcc_impl_linux-aarch64-15.3.0-h543efd9_7.conda + sha256: b777f7fea75988191524a694b861222eef7d859b55ef200145bdb3559b243e54 + md5: 509460640a88cadf2c9a5a4734134f51 depends: - binutils_impl_linux-aarch64 >=2.46.1 - libgcc >=15.3.0 - - libgcc-devel_linux-aarch64 15.3.0 h6e7e4e0_104 + - libgcc-devel_linux-aarch64 15.3.0 h6e7e4e0_107 - libgomp >=15.3.0 - - libsanitizer 15.3.0 he541324_4 + - libsanitizer 15.3.0 he541324_7 - libstdcxx >=15.3.0 - - libstdcxx-devel_linux-aarch64 15.3.0 h0e8df58_104 + - libstdcxx-devel_linux-aarch64 15.3.0 h0e8df58_107 - sysroot_linux-aarch64 license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL run_exports: {} - size: 72956757 - timestamp: 1787617681639 -- conda: https://prefix.dev/conda-forge/linux-aarch64/gxx-15.3.0-hfdd745d_4.conda - sha256: 36cd033b6473c8bf782ea7ceee7704b2db43bc2070acb9981620f0e86db7ad8d - md5: a633104932da5d9d0add986193a9b45d + size: 75249934 + timestamp: 1790302274160 +- conda: https://prefix.dev/conda-forge/linux-aarch64/geos-3.15.0-h4125222_1.conda + sha256: fd9bc3de82aec81d91285fbe18b84c6fa94d55f6cd36364dd4b6c37ab8cbc10b + md5: 49e5818343217aff06b37c0d30ce6bfa + depends: + - libstdcxx >=15 + - libgcc >=15 + license: LGPL-2.1-only + run_exports: + weak: + - geos >=3.15.0,<3.15.1.0a0 + size: 2425569 + timestamp: 1789734780719 +- conda: https://prefix.dev/conda-forge/linux-aarch64/gxx-15.3.0-hfdd745d_7.conda + sha256: 1b378d9d5a0562e66363dacd64f5d0b2489e403cd5a6dd647b82ba45a63f95bd + md5: b0fc69e39425af4a983a5261a074c9a3 depends: - conda-gcc-specs - - gcc 15.3.0 hfdd745d_4 - - gxx_impl_linux-aarch64 15.3.0 hcb04d1e_4 + - gcc 15.3.0 hfdd745d_7 + - gxx_impl_linux-aarch64 15.3.0 hcb04d1e_7 license: BSD-3-Clause + license_family: BSD run_exports: {} - size: 28835 - timestamp: 1787617914335 -- conda: https://prefix.dev/conda-forge/linux-aarch64/gxx_impl_linux-aarch64-15.3.0-hcb04d1e_4.conda - sha256: e5a301d88d8902a8954adbf0c4a28b579960bae312d4bd6ba79463a20795a86e - md5: ba4fc57002f3425ed6a36496d299332d - depends: - - gcc_impl_linux-aarch64 15.3.0 hfe63468_4 - - libstdcxx-devel_linux-aarch64 15.3.0 h0e8df58_104 + size: 29012 + timestamp: 1790302530292 +- conda: https://prefix.dev/conda-forge/linux-aarch64/gxx_impl_linux-aarch64-15.3.0-hcb04d1e_7.conda + sha256: 25df4cff4be63cdb6c93693b7312b2d5fc71034955d2a7748893585e46605750 + md5: 1300d1ce6d51343ff98b59917686c5c3 + depends: + - gcc_impl_linux-aarch64 15.3.0 h543efd9_7 + - libstdcxx-devel_linux-aarch64 15.3.0 h0e8df58_107 - sysroot_linux-aarch64 - tzdata license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL run_exports: {} - size: 14747440 - timestamp: 1787617855670 + size: 15475341 + timestamp: 1790302472944 - conda: https://prefix.dev/conda-forge/linux-aarch64/icu-78.3-py311h3512406_2.conda sha256: 54d921defd947adb58a90e10203d3bfe6c1f209f5f1a1ad2c6a9f7617f2fb59e md5: b35bbb1b957440ed742f35fb96eb7f1c @@ -442,18 +523,19 @@ packages: - libpsl >=0.23.1,<0.24.0a0 size: 73118 timestamp: 1786970733378 -- conda: https://prefix.dev/conda-forge/linux-aarch64/libsanitizer-15.3.0-he541324_4.conda - sha256: fa1493b8ddd58f40ce4ef688a30cf93c0faf736f09821465e83d51d05475cb5c - md5: 82801a6523a59e75c3ca663a80ae810e +- conda: https://prefix.dev/conda-forge/linux-aarch64/libsanitizer-15.3.0-he541324_7.conda + sha256: 28bd5d6389f032a594dbc8cf6af4fbca85fb6b386dd85b6c8d3ce9cd13aa998b + md5: baffcd8b96bdc491b795ae6b979f806f depends: - libgcc >=15.3.0 - libstdcxx >=15.3.0 license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL run_exports: weak: - libsanitizer 15.3.0 - size: 7569114 - timestamp: 1787617645405 + size: 7284100 + timestamp: 1790302233451 - conda: https://prefix.dev/conda-forge/linux-aarch64/libsqlite-3.53.4-h399dd60_1.conda sha256: fae75e68e9dbc3c90dcf93d4bae6315f1330c95aaf1404a721e8468266c23475 md5: 27e16aa1f45c787aa181549be6f209f4 @@ -728,24 +810,26 @@ packages: run_exports: {} size: 1248134 timestamp: 1765578613607 -- conda: https://prefix.dev/conda-forge/noarch/libgcc-devel_linux-aarch64-15.3.0-h6e7e4e0_104.conda - sha256: 7082eeeef07bba617b778348267956db5d0bf84eb5f1b5fe6ada9fee4a6fad85 - md5: 4d59c62b87531bb11393daeb4b750c43 +- conda: https://prefix.dev/conda-forge/noarch/libgcc-devel_linux-aarch64-15.3.0-h6e7e4e0_107.conda + sha256: e26af963eeca0f3a9b17182b1686f3a08ad3a7633e2da92b95052b320a48480d + md5: 163cf0269dc64983bc6edf481a5557fb depends: - __unix license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL run_exports: {} - size: 2353577 - timestamp: 1787617542232 -- conda: https://prefix.dev/conda-forge/noarch/libstdcxx-devel_linux-aarch64-15.3.0-h0e8df58_104.conda - sha256: 648173a13da532b6599844d49243d40ba9baec655f7ddc5016cc567c89080a87 - md5: 248aa5cadf9dc07c7c893b3acde3da1b + size: 2346429 + timestamp: 1790302128084 +- conda: https://prefix.dev/conda-forge/noarch/libstdcxx-devel_linux-aarch64-15.3.0-h0e8df58_107.conda + sha256: 7c821bf495207ca0157b38a9d2c935356ed8dba096ffacd6676adb76c759b89c + md5: 709858d98ee8e0e91c4efddc6d02887f depends: - __unix license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL run_exports: {} - size: 17560431 - timestamp: 1787617560373 + size: 17521094 + timestamp: 1790302146011 - conda: https://prefix.dev/conda-forge/noarch/meson-1.12.0-pyhcf101f3_0.conda sha256: 6c158a48c43f0b2e03dd26521fe940991285fd149773aaeb5ead843b2bda92ca md5: 73afbaae293a0d6feed3a5559b6d4359 diff --git a/.github/workflows/pixi.toml b/.github/workflows/pixi.toml index 29aa24f0b..833abfffd 100644 --- a/.github/workflows/pixi.toml +++ b/.github/workflows/pixi.toml @@ -19,8 +19,7 @@ ninja = "*" pkg-config = "*" cmake = "*" patchelf = "*" -c-compiler = "*" -cxx-compiler = "*" +geos = "*" pip = "*" python-build = "*" cython = "*" @@ -28,5 +27,13 @@ pytest = "*" pytest-mock = "*" wheel = "*" +[feature.compilers.dependencies] +c-compiler = "*" +cxx-compiler = "*" + +[environments] +default = { features = ["compilers"], solve-group = "test" } +system-compilers = { features = [], solve-group = "test" } + [tasks] test = { cmd = "pytest", cwd = "../.." } diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 10c492ca7..339bf30a2 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -336,7 +336,16 @@ jobs: run: mypy -p mesonpy pixi: + name: ${{ matrix.name }} runs-on: ubuntu-24.04-arm + strategy: + fail-fast: false + matrix: + include: + - name: pixi + environment: default + - name: pixi-system-compilers + environment: system-compilers steps: - name: Checkout uses: actions/checkout@v7 @@ -347,11 +356,12 @@ jobs: with: pixi-version: v0.77.1 manifest-path: .github/workflows/pixi.toml + environments: ${{ matrix.environment }} cache: false - name: Run tests working-directory: .github/workflows - run: pixi run test + run: pixi run --environment ${{ matrix.environment }} test uv-sync: runs-on: ubuntu-latest diff --git a/mesonpy/__init__.py b/mesonpy/__init__.py index 928d8acb0..0eb8b1211 100644 --- a/mesonpy/__init__.py +++ b/mesonpy/__init__.py @@ -143,12 +143,15 @@ class _Entry(typing.NamedTuple): def _map_to_wheel(sources: Dict[str, Dict[str, Any]], - exclude: List[str], include: List[str]) -> DefaultDict[str, List[_Entry]]: + exclude: List[str], include: List[str], + build_dir: str) -> DefaultDict[str, List[_Entry]]: """Map files to the wheel, organized by wheel installation directory.""" wheel_files: DefaultDict[str, List[_Entry]] = collections.defaultdict(list) packages: Dict[str, str] = {} excluded = _compile_patterns(exclude) included = _compile_patterns(include) + build_dir = os.path.normpath(build_dir) + assert os.path.isabs(build_dir) for key, group in sources.items(): for src, target in group.items(): @@ -206,6 +209,25 @@ def _map_to_wheel(sources: Dict[str, Dict[str, Any]], if sys.platform == 'darwin': install_rpath = [_translate_rpath(path, dst) for path in install_rpath] + # ``build_rpath`` lists the RPATH entries to remove from the + # binary. Meson automatically adds RPATH entries for shared + # libraries built as part of the project, using relative paths + # anchored at ``$ORIGIN`` or ``@loader_path``, and for shared + # libraries from dependencies installed in non-standard + # locations, using absolute paths. Installed binaries need + # the absolute paths to find their external dependencies, so + # we drop them from the list. The relative paths are only + # meaningful inside the build tree, so we leave them in the + # list to be removed. Additional entries can be added with + # the ``build_rpath`` argument passed to Meson functions. The + # most common use case for these is to point at directories + # inside the build directory. These may be absolute paths, + # but they are irrelevant for installed binaries, so we leave + # them too in the list to be removed. + build_rpath = [path for path in build_rpath + if not path.startswith('/') + or os.path.commonpath((os.path.normpath(path), build_dir)) == build_dir] + wheel_files[path].append(_Entry(dst, src, install_rpath, build_rpath)) return wheel_files @@ -1015,7 +1037,7 @@ def _manifest(self) -> DefaultDict[str, List[_Entry]]: sources[key][target] = details # Map Meson installation locations to wheel paths. - return _map_to_wheel(sources, self._excluded_files, self._included_files) + return _map_to_wheel(sources, self._excluded_files, self._included_files, str(self._build_dir)) @property def _meson_name(self) -> str: diff --git a/tests/packages/link-against-external-lib/external.c b/tests/packages/link-against-external-lib/external.c new file mode 100644 index 000000000..2f9516e99 --- /dev/null +++ b/tests/packages/link-against-external-lib/external.c @@ -0,0 +1,23 @@ +// SPDX-FileCopyrightText: 2026 The meson-python developers +// +// SPDX-License-Identifier: MIT + +#include +#include + +static PyObject *version(PyObject *self, PyObject *args) { + return PyUnicode_FromString(GEOSversion()); +} + +static PyMethodDef methods[] = { + {"version", version, METH_NOARGS, NULL}, + {NULL, NULL, 0, NULL}, +}; + +static struct PyModuleDef module = { + PyModuleDef_HEAD_INIT, "external", NULL, -1, methods, +}; + +PyMODINIT_FUNC PyInit_external(void) { + return PyModule_Create(&module); +} diff --git a/tests/packages/link-against-external-lib/meson.build b/tests/packages/link-against-external-lib/meson.build new file mode 100644 index 000000000..baee3d8fc --- /dev/null +++ b/tests/packages/link-against-external-lib/meson.build @@ -0,0 +1,16 @@ +# SPDX-FileCopyrightText: 2026 The meson-python developers +# +# SPDX-License-Identifier: MIT + +project('link-against-external-lib', 'c', version: '1.0.0') + +py = import('python').find_installation(pure: false) + +external = dependency('geos', method: 'pkg-config') + +py.extension_module( + 'external', + 'external.c', + dependencies: external, + install: true +) diff --git a/tests/packages/link-against-external-lib/pyproject.toml b/tests/packages/link-against-external-lib/pyproject.toml new file mode 100644 index 000000000..435419311 --- /dev/null +++ b/tests/packages/link-against-external-lib/pyproject.toml @@ -0,0 +1,7 @@ +# SPDX-FileCopyrightText: 2026 The meson-python developers +# +# SPDX-License-Identifier: MIT + +[build-system] +build-backend = 'mesonpy' +requires = ['meson-python'] diff --git a/tests/packages/purelib-and-platlib/meson.build b/tests/packages/purelib-and-platlib/meson.build index 5451c9431..5ccfbf725 100644 --- a/tests/packages/purelib-and-platlib/meson.build +++ b/tests/packages/purelib-and-platlib/meson.build @@ -16,4 +16,5 @@ py.extension_module( 'plat.c', install: true, install_tag: 'platlib', + build_rpath: ':'.join(['/usr/local/lib', meson.current_build_dir() / 'private']), ) diff --git a/tests/test_wheel.py b/tests/test_wheel.py index 3fdb14942..67733521b 100644 --- a/tests/test_wheel.py +++ b/tests/test_wheel.py @@ -6,6 +6,7 @@ import re import shutil import stat +import subprocess import sys import textwrap @@ -260,6 +261,22 @@ def check(rpath, *expected): check(rpath, 'custom-rpath', f'{origin}/../.link_against_local_lib.mesonpy.libs') +@pytest.mark.skipif(sys.platform in {'win32', 'cygwin'}, reason='requires RPATH support') +@pytest.mark.skipif(shutil.which('pkg-config') is None, reason='requires pkg-config') +def test_link_against_external_lib_rpath(package_link_against_external_lib, tmp_path, venv): + if subprocess.run(['pkg-config', '--exists', 'geos']).returncode: + pytest.skip('requires GEOS') + version = subprocess.check_output(['pkg-config', '--modversion', 'geos'], text=True).strip() + + # Use an installed dependency without supplying an explicit RPATH. + # Check its version too, to detect fallback to a different system copy. + filename = mesonpy.build_wheel(tmp_path) + venv.pip('install', tmp_path / filename) + output = venv.python('-c', 'import external; print(external.version())') + # GEOSversion() appends the C API version after "-CAPI-". + assert output.strip().split('-CAPI-')[0] == version + + @pytest.mark.skipif(sys.platform in {'win32', 'cygwin'}, reason='requires RPATH support') def test_link_against_local_lib_rpath_ldflags(package_link_against_local_lib, tmp_path, monkeypatch): origin = '@loader_path' if sys.platform == 'darwin' else '$ORIGIN' @@ -282,8 +299,10 @@ def test_unneeded_rpath(wheel_purelib_and_platlib, tmp_path): origin = '@loader_path' if sys.platform == 'darwin' else '$ORIGIN' rpath = mesonpy._rpath.get_rpath(tmp_path / f'plat{EXT_SUFFIX}') - for path in rpath: - assert origin not in path + + assert not any(path.startswith(origin) for path in rpath) + assert '/usr/local/lib' in rpath or not not BUILD_RPATH_SUPPORT + assert not any(path.endswith('private') for path in rpath) or not BUILD_RPATH_SUPPORT @pytest.mark.skipif(sys.platform in {'win32', 'cygwin'}, reason='requires RPATH support')