Skip to content

Conversation

LeiWang1999
Copy link

Background

  • We recently migrated TileLang from setuptools to scikit-build-core. With setuptools we could run python setup.py build_ext --inplace, rebuild C++ extensions in seconds, and keep artifacts out of site-packages.
  • Using pip install -e . with scikit-build-core currently produces a wheel, which slows down rebuilds, and drops editable binaries into the environment’s site-packages directory, which pollutes the environment.
  • Switching to mode = "inplace" avoids site-packages, but it ignores build-dir and writes artifacts directly into the project root, making the tree noisy.

What this PR changes

  • Adds a new [tool.scikit-build.editable].build-dir option that is honored when editable.mode = "inplace", letting us keep a dedicated build tree (e.g. build/{wheel_tag}/editable) without resorting to site-packages or the project root.
  • Updates the wheel builder to:
    • Reuse a single formatting payload for build-dir expansion.
    • Write the selected editable build location into CMake cache entries (SKBUILD_EDITABLE_MODE, SKBUILD_EDITABLE_BUILD_DIR) so CMake projects can detect the setting.
    • Avoid logging the build directory twice when we fall back to the source tree.
  • Extends the dataclass model, JSON schema, and docs to describe the new knob.
  • Adjusts editable-mode tests to pass the new setting and exercises the inplace path with a dedicated build directory.
  • Extends the sample simplest_c CMake project to honor the new cache entries and keep its module output inside the source tree when an external build directory is used.

Remaining follow-ups

  • Mirror the SKBUILD_EDITABLE_* handling in the other editable fixture projects (tests/packages/navigate_editable, tests/packages/cython_pxd_editable/pkg{1,2}, and tests/packages/importlib_editable/**/CMakeLists.txt) so every sample keeps extension artifacts in the source layout when editable.build-dir is set.
  • Add a short CMake snippet to the user docs (e.g. docs/configuration/index.md) showing how projects can detect SKBUILD_EDITABLE_BUILD_DIR and route outputs correctly.
  • Run the editable-focused test suite (pytest -k editable) to confirm there are no regressions.

@LecrisUT
Copy link
Collaborator

Thanks, I had a branch working on this on the side, but if someone else can work on this, it will help get this in much faster. I will give a quick review to discuss the design aspect that we would want to have for this.

Build directory to use when ``editable.mode`` is ``"inplace"``. If empty, the project
source directory is used.
````
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In order to edit these files, use nox -t gen

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I made some changes

Comment on lines +347 to +352
build_dir: str = ""
"""
Build directory to use when :confval:`editable.mode` is ``inplace``.
If empty, the project source directory is used (the historical behaviour).
"""
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From what I can read from your description is you want something like editable.mode = redirect but to fully reuse the build directory right? In that case what we need to do is create a different editable mode, because:

  • inplace mode is explicitly to have the source-dir be exactly the same as build-dir
  • redirect mode reuses the build-dir, but also rebuilds and re-installs each time
  • new mode (name TBD) reuses the build-dir completely and just points the redirect files to the build-dir values

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Understood, but with setuptools, build_ext --inplace still drops the artifacts inside the build directory, and I honestly can’t think of a scenario where someone would expect inplace to dump products directly into the source tree.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Each build backend would have their own approach. Here in scikit-build-core the focus is on the CMake workflows and trying to make it close to a vanilla CMake workflow that you would have for debugging a non-python project.

The editable modes are a way to bridge those gaps, and unfortunately this depends more on the source code than the good designs. inplace is very much a last-resort option that we must have in order to help some projects that do not use modern designs using importlib.resources, otherwise the redirect (and a future replacement) is the preferred workflow.

@LeiWang1999 LeiWang1999 marked this pull request as ready for review October 15, 2025 11:18
@LeiWang1999
Copy link
Author

I can succesfully reach my goal via pip install -e . --no-build-isolation with this commit, this pr is ready for review.

@LeiWang1999 LeiWang1999 force-pushed the inplace_with_build_dir branch from 1af7eca to 7e5e7e6 Compare October 15, 2025 11:29
@LecrisUT
Copy link
Collaborator

LecrisUT commented Oct 15, 2025

I can succesfully reach my goal via pip install -e . --no-build-isolation with this commit, this pr is ready for review.

But this is not what we would want to have. inplace mode is explicitly for the purpose of having in-source builds where the build artifacts are alongside the source files, e.g. if you have resource files in the source folder that you access via __file__ location. What you are describing there is what redirect mode already mostly does but with a few steps that is making it a bit slow and which we would want to improve on.

@LeiWang1999
Copy link
Author

@LecrisUT I see your point. Would the plan be to extend redirect with a switch that skips the wheel staging altogether? That sounds like a much larger patch. And, I can not understand the usage of inplace actually.

@LeiWang1999
Copy link
Author

Anyway, I’m happy to rework the implementation along the lines you’ve suggested—my main goal is just to land an update quickly so we can get our development workflow unblocked.

@LecrisUT
Copy link
Collaborator

@LecrisUT I see your point. Would the plan be to extend redirect with a switch that skips the wheel staging altogether?

Yes, and indeed it is not a quick drive-by patch for this, but we can assist you all-throughout the process if anyone wants to pick up the mantle for that.

my main goal is just to land an update quickly so we can get our development workflow unblocked.

What is wrong with redirect mode? Specifically with rebuild = false. In that case the intended workflow is something like this:

  • pip install -e . --config-settings=build-dir=build (already defaults are redirect mode and rebuild = false)
  • manually do cmake --build and cmake --install whenever meaningful changes to the files are made

It will reuse the previous build directory and if all of the cmake dependencies are picked from the system, a CMake re-configure step should not be done (if it is, please try to hunt down what causes it, it's mostly a project configuration issue)

@LeiWang1999
Copy link
Author

@LecrisUT Thanks, that works for me as long as we enable --build-no-isolation. my folks use scikit-build-core usually just do pip install -e . lol.

@LecrisUT
Copy link
Collaborator

@LecrisUT Thanks, that works for me as long as we enable --build-no-isolation

This issue pops up regularly in the issues, most simple example of this is in usage of pybind11. In principle, if you have a dependency installed on the system that find_package is picking up or you installed it in your own venv and use --build-no-isolation the issue of re-configure should go away. We should make the interaction with editable mode smoother, but we don't know yet how we should do it. One way could be to have a hook to try and do find_package so that system packages (which do not vanish under build isolation) are picked up and preferred. We mostly need feedback and discussions on this to find what would be preferred.

@LeiWang1999
Copy link
Author

But one thing I have to complain about is that the editable build (pip install -e .) copies the build artifacts into site-packages, which is unreasonable and pollutes the environment. For example, I encountered this:

> pip install -e . --no-build-isolation
> ls somepath/python3.12/site-packages/tilelang
3rdparty  lib

As a result, sometimes when I run a program, it works fine:

> python
Python 3.12.9 | packaged by Anaconda, Inc. | (main, Feb  6 2025, 18:56:27) [GCC 11.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import tilelang
>>> tilelang.__path__
['local_dir/tilelang/tilelang']

But other times, it fails to locate the right path — even when I explicitly set PYTHONPATH:

# test_files.py
import tilelang
print(tilelang.__path__)
from tilelang import language as T
> python test_files.py
> _NamespacePath(['somepath/python3.12/site-packages/tilelang'])

Then it throws:

ImportError: cannot import name 'language' from 'tilelang' (unknown location)

because that directory only contains lib and 3rdparty.

@oraluben
Copy link

We do sometimes want pure pth solution, i.e. to have full src and build artifacts in source folder. Meantime, we also want to set 'build-dir' when using editable.mode = "inplace" to not mess up the current source dir (to build in a seperate in-tree build dir, which is also a common practice for cmake-based project). Given that, I think there's no harm to respect build-dir for inplace mode.

@LecrisUT
Copy link
Collaborator

Meantime, we also want to set 'build-dir' when using editable.mode = "inplace" to not mess up the current source dir (to build in a seperate in-tree build dir, which is also a common practice for cmake-based project).

We are well aware of the CMake good practices and we often discuss those in the issues. The inplace mode is not a recommended method for developers, and its primary usage is when the project hard-codes relative paths to resource files like

from pathlib import Path
DIR = Path(__file__).parent
SOME_DATA = DIR / "resources/data.csv"

The modern approach around this is to use importlib.resources. However we still need to support this older approach in order to ease the developer's burden for doing such transition.

Given that, I think there's no harm to respect build-dir for inplace mode.

There is, because the inplace mode is explicitly designed to be in-source build mode. E.g. the SOME_DATA in the example above could be a file generated by CMake using configure_file, add_custom_command, etc. which are later installed in the CMake to the package folder. In the inplace mode we are skipping the installation and rely on the fact that the build directory is mirrored with the source directory.

If you do not use such constructs, do not set the editable mode to inplace. Instead use the redirect which is the default.

But one thing I have to complain about is that the editable build (pip install -e .) copies the build artifacts into site-packages, which is unreasonable and pollutes the environment. For example, I encountered this:

Yes, this is the unfortunate limitation with the redirect mode. This mode is meant to use the cmake --install in order to know which files need to be linked in the _<module>_editable.py file that we place in the site-packages. This is also the method that we would want to change with introducing a new editable mode.

If you are interested in the details

Basically we have the file-api interface from CMake which allows us to interrogate all of the CMake install commands and we can make a list of the locations in build-dir and the intended locations in the install path. And then we can do the same thing that we do to handle the source files but pointing to the build-dir

But other times, it fails to locate the right path — even when I explicitly set PYTHONPATH:

The resolutions of __path__ is something rather complex. Ideally do not rely on it, instead use importlib.resources which can account for complex namespace installations, e.g. editable installs from different projects that share the same package, e.g. some projects install into the common sphinx.contrib as a form of simple plugin mechanism. When using editable installs you are likely to end up in a similar situation regardless of build backend or editable mode chosen.

We are aware that __path__ and other related methods do not always work as expected and those are tracked in #808, but we really need more help with that.

@LeiWang1999
Copy link
Author

The new mode is super important for us.

@LecrisUT
Copy link
Collaborator

The new mode is super important for us.

I will try to carve some time this weekend to publish the WIP that I have. Please check back on me, if I don't do any updates.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants