Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions .devcontainer/devcontainer-lock.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
{
"features": {
"ghcr.io/devcontainers-extra/features/apt-packages:1": {
"version": "1.0.6",
"resolved": "ghcr.io/devcontainers-extra/features/apt-packages@sha256:55c54412112da81b9381e470cdbbe55278564950d1ff536ce925b1e8e096babd",
"integrity": "sha256:55c54412112da81b9381e470cdbbe55278564950d1ff536ce925b1e8e096babd"
},
"ghcr.io/devcontainers-extra/features/cmake:1": {
"version": "1.0.0",
"resolved": "ghcr.io/devcontainers-extra/features/cmake@sha256:86e25502f6b1213a68d88e4e55c969eba0b5016b9666d216ab65f5047808bc90",
"integrity": "sha256:86e25502f6b1213a68d88e4e55c969eba0b5016b9666d216ab65f5047808bc90"
},
"ghcr.io/devcontainers-extra/features/uv:1": {
"version": "1.0.2",
"resolved": "ghcr.io/devcontainers-extra/features/uv@sha256:1ac5b9f17a9e9e745933d0ac2ecf758e06ed3da4423cd22c94cce4d482fd2dd8",
"integrity": "sha256:1ac5b9f17a9e9e745933d0ac2ecf758e06ed3da4423cd22c94cce4d482fd2dd8"
},
"ghcr.io/devcontainers/features/docker-outside-of-docker:1": {
"version": "1.10.0",
"resolved": "ghcr.io/devcontainers/features/docker-outside-of-docker@sha256:c2c2cf829505ead8e4892c88c31b6594ae94a2bbb209e16e1fac456c1a3a624e",
"integrity": "sha256:c2c2cf829505ead8e4892c88c31b6594ae94a2bbb209e16e1fac456c1a3a624e"
},
"ghcr.io/devcontainers/features/git-lfs:1": {
"version": "1.2.5",
"resolved": "ghcr.io/devcontainers/features/git-lfs@sha256:71c2b371cf12ab7fcec47cf17369c6f59156100dad9abf9e4c593049d789de72",
"integrity": "sha256:71c2b371cf12ab7fcec47cf17369c6f59156100dad9abf9e4c593049d789de72"
},
"ghcr.io/devcontainers/features/git:1": {
"version": "1.3.8",
"resolved": "ghcr.io/devcontainers/features/git@sha256:fd75977de13a9979000e0e78baf949adb0ca71d2398995fa22e0a36d7e7e7fe2",
"integrity": "sha256:fd75977de13a9979000e0e78baf949adb0ca71d2398995fa22e0a36d7e7e7fe2"
}
}
}
5 changes: 4 additions & 1 deletion .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,17 @@
"ghcr.io/devcontainers/features/git-lfs:1": {},
"ghcr.io/devcontainers/features/docker-outside-of-docker:1": {},
"ghcr.io/devcontainers-extra/features/apt-packages:1": {
"packages": "clang-format-14,libx11-dev,libxrandr-dev,libxxf86vm-dev,libgl1-mesa-dev"
"packages": "clang-format-14,libx11-dev,libxrandr-dev,libxxf86vm-dev,libgl1-mesa-dev,patchelf"
},
"ghcr.io/devcontainers-extra/features/cmake:1": {},
"ghcr.io/devcontainers-extra/features/uv:1": {}
},
"postCreateCommand": "uv tool install pre-commit && pre-commit install",
"customizations": {
"vscode": {
"settings": {
"cmake.buildDirectory": "${workspaceFolder}/build-devcontainer"
},
"extensions": [
"ms-vscode.cpptools",
"ms-vscode.cmake-tools",
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ package-lock.json

# Build directories
build/
build-devcontainer/
_build/
**/build/
install/
Expand Down
47 changes: 38 additions & 9 deletions cmake/SetupPython.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -150,15 +150,46 @@ if(BUILD_PYTHON_BINDINGS)
else()
set(_venv_python "${_build_venv}/bin/python")
endif()
# Reuse an existing venv when possible. If the directory exists but the
# interpreter is missing, fail fast and require explicit cleanup.
if(EXISTS "${_build_venv}" AND NOT EXISTS "${_venv_python}")
message(FATAL_ERROR
"Found stale build venv directory at ${_build_venv}, but no interpreter at ${_venv_python}. "
"Please remove ${_build_venv} and reconfigure."
# Reuse the venv when its interpreter still runs. bin/python is an absolute
# symlink into a uv-managed Python, so it is only valid in the environment
# that created the venv.
set(_venv_usable FALSE)
if(EXISTS "${_venv_python}")
execute_process(
COMMAND "${_venv_python}" --version
RESULT_VARIABLE _venv_python_ok
OUTPUT_QUIET
ERROR_QUIET
)
if(_venv_python_ok EQUAL 0)
set(_venv_usable TRUE)
endif()
endif()
if(NOT EXISTS "${_venv_python}")

if(_venv_usable)
message(STATUS "Reusing existing build venv at ${_build_venv}")
elseif(EXISTS "${_build_venv}")
# Directory is present but its interpreter is not usable. Describe the
# actual failure: a dangling bin/python symlink (the common case when the
# venv was created in a different environment, e.g. a dev container vs the
# host, whose uv-managed Python lives elsewhere) versus an interpreter that
# is present but does not run. Only the former means the target is missing.
if(IS_SYMLINK "${_venv_python}" AND NOT EXISTS "${_venv_python}")
file(READ_SYMLINK "${_venv_python}" _venv_link_target)
string(CONCAT _venv_detail
"Its interpreter symlink is broken: ${_venv_python} -> "
"${_venv_link_target} (target does not exist). This build venv was "
"created in a different environment whose uv-managed Python lives "
"elsewhere.")
else()
set(_venv_detail "Its interpreter ${_venv_python} is missing or does not run.")
endif()
message(FATAL_ERROR
"Build venv at ${_build_venv} has no working Python interpreter. "
"${_venv_detail}\n"
"Remove the build directory ${CMAKE_BINARY_DIR} (or run 'cmake --fresh') "
"and reconfigure to recreate the venv for this environment.")
else()
execute_process(
COMMAND "${UV_EXECUTABLE}" venv --python "${Python3_EXECUTABLE}" "${_build_venv}"
RESULT_VARIABLE _venv_ok
Expand All @@ -167,8 +198,6 @@ if(BUILD_PYTHON_BINDINGS)
if(NOT _venv_ok EQUAL 0)
message(FATAL_ERROR "Failed to create build venv: ${_venv_err}")
endif()
else()
message(STATUS "Reusing existing build venv at ${_build_venv}")
endif()
execute_process(
COMMAND "${UV_EXECUTABLE}" pip install --python "${_venv_python}" "numpy>=2.0"
Expand Down
Loading