diff --git a/ptodsl/ptoas_wheel_bootstrap.py b/ptodsl/ptoas_wheel_bootstrap.py index d9da235a6..e7616fbba 100644 --- a/ptodsl/ptoas_wheel_bootstrap.py +++ b/ptodsl/ptoas_wheel_bootstrap.py @@ -67,7 +67,12 @@ def _candidate_wheel_python_roots(wrapper: Path, module_file: str | None = None) candidates: list[Path] = [] if module_file: - candidates.append(Path(module_file).resolve().parent) + module_path = Path(module_file).resolve() + candidates.append(module_path.parent) + # Editable installs import this bootstrap from the repository while + # the generated runtime overlay lives under build/python. + repo_root = module_path.parent.parent + candidates.append(repo_root / "build" / "python") for scheme_name in ("purelib", "platlib"): scheme_path = sysconfig.get_path(scheme_name) diff --git a/tools/ptoas/CMakeLists.txt b/tools/ptoas/CMakeLists.txt index 1e2918bd5..1adff5114 100644 --- a/tools/ptoas/CMakeLists.txt +++ b/tools/ptoas/CMakeLists.txt @@ -116,6 +116,20 @@ add_custom_target(ptoas_runtime_staging ALL VERBATIM ) +# Editable Python installs resolve the wheel bootstrap from build/python. Keep +# a wheel-shaped runtime overlay there so the same launcher contract works for +# both regular and editable installations. +if(TARGET PTODSLPackage) + add_custom_command(TARGET ptoas_runtime_staging POST_BUILD + COMMAND ${CMAKE_COMMAND} -E remove_directory + "${CMAKE_BINARY_DIR}/python/ptoas/_runtime" + COMMAND ${CMAKE_COMMAND} -E copy_directory + "${PTOAS_BUILD_RUNTIME_STAGING_DIR}" + "${CMAKE_BINARY_DIR}/python/ptoas/_runtime" + VERBATIM + ) +endif() + if(TARGET PTODSLPackage) # The build-tree launcher imports ptoas._runtime_entry from build/python. # Keep that package staging coupled to every runtime staging entrypoint,