fix(install): stage fbuild._native during source/editable install (#829)#887
Conversation
`uv pip install -e .` (or any source install) left `from fbuild import ...`
broken with `ModuleNotFoundError: No module named 'fbuild._native'`.
Root cause: setup.py's `BuildWithCargo` only built `fbuild-cli` — the
PyO3 extension produced by `crates/fbuild-python` (cdylib `_native`)
was a separate manual step nobody knew to run.
Extend `BuildWithCargo.run` to also build `fbuild-python` with the
`extension-module` feature and stage the resulting cdylib into
`python/fbuild/_native.{pyd,so}`. The CLI build path is unchanged; the
new cdylib step mirrors it exactly:
- `_build_fbuild_python()` — invoke
`soldr cargo build -p fbuild-python --features extension-module
--message-format=json-render-diagnostics` and collect the cdylib path
from cargo's JSON artifact stream.
- `_find_native_cdylib_from_json` / `_find_native_cdylib_by_search`
fallback — same selection rules as the CLI helpers, but match on
`target.name == "_native"` + `target.kind contains "cdylib"`, and
pick the `.dll` / `.so` / `.dylib` filename from cargo's `filenames`
array (cdylibs aren't exposed via the `executable` field).
- `STAGED_NATIVE_EXT_PATH` — `.pyd` on Windows, `.so` on Linux/macOS,
matching CPython's extension search order. Stripping the `lib`
prefix on Unix happens implicitly (we write `_native.so`, not
`lib_native.so`).
- `_staged_native_ext_is_up_to_date` — mtime fast-path companion to
the existing CLI check. Both staged artifacts must be fresh to skip
the cargo invocation entirely.
`pyproject.toml`'s existing `[tool.setuptools.package-data]
fbuild = ["_native.pyd", "_native.so"]` already pulls the staged file
into the wheel; no pyproject change needed.
Closes #829
|
Warning Review limit reached
Next review available in: 43 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Rolls up the fixes shipped since 2.3.14: - #855 (#883) — drop stale standalone-zccache CI/Docker/docs references after the soldr embedded-zccache transition (soldr#977/#980/#1081) - #865 (#884) — write daemon status via sync write_atomic; unblocks fbuild-daemon unit tests on macOS/Windows by eliminating the block_in_place panic in current-thread tokio runtimes - #875 (#885) — pin TMP/TEMP for compiler subprocess on Windows; ESP32 compile no longer fails with 'Cannot create temporary file in C:\Windows\' on the very first TU - #720 (#886) — record anti-removal policy for dump_usb_ids example - #829 (#887) — stage fbuild._native cdylib during source/editable install so 'from fbuild import ...' works after 'uv pip install -e .' Plus all prior #664 platform_packages audit work, the #826 testing followups, and the build cancellation fix from earlier in the cycle.
Problem
uv pip install -e .(or any source install) leftfrom fbuild import ...broken withModuleNotFoundError: No module named 'fbuild._native'. Root cause:setup.py'sBuildWithCargoonly builtfbuild-cli— the PyO3 extension produced bycrates/fbuild-python(cdylib_native) was a separate manual step nobody knew to run.Fix
Extend
BuildWithCargo.runto also buildfbuild-pythonwith theextension-modulefeature and stage the resulting cdylib intopython/fbuild/_native.{pyd,so}. The CLI build path is unchanged; the new cdylib step mirrors it exactly._build_fbuild_python()— invokesoldr cargo build -p fbuild-python --features extension-module --message-format=json-render-diagnosticsand collect the cdylib path from cargo's JSON artifact stream._find_native_cdylib_from_json/_find_native_cdylib_by_searchfallback — match ontarget.name == "_native"+target.kind contains "cdylib", pick the.dll/.so/.dylibfilename from cargo'sfilenamesarray (cdylibs aren't exposed via theexecutablefield).STAGED_NATIVE_EXT_PATH—.pydon Windows,.soon Linux/macOS, matching CPython's extension search order. Strip thelibprefix on Unix implicitly by writing_native.sonotlib_native.so._staged_native_ext_is_up_to_date— mtime fast-path companion to the existing CLI check. Both artifacts must be fresh to skip cargo entirely.pyproject.toml's existing[tool.setuptools.package-data] fbuild = ["_native.pyd", "_native.so"]already pulls the staged file into the wheel; no pyproject change needed.Verification
python -c "import ast; ast.parse(open('setup.py').read())"— syntax cleanCloses #829