Skip to content

Introduce pip package for python interface#118

Merged
lisitsyn merged 15 commits intomainfrom
pip-packaging
Feb 9, 2026
Merged

Introduce pip package for python interface#118
lisitsyn merged 15 commits intomainfrom
pip-packaging

Conversation

@lisitsyn
Copy link
Owner

@lisitsyn lisitsyn commented Feb 7, 2026

Summary

Adds pip install support for tapkee with CI that builds wheels for all major platforms and architectures.

Packaging lives in packages/python/ to prepare the repo for multiple packages.

  • packages/python/pyproject.toml: scikit-build-core backend, cibuildwheel config, package metadata (Python 3.11+), cmake.source-dir points to repo root
  • wheels.yml: cibuildwheel CI building on every push/PR, auto-publish to PyPI on v* tags
  • CMakeLists.txt: BUILD_CLI option to decouple CLI from Python extension build, replaced pytapkee rename hack with set_target_properties, proper install() with component filter
  • Makefile: pip-package target to build a wheel locally via pip wheel packages/python -w dist
  • Removed nanobind.yml: superseded by wheels.yml

Wheel matrix

Platform Arch Runner Dependencies
Linux x86_64 ubuntu-latest (manylinux_2_28) Eigen & fmt from source, ARPACK from EPEL
Linux aarch64 ubuntu-24.04-arm (native) Eigen & fmt from source, ARPACK from EPEL
macOS arm64 macos-latest Homebrew
Windows AMD64 windows-latest vcpkg (cached)

Build speed optimizations

  • Native ARM runner instead of QEMU emulation
  • Python 3.11+ only (3.9/3.10 are EOL)
  • Free-threaded Python builds skipped
  • vcpkg binary cache on Windows

Things to consider

  • Windows: vcpkg-based ARPACK/Eigen/fmt — may need tweaking if FindArpack.cmake doesn't pick up vcpkg paths
  • PyPI publish: uses trusted publishing (OIDC) — needs to be configured on pypi.org before the first v* tag push
  • Version: hardcoded 0.1.0 — worth switching to dynamic versioning (e.g., from git tags)?

Test plan

  • Linux x86_64 wheels build and pass smoke test
  • Linux aarch64 wheels build and pass smoke test
  • macOS arm64 wheels build and pass smoke test
  • Windows AMD64 wheels build and pass smoke test
  • pip install . works locally (verified on macOS arm64)
  • Existing CLI build (BUILD_CLI=ON, default) still works
  • Existing Linux/macOS/Windows CI unaffected

🤖 Generated with Claude Code

- Add pyproject.toml with scikit-build-core backend and cibuildwheel config
- Add wheels.yml workflow building wheels for Linux (x86_64, aarch64),
  macOS (x86_64, arm64), and Windows (AMD64) on every push/PR
- Includes PyPI publish job triggered on v* tags (trusted publishing)
- Refactor CMakeLists.txt: add BUILD_CLI option to decouple CLI from
  Python extension build, replace pytapkee rename hack with
  set_target_properties, add install target with component filter
- Remove superseded nanobind.yml workflow

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
message(FATAL_ERROR \"Error renaming file from \${SOURCE_FILE} to \${DEST_FILE}\")
endif()")
message(STATUS "Detecting and configuring nanobind - done")
install(TARGETS pytapkee LIBRARY DESTINATION . COMPONENT python)
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hey @iglesias, Claude suggested it might be replaced with the target_name thing.. I understand the renaming thing had been there for a reason but I am not sure

lisitsyn and others added 4 commits February 7, 2026 14:23
Linux: force manylinux_2_28 image (GCC 14 for C++23), install Eigen
3.4 from source since EPEL only has 3.3.x.

macOS: set MACOSX_DEPLOYMENT_TARGET per runner to match Homebrew
library targets (13.0 for macos-13, 15.0 for macos-latest).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
EPEL fmt 6.2.1 fmt::fmt-header-only target doesn't properly define
FMT_HEADER_ONLY, causing undefined symbol at runtime. Install fmt
10.2.1 from source instead.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
macos-13 runners are no longer available on GitHub Actions. ARM64
wheels work on Intel Macs via Rosetta 2.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Use native ARM runner (ubuntu-24.04-arm) instead of QEMU emulation
- Drop Python 3.9/3.10 (EOL), bump requires-python to 3.11+
- Skip free-threaded Python builds (cp*t-*)
- Cache vcpkg installed packages on Windows

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
license = "BSD-3-Clause"
authors = [
{ name = "Sergey Lisitsyn", email = "lisitsyn@hey.com" },
{ name = "Fernando José", email = "fernando.iglesiasg@gmail.com" },
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@iglesias also, is that the correct email to be used here and would you like to be in the list?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sure, it can be left as is, I don't mind it

@lisitsyn lisitsyn changed the title RFC: pip packaging with cross-platform wheel builds Introduce pip package for python interface Feb 7, 2026
lisitsyn and others added 2 commits February 7, 2026 15:26
MSVC linker can't resolve bare 'arpack' to 'libarpack.lib' (vcpkg
naming). Use ${ARPACK_LIB} (full path from FindArpack) everywhere.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
parpack is the MPI parallel wrapper and doesn't contain the core
ARPACK symbols (dsaupd_, dseupd_). Search for arpack first.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
SET(ARPACK_SEARCH_PATHS ${ARPACK_DIR})

FIND_LIBRARY(ARPACK_LIB NAMES parpack arpack PATHS ${ARPACK_SEARCH_PATHS})
FIND_LIBRARY(ARPACK_LIB NAMES arpack parpack PATHS ${ARPACK_SEARCH_PATHS})
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice one detected by Claude as the order makes parpack the main library to link which leads to linking errors in some cases

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice. Worth adding a test to avoid making the same mistake again?

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah I missed one part. It now links with ARPACK_LIB so it should be alright now. Before the fix it was finding 'parpack' but linking to 'arpack' in some cases.

lisitsyn and others added 8 commits February 7, 2026 18:33
The Windows wheel built successfully but failed at test time with
"DLL load failed" because ARPACK/OpenBLAS/gfortran DLLs from vcpkg
were not bundled into the wheel. Add delvewheel repair-wheel-command
pointing at the vcpkg bin directory.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Prepares the repo for multiple packages by relocating pyproject.toml
to packages/python/. Updates CI workflow and adds Makefile target.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adds PYTHON variable (defaults to `python`, overridable via
`make PYTHON=python3.12`) and replaces all bare `python` / `pip`
calls with $(PYTHON) / $(PYTHON) -m pip.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adds a Makefile target that builds the wheel, installs it in a
temporary venv, and runs a smoke test. The wheels CI now runs this
as a gate before publishing.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Include LICENSE in wheels via license-files
- Add Repository and Issues URLs for PyPI sidebar
- Add BSD License classifier
- Gitignore dist/ and .venv-test/

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The SPDX license expression (PEP 639) is incompatible with both
license-files globs outside the project dir and License:: classifiers.
The SPDX field alone is sufficient for PyPI.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adds a README.md tailored for the PyPI page with install instructions,
usage example, supported methods, and citation info.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@lisitsyn
Copy link
Owner Author

lisitsyn commented Feb 9, 2026

Seems it is ready to be merged.

@lisitsyn lisitsyn merged commit 7e35862 into main Feb 9, 2026
14 checks passed
@lisitsyn lisitsyn deleted the pip-packaging branch February 15, 2026 11:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants