What it means for Python¶
You edit the project’s Python files and the changes are reflected “immediately” in the python interpreter.
All you need is to pip install -e or uv sync the project/workspace.
What it means for scikit-build-core¶
On top of the typical pure-python features, scikit-build-core editable installs also rebuild the CMake project.
Technically cmake --build and cmake --install.
Demystifying editable.mode¶
Currently, there are 2 editable modes redirect (default), inplace (use it at your own risk).
redirect mode¶
Creates a _editable_skbc_{}.(py|pth) file with instructions where to find Python files and CMake build (and installed) artifacts.
The CMake build artifacts are installed into site-packages path after each rebuild.
inplace mode¶
Effectively builds the CMake project with source-dir (-S) the same as build-dir (-B), which is a big no-no in CMake design.
Scikit-build-core 1.0 tricks and tips¶
You can now rebuild the CMake project on demand with
1 2 3>>> import importlib >>> importlib.util.find_spec("foo").loader.rebuild() >>> import foo
(You can also do foo.__loader__.rebuild(), but foo is already loaded, so if it’s not lazy, it’s too late, symbols are already loaded, it will work on restart only.)
Scikit-build-core pitfalls¶
Dependencies in build-system.requires¶
Build dependencies that provide CMake files (e.g. pybind11) need to be persistent in order to be able to rebuild.
With --no-build-isolation the build dependencies are taken from local site-packages
pip install --no-build-isolation -e .
uv sync --no-build-isolationUse importlib.resources¶
Inherently redirect editable mode behaves like a namespace package, i.e. sources are in multiple locations.
You cannot rely on patterns like __file__ to navigate to files in your package.
>>> from pathlib import Path
>>> lib = Path(__file__).parent / "my_lib.so"
>>> lib.open()
FileNotFoundError: [Errno 2] No such file or directory: 'my_lib.so'Instead use importlib.resources.files
1 2 3>>> from importlib.resources import files >>> lib = files("my_pkg") / "my_lib.so" >>> lib.open()
Don’t forget the build-dir¶
In order to be able to rebuild the CMake project you need a persistent build directory defined in build-dir.
By default redirect would not allow you to rebuild the CMake project and only cover the pure python files loading.
Providing a persistent build-dir allows to manually rebuild() and with the editable.rebuild it will do so automatically whenever you import
Example¶
[build-system]
requires = ["scikit-build-core>=1"]
build-backend = "scikit_build_core.build"
[project]
name = "example"
version = "0.1.0"
[tool.scikit-build]
build-dir = "build"from importlib.resources import files
def show_file():
cmake_file = files("example") / "file.txt"
print(cmake_file.read_text())cmake_minimum_required(VERSION 3.15...4.3)
project(${SKBUILD_PROJECT_NAME} LANGUAGES NONE)
add_custom_target(copy_file ALL
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/source.txt ${CMAKE_CURRENT_BINARY_DIR}/file.txt
)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/file.txt DESTINATION ${SKBUILD_PROJECT_NAME})>>> import example
>>> example.show_file()
Hello, world!Edit file.
>>> import importlib
>>> importlib.util.find_spec("example").loader.rebuild()
Running cmake --build & --install in /home/cle/tmp/simple-py/build
[1/1] cd build && /usr/bin/cmake -E copy source.txt build/file.txt
-- Install configuration: "Release"
-- Installing: .venv/lib64/python3.14/site-packages/example/file.txt
>>> import example
>>> example.show_file()
Off to the races!