perf(install): pin CARGO_TARGET_DIR + disable PEP 517 isolation#5
Merged
Merged
Conversation
…tems 4+5) Two complementary changes that together let cargo's incremental fingerprint cache survive across `pip install .` / `uv build` invocations. Ported from FastLED/fbuild#743. 1. `os.environ.setdefault("CARGO_TARGET_DIR", ~/.template-python-rust-cmd/cargo-target/wheel-build)` at the top of `ci/build_wheel.py`. PEP 517 isolated builds copy the source tree to a temp dir and throw `<temp>/target/` away after each install — every install runs cargo cold (25-30s wall-clock without this). Pinning to a stable home-dir path preserves the fingerprint across invocations. Deliberately separate from `<repo>/target/` so iteration with bare `cargo check` doesn't churn the wheel-build cache and vice versa. 2. `[tool.uv] no-build-isolation-package = ["template-python-rust-cmd"]` in `pyproject.toml`. Without this, `uv build` (and `uv pip install .`) copy the source tree to a temp dir, and (a) cargo's incremental cache lands in that temp dir then gets discarded, (b) the future mtime-skip fast path can't see the staged binary because it's outside the temp tree. `maturin` already ships in the dev dependency group, so the build env has what it needs without isolation. 3. Refactor: pull `_cargo_target_root()` out so it respects `CARGO_TARGET_DIR`. Previously hardcoded `ROOT / "target" / "release"` — would have masked the pinned path. Refs #2 (items 4 + 5). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
3 tasks
zackees
added a commit
that referenced
this pull request
Jun 22, 2026
…#2 items 1+10) (#7) Previously the Python entry point `[project.scripts] template-python-rust-cmd = "template_python_rust_cmd.cli:main"` created a pip console-script `.exe` that subprocess-launched the staged `_bin/template-cli`. On Windows that pattern races the next shell prompt ahead of the child's stdout, because the Python shim returns to cmd.exe before the spawned native binary finishes flushing. Same class of bug fbuild fixed in FastLED/fbuild#747. Drop the shim. ci/build_wheel.py now post-processes the maturin-built wheel: opens the zip, injects the cargo-built `template-cli[.exe]` at `<name>-<ver>.data/scripts/template-cli[.exe]`, recomputes the RECORD row (sha256 + size), and stamps the Unix executable bit on the entry. Files in `.data/scripts/` are pip's canonical raw-script install location — pip drops them straight into the venv's `Scripts/` (Win) / `bin/` (POSIX) directory verbatim, with no Python wrapper for `.exe` files. Same mechanism cargo-dist and maturin's "bin" mode use. Removed: - `[project.scripts]` table from pyproject.toml. - `src/template_python_rust_cmd/cli.py` (the racy subprocess shim). - `src/template_python_rust_cmd/_bin/.gitkeep` + the gitignore lines that staged binary into the package data directory. - `action/cleanup/action.yml` step that rm'd the (now-nonexistent) `_bin/` staging directory. Verified end-to-end on Windows: - Fresh maturin wheel produced via `uv run --no-project --script ci/build_wheel.py`. - `unzip -l dist/*.whl` shows `template_python_rust_cmd-0.1.0.data/ scripts/template-cli.exe` (1.2 MB) — no `_bin/` entries. - `uv pip install` of that wheel into a fresh venv lands a `Scripts/ template-cli.exe` that `file` reports as `PE32+ executable` (NOT a Zip-archive console-script stub). - `cmd /c 'echo === BEFORE === & template-cli.exe --version & echo === AFTER ==='` prints `=== AFTER ===` AFTER the version output — acceptance criterion from issue #2 met. The `no-build-isolation-package` setting added in PR #5 was reverted in this PR: with maturin (vs. setuptools) the trade-off doesn't favor us — uv reuses a stale build env that lacks maturin, and the preview `extra-build-dependencies` mechanism is too fragile to ship in a template. The CARGO_TARGET_DIR pin from that PR stays — it already gives the cargo-incremental win without touching isolation. Closes #2 (items 1 + 10). Refs FastLED/fbuild#747. Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
This was referenced Jun 22, 2026
zackees
added a commit
that referenced
this pull request
Jun 22, 2026
…oses #9) (#10) Followup cleanup to #7 (drop Python CLI shim, ship raw wheel script). The package-side refactor worked at the wheel-build level but left stale source-tree references in two artifact-walking tools — same failure shape as fbuild#748 (a packaging refactor that worked at the wheel level but broke a tool walking the source tree a different way). Stale references found by `git grep '_bin\|template_python_rust_cmd\.cli'`: 1. `tests/test_cli.py` — imported `template_python_rust_cmd.cli. packaged_binary_path` (module deleted in #7). Whole file failed to collect with ImportError; the suite was silently 1 file short. 2. `ci/gates/action_surface.py::_binary_path()` — listed `src/template_python_rust_cmd/_bin/template-cli[.exe]` as its FIRST lookup candidate. That directory was removed in #7. Fallback to target/release worked locally but the gate doesn't honor CARGO_TARGET_DIR (pinned to ~/.template-python-rust-cmd/cargo-target/ wheel-build in #5), so it silently misses the binary on a wheel-build-driven runner. 3. `tests/README.md` — described `test_cli.py` as covering "the Python CLI shim's binary-discovery logic" (module gone). Fix: - `tests/test_cli.py` rewritten as a runtime contract check: probe PATH for `template-cli`, skip if absent (dev venv without install), otherwise assert it's invokable and produces non-empty --version output. Matches the new shipping mechanism (raw wheel script) which doesn't leave a source-tree probe target. - `ci/gates/action_surface.py::_binary_path()` now searches, in order: 1. $CARGO_TARGET_DIR/{release,debug}/ if set 2. ROOT/target/{release,debug}/ for the local ./test flow 3. PATH via shutil.which for pip/uv-installed binaries Updated the "no binary found" warning to match. - `tests/README.md` describes what test_cli.py actually does now. Verified: - `uv run pytest tests/test_cli.py tests/test_version.py tests/test_bindings.py -v` → 2 pass, 2 skip (test_cli skips because dev venv has no installed template-cli — expected behavior). - `./ci.sh test` → 34 pass, 2 skip, [test] ok. - `./ci.sh action_surface` → finds the binary, gate passes. Closes #9. Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Together these let cargo's incremental fingerprint cache survive across
pip install ./uv buildinvocations. Ported from fbuild#743.os.environ.setdefault("CARGO_TARGET_DIR", ~/.template-python-rust-cmd/cargo-target/wheel-build)at the top ofci/build_wheel.py. PEP 517 isolated builds copy the source tree to a temp dir;<temp>/target/is thrown away after each install. Pinning preserves cargo's fingerprint.[tool.uv] no-build-isolation-packageinpyproject.toml.maturinis already in the dev group so the build env has what it needs without isolation. Enables the future mtime-skip fast path to see the staged binary._cargo_target_root()helper sobuild_cli_binary()actually respects the pinned dir.Refs #2 — items (4) + (5).
Test plan
ci/build_wheel.pystill produces a wheel + sdist with both deliverables.🤖 Generated with Claude Code