Build System#
Project structure#
The layout below reflects the actual CMakeLists.txt hierarchy (root CMakeLists.txt and src/core/CMakeLists.txt):
IsaacTeleop/
├── CMakeLists.txt # Top-level: deps, core, examples, plugins, etc.
├── cmake/
│ ├── SetupHunter.cmake # BUILD_PLUGINS, Hunter for OAK/DepthAI
│ ├── SetupPython.cmake # BUILD_PYTHON_BINDINGS, uv-managed Python
│ ├── ClangFormat.cmake # clang_format_check / clang_format_fix
│ └── ...
├── deps/
│ ├── CMakeLists.txt # Adds third_party
│ ├── third_party/CMakeLists.txt # FetchContent: OpenXR, yaml-cpp, pybind11, etc.
│ └── cloudxr/ # CloudXR (CI / optional)
├── src/core/
│ ├── CMakeLists.txt # Core options, subdirs in dependency order
│ ├── schema/ # FlatBuffer schemas and generated code
│ ├── oxr_utils/ # Header-only OpenXR utilities
│ ├── plugin_manager/ # Plugin manager (C++ and Python)
│ ├── oxr/ # OpenXR session management (C++ and Python)
│ ├── pusherio/ # PusherIO (depends on oxr)
│ ├── deviceio/ # Device I/O library (C++ and Python)
│ ├── mcap/ # MCAP recording (depends on deviceio)
│ ├── retargeting_engine/ # Retargeting (Python)
│ ├── retargeting_engine_ui/ # Retargeting UI (Python)
│ ├── teleop_session_manager/ # Teleop session manager (Python)
│ ├── cloudxr/ # CloudXR runtime helper (Python)
│ └── python/ # Python wheel packaging (when BUILD_PYTHON_BINDINGS=ON)
├── src/plugins/ # Built when BUILD_PLUGINS=ON
│ ├── plugin_utils/
│ ├── controller_synthetic_hands/
│ ├── generic_3axis_pedal/
│ ├── manus/
│ ├── oak/ # When BUILD_PLUGIN_OAK_CAMERA=ON
| └── haptikos/
└── examples/
├── oxr/ # OpenXR examples (C++ and Python)
├── retargeting/
├── teleop_session_manager/
├── teleop_ros2/
├── schemaio/
└── native_openxr/
CMake integration#
The project uses a modern CMake target-based approach. Libraries export targets (e.g. OXR, DEVICEIO, schema); include directories are propagated. Package config files are generated for use after install. See the respective CMakeLists.txt in src/core and under examples/ for target names and usage.
Using the Python wheel#
After building, install the wheel with uv or pip:
uv pip install isaacteleop --find-links=./install/wheels/ --reinstall
# or
pip install install/wheels/isaacteleop-*.whl
Installing from source with pip (scikit-build-core)#
In addition to the classic CMake flow above (which stages the package
and produces a wheel under install/wheels/), the repository ships a root
pyproject.toml that exposes isaacteleop through the
scikit-build-core build backend,
driving the same top-level CMakeLists.txt (so the two paths coexist):
pip install . # build + install the compiled wheel from source
pip install -e . # editable / developer install
For the walkthrough — how this scoped build differs from the classic flow (ABI, omitted type stubs, versioning) and the caveat on iterating on pure-Python subpackages under an editable install — see Build from Source.
Build directory layout and per-Python-version builds#
A CMake binary directory holds exactly one configured Python version — the
interpreter and ABI are baked into CMakeCache.txt and into the build venv. The
two build paths therefore never share a directory:
classic CMake → whatever you pass to
-B,build/by convention.ISAAC_TELEOP_PYTHON_VERSIONselects the interpreter (default3.11), and changing it on an existing tree is rejected with an error rather than silently reusing the old one — give each version its own directory.cmake -B build cmake --build build --parallel cmake --install build cmake -B build-py3.12 -DISAAC_TELEOP_PYTHON_VERSION=3.12 # a second version
pip / scikit-build-core →
build-wheel/<cache-tag>/(e.g.build-wheel/cpython-312/), set bybuild-dirin pyproject.toml and chosen automatically per interpreter, keyed offsys.implementation.cache_tag. It lives outsidebuild/sopip installand a classiccmake -B buildnever collide, andrm -rf buildleaves the incremental wheel tree intact.
build/ and build-wheel/ are gitignored.
Output locations#
After a successful build and install, relative to your build directory:
C++ libraries:
src/core/(and under each module)Python wheel:
wheels/isaacteleop-*.whlExamples (binaries): under
examples/(e.g.examples/oxr/cpp/)Installed files:
install/(or yourCMAKE_INSTALL_PREFIX) - Libraries:install/lib/- Headers:install/include/- Wheels:install/wheels/- Examples:install/examples/
Troubleshooting#
Dependencies fail to download#
FetchContent in deps/third_party/CMakeLists.txt requires network access. If downloads fail, check connectivity. Key repositories:
OpenXR SDK: KhronosGroup/OpenXR-SDK.git
pybind11: pybind/pybind11.git
yaml-cpp: jbeder/yaml-cpp.git
FlatBuffers, Catch2, MCAP: see
deps/third_party/CMakeLists.txtfor URLs and tags.
You can inspect the _deps directory in your build tree for fetch logs.
CMake can’t find OpenXR#
OpenXR is fetched automatically; it is not a system package. If configuration fails, try a clean configure
(--fresh wipes the CMake cache and reconfigures):
cmake -B build --fresh
Examples or tests can’t find the library#
When building from the top-level, examples and tests use the build tree. Ensure you run
cmake --build build from the project root and run executables from the build directory
(or use cmake --install build and run from install/).
uv or Python version#
cmake/SetupPython.cmake requires uv and uses ISAAC_TELEOP_PYTHON_VERSION. Install uv as
in One time setup and pass -DISAAC_TELEOP_PYTHON_VERSION=3.12 (or 3.11,
3.13) if you need a specific version.
Reference#
Root build and options:
CMakeLists.txtCore modules and options:
src/core/CMakeLists.txtDependencies:
deps/third_party/CMakeLists.txtPython and uv:
cmake/SetupPython.cmakePlugins and Hunter:
cmake/SetupHunter.cmakeCI (Ubuntu, matrix build_type/python_version/arch):
.github/workflows/build-ubuntu.yml