Explore a real multi-Python-version build matrix (osx-arm64) - #424
Explore a real multi-Python-version build matrix (osx-arm64)#424Tobias-Fischer wants to merge 4 commits into
Conversation
Depends on Tobias-Fischer/vinca#feature/conditional-python-dependency-v2 (pending a PR to RoboStack/vinca), which stops adding a Python host/run dependency to every recipe unconditionally -- only packages that actually need Python (ament_python, a rosidl interface package, or an explicit Python-flavored dependency) get one now. That's what makes a real multi-version python: pin viable at all: without it, every single recipe (including pure C++ libraries with zero Python content) would get rebuilt once per Python version. Changes here: - conda_build_config.yaml: python's [not emscripten] entry changed from a single pinned version to a real 3-entry matrix (3.11, 3.12, 3.13); the [emscripten] entry is untouched. Added python_min (per CFEP-25, used by the vinca change above to pin the build-time-only interpreter every recipe still needs without dragging it into this matrix). - pixi.toml: sccache dependency + --no-build-id on the build task (so sccache/ccache can actually get cache hits across the repeat builds this now causes for Python-dependent packages), a sccache-stats task, and the vinca dependency pointed at the fork branch above pending its own review. Validated end-to-end against a representative 133-package subset (std_msgs, example_interfaces, rclcpp, rclpy, demo_nodes_cpp, demo_nodes_py, launch, ros2cli, ros2topic + transitive closure), osx-arm64 only: 77 packages built exactly once regardless of the 3-version matrix, 56 built 3x (once per version), 245 total artifacts with zero classification exceptions. See README-multi-python.md for the full writeup, sccache timing data (including a compile-heavy fastrtps comparison showing ~2.6-2.8x speedup on repeat Python-version builds), and open questions for reviewers -- notably the CI-cost tradeoff of applying this pin to the full distro, which this PR deliberately leaves as a separate decision. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
d4d2f66 to
a439186
Compare
|
Force-pushed a corrected history: the original push accidentally included ~110 unrelated commits (my local branch was based off a stale, unmerged integration branch rather than |
Needed because this PR bumps vinca past its snapshot-metadata-caching change (RoboStack/vinca#134/RoboStack#145) -- the currently-committed snapshot predates that feature and lacks per-package dependency metadata vinca now requires, which broke recipe generation outright ("Snapshot metadata for 'X' has no dependencies; regenerate the rosdistro snapshot") for every single package, confirmed via this PR's own CI. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
|
CI caught a real, separate issue: main's currently-committed |
Fixes a UnicodeEncodeError crashing recipe generation outright on win-64 CI: Windows' console defaults to cp1252, which can't encode the Unicode ellipsis vinca's own generation-summary table (rich) uses for truncated cells. Unrelated to this PR's actual changes, but surfaced by its CI run. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
|
Two distinct failures in the last run, both confirmed pre-existing on
Given (1), I don't expect a clean full-distro CI run here regardless of anything in this PR -- the local 133-package validation (README-multi-python.md) used freshly-built local artifacts throughout, so it never exercised this particular staleness. Flagging clearly rather than chasing it further, since resolving it would mean rebuilding a chunk of the published distro unrelated to the Python-matrix proposal this PR is actually about. |
Follow-up to Tobias-Fischer/vinca@1bc88d1 (addressing @traversaro's review on vinca#153): vinca's build scripts now require an explicit VINCA_USE_SCCACHE=1 rather than auto-detecting sccache on PATH, so this repo's build task sets it explicitly instead of relying on sccache merely being installed. Verified end-to-end: a build without the env var produces zero sccache compile requests (confirmed via a freshly-reset sccache server) despite sccache being installed, and a build with it set produces a 100% cache hit rate on a repeat build. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
|
Addressed a review comment on the companion vinca PR (RoboStack/vinca#153): @traversaro correctly flagged that auto-detecting sccache on PATH silently changes build behavior depending on the environment. Fixed there (1bc88d1) -- sccache routing now requires an explicit Also tried a second package to strengthen the sccache demonstration: |
Summary
Follow-up on RoboStack/robostack.github.io#100. Depends on RoboStack/vinca#153, which stops vinca from adding a Python host/run dependency to every recipe unconditionally — only packages that actually need Python (
ament_python, a rosidl interface package, or an explicit Python-flavored dependency) get one now. That's what makes a real multi-versionpython:pin viable at all: without it, every single recipe (including pure C++ libraries with zero Python content — the majority, per @traversaro's investigation in the linked issue) would get rebuilt once per Python version.This PR is scoped as an experiment/proposal, not a request to flip the pin for the full distro — see "Open questions" below.
What changed
vinca_pinning.yaml/conda_build_config.yaml:python:changed from a single pinned version to a real 3-entry matrix (3.11, 3.12, 3.13). Note the build-string glob differs by version — conda-forge only started tagging the build string with the minor version (*_cp313, to disambiguate from the free-threaded*_cp313tvariant) starting with 3.13; 3.11/3.12 still publish under the older, untagged*cpythonsuffix.pixi.toml: addedsccacheas a dependency and--no-build-idto thebuildtask (required forsccache/ccacheto actually get cache hits, since both are sensitive to the timestamped build-directory paths rattler-build uses by default), added asccache-statstask, and pointed thevincapypi-dependency at RoboStack/vinca#153's branch pending its own review.README-multi-python.md: full writeup of the motivation, changes, validation results, and open questions.Validation
Rather than trying to build the full ~900-package distro, this was validated against a representative 133-package subset (
std_msgs,example_interfaces,rclcpp,rclpy,demo_nodes_cpp,demo_nodes_py,launch,ros2cli,ros2topic, plus their transitive closure — deliberately spanning all three of vinca's Python-need categories), osx-arm64 only, built locally end-to-end:77 packages built exactly once regardless of the 3-version matrix (
rclcpp,rmw_*,rcutils,cyclonedds,iceoryx*,fastcdr,demo_nodes_cpp,gtest/gmock-vendor,rosidl_default_generators, ...).56 packages built 3x, once per Python version (all
*_msgspackages,rclpy,launch*,ros2cli,ros2topic,demo_nodes_py, theament_*lint tools,rosidl_adapter/cli/parser/generator_*,pybind11_vendor, and — as an accepted false positive —fastrtps).245 total build artifacts (77×1 + 56×3 = 245), exactly matching the classification with zero exceptions.
sccachemeasurably reuses compiled objects across Python-version rebuilds of the same package. Real wall-clock timings, isolated single-recipe rebuilds (same build command each time, no--skip-existingso all 3 Python variants are genuinely rebuilt):std_msgs— a small message package, mostly CMake configure/rosidl codegen rather than compilation:fastrtps— a large, compile-heavy vendored C++ library (also Python-classified, an accepted false positive), same methodology:confirmed via
sccache --show-stats: 645 compile requests, 430 cache hits (66.67%). The first variant pays a small cache-write penalty (66s vs. 57s cold), but the second and third — which reuse most of the compiled objects across the Python-version-specific bindings layer — are ~2.6-2.8× faster than a fresh, uncached rebuild.std_msgsalone understated the benefit: most of its build time is CMake configure/codegen, not compilation, so the payoff scales with how much actual C/C++ compilation a package does — much more pronounced for something likefastrtpsthan for a small message package.Full details, including the exact per-category package lists, are in
README-multi-python.md.Open questions for reviewers
python:pin to this 3-version matrix would 3x the build time for whatever fraction of the ~900 packages the heuristic classifies as Python-dependent (roughly 40% on this subset, though the full-distro fraction hasn't been measured). This seems like a decision worth making deliberately rather than as a side effect of merging vinca#153 — that PR alone is harmless with a single-version pin (it just stops adding a spurious Python dependency to non-Python packages, freeing up e.g. Windows/Linux platforms from unnecessary rebuild churn even without touching this pin).ament_cmake_test-shaped edge cases: any package that callsament_python_install_package()internally without declaring a Python dependency inpackage.xmlbuilds its Python helper once, at whichever Python version happens to bepython_min— a downstream package importing that helper while running under a different active Python version could see a site-packages path mismatch. Not exercised in this validation run (--test skipthroughout); worth flagging for anyone relying on it in production. See vinca#153's discussion for the$SP_DIRfallback this surfaced.Test plan
🤖 Generated with Claude Code