Skip to content
Merged
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
126 changes: 113 additions & 13 deletions .github/workflows/build-ubuntu.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,16 @@ jobs:
with:
fetch-depth: 0 # Full history for accurate git describe

# CMakePresets.json defines one preset per supported Python (py3.10 … py3.13),
# each configuring an isolated build/cmake-cpython-3XX directory. Derive the
# preset name and its build directory once here; later steps (ctest, coverage,
# test packaging, install) need the directory the preset chose.
- name: Resolve CMake preset
run: |
py="${{ matrix.python_version }}"
echo "CMAKE_PRESET=py${py}" >> "$GITHUB_ENV"
echo "BUILD_DIR=build/cmake-cpython-${py//./}" >> "$GITHUB_ENV"

- name: Install uv
uses: ./.github/actions/setup-uv

Expand Down Expand Up @@ -102,10 +112,10 @@ jobs:
with:
path: |
~/vcpkg
build/vcpkg_installed
key: vcpkg-${{ runner.os }}-${{ runner.arch }}-${{ env.VCPKG_COMMIT }}-${{ hashFiles('cmake/DepthAIVcpkgManifest.cmake') }}
${{ env.BUILD_DIR }}/vcpkg_installed
key: vcpkg-${{ runner.os }}-${{ runner.arch }}-${{ env.CMAKE_PRESET }}-${{ env.VCPKG_COMMIT }}-${{ hashFiles('cmake/DepthAIVcpkgManifest.cmake') }}
restore-keys: |
vcpkg-${{ runner.os }}-${{ runner.arch }}-${{ env.VCPKG_COMMIT }}-
vcpkg-${{ runner.os }}-${{ runner.arch }}-${{ env.CMAKE_PRESET }}-${{ env.VCPKG_COMMIT }}-

- name: Setup vcpkg
run: |
Expand Down Expand Up @@ -142,9 +152,10 @@ jobs:
)
fi

cmake -B build \
# The preset supplies ISAAC_TELEOP_PYTHON_VERSION and the per-Python
# build directory; everything else is a command-line -D override.
cmake --preset "${CMAKE_PRESET}" \
-DCMAKE_BUILD_TYPE=${{ matrix.build_type }} \
-DISAAC_TELEOP_PYTHON_VERSION=${{ matrix.python_version }} \
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
-DBUILD_PLUGIN_OAK_CAMERA=ON \
Expand All @@ -155,13 +166,13 @@ jobs:
"${coverage_args[@]}"

- name: Build
run: cmake --build build --parallel 4
run: cmake --build --preset "${CMAKE_PRESET}" --parallel 4

- name: ccache stats
run: ccache --show-stats

- name: Run All Tests
run: ctest --test-dir build --output-on-failure --parallel
run: ctest --test-dir "${BUILD_DIR}" --output-on-failure --parallel

- name: Generate coverage report
if: ${{ matrix.build_type == 'Debug' && matrix.python_version == '3.11' && matrix.arch == 'x64' }}
Expand All @@ -171,10 +182,10 @@ jobs:

gcovr_args=(
--root "${GITHUB_WORKSPACE}"
--object-directory build/src
--object-directory "${BUILD_DIR}/src"
# CMake compiler-id probes are not test targets and produce noisy gcov warnings.
--gcov-exclude "build/CMakeFiles/.*/CompilerId.*/.*"
--exclude-directories "build/CMakeFiles"
--gcov-exclude "${BUILD_DIR}/CMakeFiles/.*/CompilerId.*/.*"
--exclude-directories "${BUILD_DIR}/CMakeFiles"
--filter "src/"
--exclude "src/.*/.*_tests/.*"
--exclude "src/.*/tests/.*"
Expand Down Expand Up @@ -226,10 +237,10 @@ jobs:
mkdir -p viz-tests-pkg
# Glob all viz_*_tests executables (covers viz_core_tests today, and
# viz_layers_tests / viz_session_tests / viz_xr_tests as they ship).
find build/src/viz -name 'viz_*_tests' -type f -executable \
find "${BUILD_DIR}/src/viz" -name 'viz_*_tests' -type f -executable \
-exec cp -v {} viz-tests-pkg/ \;
if ! ls viz-tests-pkg/viz_*_tests >/dev/null 2>&1; then
echo "No viz test binaries found under build/src/viz/"
echo "No viz test binaries found under ${BUILD_DIR}/src/viz/"
exit 1
fi
tar -cvzf viz-tests.tar.gz -C viz-tests-pkg .
Expand All @@ -245,7 +256,7 @@ jobs:

- name: Install (Release only)
if: matrix.build_type == 'Release'
run: cmake --install build
run: cmake --install "${BUILD_DIR}"

- name: Repair wheel tags with auditwheel (Release only)
if: matrix.build_type == 'Release'
Expand Down Expand Up @@ -292,6 +303,95 @@ jobs:
if-no-files-found: error
retention-days: 7

pip-editable-install:
# Validates the scikit-build-core (PEP 517/660) from-source install path added
# for issue #735: an sdist build and `pip install -e .` over the root
# pyproject.toml, which drives the same top-level CMake build as build-ubuntu.
# This guards the standards-based path so it does not rot. Single config
# (x64 / Python 3.11 / Release) is sufficient -- the backend just wraps CMake,
# already matrix-tested above. No CUDA/Vulkan here, so BUILD_VIZ stays auto-OFF.
runs-on: ubuntu-22.04
permissions:
contents: read
steps:
- name: Checkout code
uses: actions/checkout@v6
with:
fetch-depth: 1
Comment thread
jiwenc-nv marked this conversation as resolved.
persist-credentials: false

- name: Install uv
uses: ./.github/actions/setup-uv

- name: Install Apt dependencies
run: |
sudo apt-get update
# clang-format-14: the pip build enforces the clang-format gate (no
# cmake.define override), so the tool must be present or the build FATALs.
sudo apt-get install -y $CORE_APT_DEPS ccache patchelf clang-format-14
Comment thread
jiwenc-nv marked this conversation as resolved.

- name: Build sdist (validates backend config + metadata)
run: |
set -euo pipefail
uv build --sdist --python 3.11 --out-dir dist
ls -la dist

- name: Editable install
run: |
set -euo pipefail
uv venv --python 3.11 .venv-skbuild
# Editable install through scikit-build-core. It drives the same CMake
# build, scoped by pyproject.toml (no examples/tests/plugins/clang-format),
# and fetches C++ deps via FetchContent.
uv pip install --python .venv-skbuild -e .

- name: Import smoke test
run: |
set -euo pipefail
cat > "${RUNNER_TEMP}/skbuild_smoke.py" <<'PY'
import importlib.util

# (1) ABI check: actually import the compiled pybind11 extensions and the
# eager pure-Python packages. `import isaacteleop` also exercises the eager
# submodule chain (cloudxr, teleop_session_manager) that the base install
# must satisfy with only numpy+pyyaml.
import isaacteleop
for mod in (
"oxr",
"deviceio",
"deviceio_trackers",
"deviceio_session",
"schema",
"plugin_manager",
):
importlib.import_module(f"isaacteleop.{mod}")

# (2) Completeness check: every top-level subpackage that the classic wheel
# ships (minus GPU-only `viz`, which is auto-OFF here) must be PACKAGED.
# find_spec locates the package without importing its optional third-party
# deps, so a subpackage silently dropped from the build fails loudly here
# even though the smoke env installs no extras.
expected = [
"isaacteleop.mcap",
"isaacteleop.rig",
"isaacteleop.cloudxr",
"isaacteleop.teleop_session_manager",
"isaacteleop.retargeters",
"isaacteleop.retargeting_engine",
"isaacteleop.retargeting_engine_ui",
"isaacteleop.haptic_devices",
]
missing = [m for m in expected if importlib.util.find_spec(m) is None]
assert not missing, f"subpackages missing from the wheel: {missing}"

print("isaacteleop", isaacteleop.__version__, "imported OK;",
"all expected subpackages present")
PY
# Run the editable install directly with the venv's interpreter -- NOT via
# `uv run`, which (with [tool.uv] package = false) would use the project's
# own .venv without isaacteleop, rather than .venv-skbuild.
.venv-skbuild/bin/python "${RUNNER_TEMP}/skbuild_smoke.py"

test-viz-gpu:
# Runs [gpu]-tagged Catch2 tests for the Televiz module on a self-hosted
# GPU runner. The build-ubuntu job runs on a GPU-less GitHub-hosted runner
Expand Down
25 changes: 19 additions & 6 deletions .github/workflows/build-windows.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@ jobs:

env:
SCCACHE_GHA_ENABLED: "true"
# CMakePresets.json preset used to configure/build, and the build directory
# it selects. Windows has no Python matrix, so it pins the CMakeLists
# default (3.11); keep the two in sync if that changes.
CMAKE_PRESET: py3.11
BUILD_DIR: build/cmake-cpython-311

strategy:
matrix:
Expand All @@ -48,15 +53,20 @@ jobs:
uses: ilammy/msvc-dev-cmd@v1

# vcpkg - required when BUILD_PLUGIN_OAK_CAMERA=ON for DepthAI v3.x deps
#
# vcpkg installs manifest ports into ${CMAKE_BINARY_DIR}/vcpkg_installed, so
# this path tracks the preset's build directory. The preset is part of the key
# for the same reason: an entry saved from a different build directory would
# restore to a path this job never reads.
- name: Cache vcpkg
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: |
C:\vcpkg
build\vcpkg_installed
key: vcpkg-${{ runner.os }}-${{ hashFiles('cmake/DepthAIVcpkgManifest.cmake') }}
${{ env.BUILD_DIR }}/vcpkg_installed
key: vcpkg-${{ runner.os }}-${{ env.CMAKE_PRESET }}-${{ hashFiles('cmake/DepthAIVcpkgManifest.cmake') }}
restore-keys: |
vcpkg-${{ runner.os }}-
vcpkg-${{ runner.os }}-${{ env.CMAKE_PRESET }}-

- name: Setup vcpkg
run: |
Expand Down Expand Up @@ -94,11 +104,14 @@ jobs:

- name: Configure CMake
# Note:
# The py3.11 preset selects Python 3.11 (the CMakeLists default) and the
# build/cmake-cpython-311 build directory; the generator and the flags below
# are command-line additions on top of it.
# sccache does not work with VSBuild, so we use Ninja generator here.
# -G Ninja would pickup mingw64 by default on Windows, so we explicitly set the compiler to cl.exe
# Force embedded debug info (Z7) to avoid PDB contention whenever debug info is generated.
run: >
cmake -B build -G Ninja
cmake --preset ${{ env.CMAKE_PRESET }} -G Ninja
-DCMAKE_BUILD_TYPE=${{ matrix.build_type }}
-DENABLE_EXPERIMENTAL_WINDOWS_BUILD=ON
-DCMAKE_C_COMPILER_LAUNCHER=sccache
Expand All @@ -111,7 +124,7 @@ jobs:
-DCMAKE_TOOLCHAIN_FILE="${{ env.VCPKG_ROOT }}/scripts/buildsystems/vcpkg.cmake"

- name: Build
run: cmake --build build --parallel
run: cmake --build --preset ${{ env.CMAKE_PRESET }} --parallel

- name: Run All Tests
run: ctest --test-dir build --output-on-failure --parallel
run: ctest --test-dir ${{ env.BUILD_DIR }} --output-on-failure --parallel
38 changes: 38 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -201,3 +201,41 @@ endif()

# Formatting enforcement (runs on Linux by default)
include(cmake/ClangFormat.cmake)

# ==============================================================================
# scikit-build-core: install every built executable into the venv's bin/
# ==============================================================================
# Under pip (SKBUILD), put all executables built from this repo -- examples, C++
# test binaries, plugin tools, etc. -- on the venv PATH via the wheel's scripts
# scheme. We walk the directory tree from the project root but skip deps/ (and any
# FetchContent _deps/ subtree) so third-party executables (e.g. flatc) are never
# swept in. Shared libraries (Python extension modules, plugin .so) are not
# executables and are handled elsewhere / not installed here; a plugin that skips a
# missing SDK becomes a UTILITY target and is naturally excluded. Tagged with the
# isaacteleop_binaries component, selected via install.components in pyproject.toml.
if(SKBUILD)
function(isaac_teleop_install_executables _dir)
# Skip third-party dependency trees (deps/ and FetchContent's _deps/).
if(_dir STREQUAL "${CMAKE_SOURCE_DIR}/deps" OR _dir MATCHES "/_deps/")
return()
endif()
get_property(_subdirs DIRECTORY "${_dir}" PROPERTY SUBDIRECTORIES)
foreach(_subdir IN LISTS _subdirs)
isaac_teleop_install_executables("${_subdir}")
endforeach()
get_property(_targets DIRECTORY "${_dir}" PROPERTY BUILDSYSTEM_TARGETS)
foreach(_target IN LISTS _targets)
get_target_property(_type "${_target}" TYPE)
get_target_property(_imported "${_target}" IMPORTED)
if(_type STREQUAL "EXECUTABLE" AND NOT _imported)
install(TARGETS "${_target}"
RUNTIME DESTINATION "${SKBUILD_SCRIPTS_DIR}"
COMPONENT isaacteleop_binaries)
endif()
endforeach()
endfunction()

# Walk from the project root (deps/ skipped) so every executable built from
# this repo -- across src/ and examples/ -- is installed.
isaac_teleop_install_executables("${CMAKE_SOURCE_DIR}")
endif()
36 changes: 36 additions & 0 deletions CMakePresets.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
{
"version": 3,
"cmakeMinimumRequired": { "major": 3, "minor": 21, "patch": 0 },
"configurePresets": [
{
"name": "py3.10",
"displayName": "Python 3.10 (build/cmake-cpython-310)",
"binaryDir": "${sourceDir}/build/cmake-cpython-310",
"cacheVariables": { "ISAAC_TELEOP_PYTHON_VERSION": "3.10" }
},
{
"name": "py3.11",
"displayName": "Python 3.11 (build/cmake-cpython-311)",
"binaryDir": "${sourceDir}/build/cmake-cpython-311",
"cacheVariables": { "ISAAC_TELEOP_PYTHON_VERSION": "3.11" }
},
{
"name": "py3.12",
"displayName": "Python 3.12 (build/cmake-cpython-312)",
"binaryDir": "${sourceDir}/build/cmake-cpython-312",
"cacheVariables": { "ISAAC_TELEOP_PYTHON_VERSION": "3.12" }
},
{
"name": "py3.13",
"displayName": "Python 3.13 (build/cmake-cpython-313)",
"binaryDir": "${sourceDir}/build/cmake-cpython-313",
"cacheVariables": { "ISAAC_TELEOP_PYTHON_VERSION": "3.13" }
}
],
"buildPresets": [
{ "name": "py3.10", "configurePreset": "py3.10" },
{ "name": "py3.11", "configurePreset": "py3.11" },
{ "name": "py3.12", "configurePreset": "py3.12" },
{ "name": "py3.13", "configurePreset": "py3.13" }
]
}
2 changes: 2 additions & 0 deletions CMakePresets.json.license
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
SPDX-License-Identifier: Apache-2.0
Loading
Loading