source/libraries is the home for Isaac Sim code that must work without Kit. It contains C and C++ libraries, pure
Python modules, and optional Python bindings built with nanobind. Use this guide when you add, build, test, package, or
deliver one of these modules.
Public APIs must not expose Carbonite types or headers. Most modules use the shared
isaacsim.common.logging API instead of including Carbonite. Infrastructure modules may link Carbonite privately and
statically, but the resulting binary must not depend on Carbonite dynamically or export Carbonite symbols.
This document uses the following terms for different responsibilities:
| Term | Meaning |
|---|---|
| Host adapter | Code that connects a module to services or lifecycle events owned by the host application. For example, a host adapter can connect a logging backend or handle startup and shutdown. |
| Compatibility wrapper (shim) | An optional API layer that preserves or translates an older API during a migration. This is one specific kind of wrapper; the codebase also uses wrapper for ordinary object and binding wrappers. Simply packaging an unchanged module does not create a compatibility wrapper. |
A Kit extension can stage a library wheel and also contain a native host adapter. Add a compatibility wrapper only when the public API differs from the underlying module API.
source/libraries/
├── build.sh # Standalone Linux dependency, CMake, test, and wheel entry point.
├── build.bat # Standalone Windows entry point with the same arguments.
├── CMakeLists.txt # Standalone project and explicit distribution-package inventory.
├── CMakePresets.json # Supported local build configurations.
├── README.md # Module structure and build contract.
├── VERSION # One canonical version shared by every distribution package.
├── package_manifest.py # Shared generated-package manifest validation.
├── system_requirements.toml # Authoritative C, C++, Python, and CMake version contract.
├── cmake/
│ ├── README.md # Public helper reference and generated-name contract.
│ ├── IsaacSimModule.cmake # Public entry point for build helpers.
│ ├── IsaacSimModuleCore.cmake # C++ targets, dependencies, installation, and source boundary.
│ ├── IsaacSimPackage.cmake # Distribution registration, metadata, and install components.
│ ├── IsaacSimPackagingFilters.cmake # Shared exclusions for generated caches and Python bytecode.
│ ├── IsaacSimPython.cmake # Python package staging, installation, and registration.
│ ├── IsaacSimUsdSchema.cmake # Codeless USD schema generation and packaging.
│ ├── IsaacSimNanobind.cmake # Bindings, runtime closure, and loader paths.
│ ├── IsaacSimTesting.cmake # Unit, ABI, binary-boundary, and install-contract tests.
│ ├── IsaacSimDocumentationCatalog.cmake # Generates the public documentation inventory.
│ ├── IsaacSimSystemRequirements.cmake # Loads the shared language and tool version contract.
│ ├── FindCarbonite.cmake # Demand-driven pinned static Carbonite discovery.
│ ├── IsaacSimPackageConfig.cmake.in # Per-package installed CMake configuration.
│ ├── IsaacSimPackageConfigVersion.cmake.in # Per-package CMake version policy.
│ ├── IsaacSimPackageManifest.json.in # Installed package identity and membership manifest.
│ ├── CheckBinaryDependencies.cmake # Rejects dynamic Kit and Carbonite dependencies.
│ ├── CheckExportedSymbols.cmake # Checks an explicitly stable C ABI.
│ ├── CopyPythonPackage.cmake # Copies package trees without generated cache files.
│ ├── CopyRuntimeDirectory.cmake # Copies runtime data without transient Python files.
│ ├── initialize_nanobind_runtime.py # Initializes installed binding runtime search paths.
│ ├── run_nanobind_stubgen.py # Enables Windows binding runtime paths during stub generation.
│ ├── run_usd_gen_schema.py # Runs USD schema generation in the locked environment.
│ ├── StageEditableDirectory.cmake # Links editable Python trees with a portable copy fallback.
│ ├── RunInstallContractTest.cmake # Tests relocated C, C++, and Python installations.
│ └── tests/ # Generic CMake helper contract tests.
├── ovsim/interfaces/
│ ├── cpp/ # Canonical OV SIM C++ function-pointer type aliases.
│ └── python/ # Source-only OV SIM Python callable type aliases.
├── packaging/
│ ├── README.md # Native archive and Python wheel workflow.
│ ├── isaacsim_libraries_metadata.py # Exact shared-version Python dependency provider.
│ ├── package.py # Standard-library native archive builder.
│ ├── wheel.py # Packaging-only PEP 517 wheel orchestrator.
│ └── tests/ # Unit tests for packaging orchestration.
├── tools/
│ ├── build.py # Cross-platform standalone build orchestration.
│ ├── prepare_root_build.py # Discovers wheel-staging manifests for the root application build.
│ ├── stage_extension_wheel.py # Installs and validates a wheel and SDK for a Kit extension.
│ ├── update_version.py # Checks or updates the lockstep library version.
│ └── tests/ # Host, root-integration, artifact, and build-layout contract tests.
├── testing/ # Shared test infrastructure; not module test suites.
│ ├── README.md # Purpose and ownership of every shared test file.
│ ├── cpp/ # Shared compiled-test support.
│ ├── examples/ # Repository examples integration-test driver.
│ ├── install_contract/ # Generic downstream C, C++, and Python consumer templates.
│ └── python/ # Shared pytest configuration and test utilities.
├── licenses/ # Authored notices for redistributed native dependencies.
├── isaacsim_deprecated/ # Flat compatibility distribution with an explicit module prefix.
├── isaacsim_usd_schemas/<schema>/ # USD schema distributions with explicit module prefixes.
│ ├── CMakeLists.txt # Registers schema inputs, import roots, and public headers.
│ └── pyproject.toml # Authoritative schema wheel metadata.
└── isaacsim/<distribution>/ # Derives the isaacsim_<distribution> package name.
├── CMakeLists.txt # Registers the package, then its modules in dependency order.
├── pyproject.toml # Authoritative Python distribution and wheel build metadata.
├── docs/ # Optional package-level documentation rooted at index.rst.
└── <module-suffix>/ # Full path derives isaacsim.<distribution>.<module-suffix>.
├── CMakeLists.txt
├── CHANGELOG.md # Required history for this module's public APIs.
├── include/ # Installed public headers under their full namespace path.
│ └── .../details/ # Public inline/template implementation details when required.
├── src/ # C/C++ implementation and private headers.
│ └── details/ # Private detail-namespace headers and implementations.
├── bindings/python/ # Optional nanobind definition and binding-only headers.
├── python/ # Optional leaf package content.
│ ├── __init__.py # Fixed facade re-exporting impl.__all__.
│ ├── impl/ # Public API inventory and Python implementation.
│ └── py.typed # Inline typing marker.
├── tests/ # Optional tests, organized strictly by implementation language.
│ ├── c/ # C API doctest cases, compiled as C++.
│ ├── cpp/ # C++ API doctest cases.
│ └── python/ # pytest and Hypothesis tests.
├── resources/ # Optional explicitly registered test or runtime data.
├── abi/ # Optional stable C symbol baseline.
└── docs/ # Optional module API documentation rooted at index.rst.
A directory is not built or installed until its distribution registers it with a CMake helper. Choose the helper that matches the module:
- Compiled:
isaacsim_add_modulecreates a shared library from C11, C++17, or both. - Header-only:
isaacsim_add_header_moduleexports C or C++ headers and their dependencies without creating a binary. - Pure Python:
isaacsim_add_python_moduleinstalls a typed Python leaf package without a compiled target. - Compatibility Python:
isaacsim_add_compat_python_modulekeeps the module's source identity but installs it at an explicitly declared legacy import path. - USD schema:
isaacsim_add_usd_schema_modulegenerates codeless schema resources, typed Python imports, and optional public C++ headers. - Native with Python bindings: Register the native module with
isaacsim_add_moduleorisaacsim_add_header_module, then add its private Python binding withisaacsim_add_nanobind.
For compatibility migrations, pass PRESERVE_PACKAGE_LAYOUT to isaacsim_add_python_module only when you must keep
an existing leaf package unchanged. New modules use the standard impl/ layout.
Pass REQUIRES_BINDINGS to isaacsim_add_python_module or isaacsim_add_compat_python_module only when the module
cannot be imported without a nanobind extension. Install tests without bindings skip those imports but still validate
the distribution and all of its dependencies. This module option is separate from the Python test option with the
same name.
A distribution package is one unit that can be installed and shipped independently. Its CMake name usually comes
from its two-part source path: for example, isaacsim/common becomes isaacsim_common. A flat distribution directory
is also supported when it declares MODULE_PREFIX; isaacsim_deprecated, for example, declares
MODULE_PREFIX isaacsim.deprecated.
The CMake API uses the older term group for a distribution package, so helper names and placeholders still use
group. One package can contain several C, C++, header-only, pure Python, or Python-bound modules. For example,
isaacsim/common/logging defines the logical module isaacsim.common.logging. A module does not have to expose a
Python API.
Each module has its own changelog, but all packages and modules use the version in source/libraries/VERSION. The
native runtime, development files, Python files, and documentation are installable parts of the same package, not
separately versioned packages.
Use underscores in CMake group, component, manifest, and native archive names. Use canonical hyphenated names, such as
isaacsim-common, in Python project metadata and requirements. Use dotted names for logical modules and imports.
Register a group before its modules:
isaacsim_add_group(
NAME isaacsim_common
MODULES
isaacsim.common.array
isaacsim.common.logging
isaacsim.common.profiling
)
add_subdirectory(array)
add_subdirectory(logging)
add_subdirectory(profiling)For a normal two-part root, isaacsim/<distribution> determines the underscore-separated distribution name. The full
module path determines the dotted logical module name. For a flat root, the directory supplies the distribution name,
MODULE_PREFIX supplies the dotted prefix, and the path below the root supplies the rest. You still declare CMake
names explicitly; configuration fails if a name does not match its path. A compatibility Python module keeps this
path-based logical name and declares its legacy import separately:
Source path relative to source/libraries |
CMake group | Logical module | Python import |
|---|---|---|---|
isaacsim/common/logging |
isaacsim_common |
isaacsim.common.logging |
isaacsim.common.logging |
isaacsim/common/profiling |
isaacsim_common |
isaacsim.common.profiling |
isaacsim.common.profiling |
isaacsim/navigation/route_planner |
isaacsim_navigation |
isaacsim.navigation.route_planner |
isaacsim.navigation.route_planner |
isaacsim/robot/kinematics/inverse |
isaacsim_robot |
isaacsim.robot.kinematics.inverse |
isaacsim.robot.kinematics.inverse |
isaacsim_deprecated/core/experimental/objects |
isaacsim_deprecated |
isaacsim.deprecated.core.experimental.objects |
isaacsim.core.experimental.objects |
USD schema distributions under isaacsim_usd_schemas follow the package boundaries of newton-usd-schemas and
physx-usd-schemas. They declare MODULE_PREFIX because their source layout, distribution names, and public import
names intentionally differ. Ordinary modules must still follow the source-path naming rules.
Schema generation supports two separate compatibility variants. Standalone builds generate usd2505 resources. A
Kit extension can request usd2511, which uses the matching OpenUSD dependency in _build/target-deps/usd. Their pure
Python wheels use the build tags 1usd2505 and 1usd2511. Wheel staging requires an exact tag instead of relying on
pip to choose a variant.
A module must live below its distribution root; the root itself cannot be a module. Intermediate namespace
directories do not need a CMakeLists.txt. For example, the distribution can call
add_subdirectory(kinematics/inverse) directly. Module roots cannot overlap: if isaacsim.robot.kinematics is a
module, isaacsim.robot.kinematics.inverse cannot also be one. The group-level docs directory is reserved for
package documentation.
Python packages use implicit namespaces above the module root, as defined by PEP 420. For example, the
isaacsim.common.logging wheel includes isaacsim/common/logging/__init__.py, but not isaacsim/__init__.py or
isaacsim/common/__init__.py. This allows independently installed distributions to share the isaacsim namespace.
The distribution root is packaging structure, not an importable API. Compatibility distributions may declare legacy
imports outside their logical namespace, but each import must still have exactly one owner.
After registering a group, declare each dependency on another package with isaacsim_add_group_dependency. Register
dependency groups first. All dependencies use the shared version in source/libraries/VERSION; you cannot provide a
different version.
The MODULES list must exactly match the modules registered for the package. CMake generates package metadata and
install tests only when the list matches and all dependencies can be packaged. To make an incomplete package a
configuration error, set ISAACSIM_PACKAGE_GROUP=<name> or ISAACSIM_ENFORCE_COMPLETE_PACKAGES=ON.
The package's pyproject.toml defines its Python metadata and runtime dependencies. List supported version ranges for
external dependencies in [project.dependencies]. For dependencies on other source/libraries packages, use the
dynamic metadata provider so every package uses the shared version:
[project]
dynamic = ["version", "dependencies"]
[[tool.dynamic-metadata]]
provider = { path = "../../packaging", module = "isaacsim_libraries_metadata" }
field = "dependencies"
names = ["isaacsim-common"]The provider reads source/libraries/VERSION and adds exact requirements such as
isaacsim-common==7.0.0a2 to the wheel metadata. Native package dependencies do not automatically become wheel
requirements. If a wheel declares an internal dependency, validation confirms that the dependency exists in the
native package graph and uses the shared version.
CMake does not create or edit Python project metadata. The standalone build compiles the full module graph. Wheel
assembly installs only the selected package's <group>-python component, then packages those files without running
CMake again.
Create only the directories a group or module uses. The build does not discover source directories automatically.
The root project adds each distribution with add_subdirectory, and each distribution adds its module paths.
A group may register a module conditionally when all required external targets are available. If only some required targets are available, stop with a configuration error instead of building a reduced module. If an optional target set is completely unavailable, report that in the configuration output.
Generated files are not source files. Standard build trees live under
<repo>/_cmake_build/isaacsim-libraries-<configuration>. Release trees for the other profiles live under
<repo>/_cmake_build/isaacsim-libraries-<profile>; Debug appends -debug. Populated dependencies live under
<repo>/_cmake_build/isaacsim-libraries-target-deps, and default wheel and native artifacts live under
<repo>/_cmake_build/isaacsim-libraries-artifacts/<configuration> when the documented packaging commands are used.
Wheels prepared for Kit and their validated extension stages live under
<repo>/_cmake_build/extension-wheel-artifacts/<configuration> and
<repo>/_cmake_build/extension-wheel-stages/<configuration>/<extension>. Keep the editable Python stage, generated
export headers, nanobind binaries, stubs, package manifests, and installation test files inside a build tree. Never
treat tool-created caches, bytecode, or packaging staging directories as source structure or include them in an
installed package.
After successful default extension-wheel assembly and staging, the historical
module-carrier-artifacts/<configuration> and module-carriers/<configuration>/<extension> paths under
_cmake_build link to those same respective outputs. An explicit --output-dir remains caller-owned and does not
update the historical artifact path. Generate-only prepares link-target directories and preserves any existing
ordinary legacy stage directory and its files until that extension is staged successfully.
Library dependencies are separate from Kit application dependencies. Private and patched native dependencies belong
in deps/isaacsim-libraries.packman.xml and are installed under
_cmake_build/isaacsim-libraries-target-deps. Public native archives, including the OVPhysX SDK, use Pixi recipes
pinned by checksum.
The root pixi.toml and pixi.lock define all public build and Python packages. Exact versions of Python, CMake,
Ninja, DLPack, doctest, fmt, nanobind, SDL, stb, and tsl-robin-map are recorded in pixi.lock. Pixi uses conda-forge
binaries when they are compatible with the standalone modules and builds selected packages from checksum-pinned
official archives where needed. CMake uses the installed files and never downloads dependencies itself.
DLPack headers are installed with their development component so the SDK is self-contained. Locked and minimum
dependency environments live under .pixi/envs. Packages come from public PyPI or the NVIDIA public index when
available; use NVIDIA's internal PyPI only for a pinned version that is unavailable from those sources.
Repository builds prepare extensions with wheel-staging.toml through tools/repoman/repoman.py before Repo
generation and staging. Internal Linux builds wait for the linbuild relaunch so staged binaries use the application
toolchain. Windows and --no-docker builds prepare them directly.
The standalone launcher collects licenses for redistributed packages from the locked native-runtime environment.
It stores the combined license set under _cmake_build/PACKAGE-LICENSES/<key>, and CMake copies it into each build
profile. Runtimes, SDKs, Python wheels, and extension wheel stages install the appropriate copy under
share/licenses/<distribution>.
A successful full standard build with locked dependencies also creates a developer-environment in its build tree.
It contains the runtime, development, and Python components of every complete package. Source examples use this
environment directly, so they do not install or replace dependencies. Concurrent examples hold a shared read lock;
cleanup or replacement waits for them to finish.
Do not add library-only dependencies to deps/isaac-sim.packman.xml or Kit Python prebundles.
Declare dependencies as close as possible to the code that uses them:
- Prefer an exact public conda package on each supported platform. Use a checksum-pinned Pixi source recipe only when a platform package is unavailable or conflicts with a runtime provided by the host. Do not add a CMake download fallback.
- Add or update private, patched, and binding packages in
deps/isaacsim-libraries.packman.xml. - Add or update external Python runtime, native-support, build, and test dependencies in root
pixi.toml, then regenerate and reviewpixi.lock. Keep non-public package indexes scoped to the individual dependency. - Declare target-level build dependencies in the consuming module's
CMakeLists.txt. UsePACKAGE_DEPENDENCIESwhen consumers must find a package before loading an installed exported target. - Declare dependencies on another distribution with
isaacsim_add_group_dependency. The owning package must declare a dependency before one of its targets can link to that package. If the wheel also needs the package, add its name to theisaacsim_libraries_metadataprovider inpyproject.toml. - Declare third-party Python runtime requirements and their supported ranges in
[project.dependencies]. Concrete build/test tool selections remain private build-environment inputs and do not become wheel runtime requirements.
Carbonite is a private implementation dependency with extra restrictions. Public APIs and package dependencies must not expose its types or headers. A host-integration header may accept an opaque native handle, allowing a host adapter to use a host-owned backend without making feature consumers include or link Carbonite.
isaacsim.common.logging and isaacsim.common.profiling contain the shared Carbonite implementation. Feature modules
link to these public APIs instead of compiling their own copy. An infrastructure module may link Carbonite privately
only when CMake identifies it as a static library, and the result must still pass binary-dependency and exported-symbol
tests. Call find_package(Carbonite REQUIRED MODULE) only in modules that use it.
The project requires CMake 3.26 or newer and Ninja. The standalone entry point installs and always uses the locked
Pixi CMake 4.3.2 and Ninja 1.13.2 packages. Linux host prerequisites are standard shell/archive utilities,
CA certificates, and either curl or wget for Packman bootstrap downloads. On
Windows 11, install Visual Studio 2022 and the Windows SDK. Windows 10 is not supported. The build reuses an initialized
developer environment or locates Visual Studio with vswhere. NVIDIA CI may provision its non-redistributable Windows
compiler separately through Packman; it is not part of the public dependency manifest.
See cmake/README.md for the complete public helper reference and generated-name rules.
The gRPC protocol module includes the following third-party source file:
| Component | Source file | Copyright | License |
|---|---|---|---|
| Google APIs RPC status protocol | google/rpc/status.proto |
Copyright 2026 Google LLC | Apache-2.0 |
The file retains its original Google copyright and license header. It matches
the upstream Google APIs file at revision ebd1d23ac613b177828dad42ad8dfb13ba498279
except for three removed blank lines. The accompanying license text is copied unchanged from that revision.
This entry covers the vendored protocol source, not the gRPC and Protobuf libraries downloaded for a build. Built library distributions carry the dependency license aggregate described above.
isaacsim_add_module(
NAME isaacsim.common.logging
EXPORT_HEADER isaacsim/common/logging/Export.h
EXPORT_MACRO ISAACSIM_COMMON_LOGGING_API
PUBLIC_C_HEADERS
isaacsim/common/logging/Logging.h
PUBLIC_CPP_HEADERS
isaacsim/common/logging/Logging.hpp
PUBLIC_C_SYMBOLS_FILE abi/c-api.symbols
SOURCES
src/Logging.cpp
)NAME must match the module path relative to source/libraries, with slashes replaced by dots. CMake uses this name to
derive the native and exported targets, Python path, test name, and output directory. For example,
isaacsim.common.logging exports isaacsim::common-logging, while isaacsim.navigation.route_planner exports
isaacsim::navigation-route_planner.
Each compiled module is a C11 or C++17 shared library, or both. It has hidden symbol visibility, a generated export
header, package release metadata, and portable runtime library paths. On platforms with shared-library versioning, the
runtime includes the fully versioned file and an unversioned link, such as libisaacsim-common-logging.so.7.0.0 and
libisaacsim-common-logging.so. This version identifies the library within its distribution; the module is not
released independently. The CMake package installs both public and generated export headers.
find_package(isaacsim_common CONFIG REQUIRED)
target_link_libraries(application PRIVATE isaacsim::common-logging)Use .h for C interfaces and .hpp for C++ interfaces. Use .c for C implementation sources and .cpp for C++
implementation sources. Name C and C++ headers and sources with PascalCase file stems. Public header extensions and
the repository-wide PEP 440 VERSION file are checked at configure time. A module may expose a stable C API, a C++
API, or both; C++ sources and consumers require C++17.
Keep only public, installed headers under include/. Put private headers under src/ and nanobind-only adapters under
bindings/python/. You may use a build-only interface target to share binding code between modules, but do not export
it as part of the public C++ package. PUBLIC_C_HEADERS and PUBLIC_CPP_HEADERS must list every file under
include/. Only those files and the generated export header are installed.
Use target dependencies rather than ambient include or library directories:
PUBLIC_DEPENDENCIES isaacsim::other-module ThirdParty::Core
PRIVATE_DEPENDENCIES ThirdParty::Implementation
PACKAGE_DEPENDENCIES ThirdPartyPACKAGE_DEPENDENCIES lists external packages that consumers must find before loading exported targets. CMake also
uses internal module dependencies to find all shared libraries needed by Python bindings. Declare dependencies on
other Isaac Sim distributions at group level instead of repeating them in PACKAGE_DEPENDENCIES.
For example, a module in another distribution that logs through isaacsim.common.logging declares both the package
dependency and target link:
isaacsim_add_group(
NAME isaacsim_feature
MODULES isaacsim.feature.runtime
)
isaacsim_add_group_dependency(
GROUP isaacsim_feature
DEPENDS_ON isaacsim_common
)
isaacsim_add_module(
NAME isaacsim.feature.runtime
# Other required arguments omitted.
PRIVATE_DEPENDENCIES isaacsim::common-logging
)Use PRIVATE_DEPENDENCIES when logging is an implementation detail. Use PUBLIC_DEPENDENCIES only when a public
header uses logging API types. If the dependent distribution produces a wheel, add isaacsim-common to the
isaacsim_libraries_metadata provider in its pyproject.toml. The dependency supplies the logging library; do not
copy it into the dependent package.
Use isaacsim_add_header_module for a header-only C or C++ API. Use
isaacsim_install_runtime_dependencies to copy an imported shared library into the standalone C++ runtime. Use
isaacsim_add_runtime_directory for other runtime data, such as schema registries. Put these declarations in the
module that uses the files. A resources/ directory has no automatic build behavior; register test and runtime data
explicitly.
Source checks reject Kit, OmniGraph, and pybind11 includes, imports, and dependencies. They also reject Carbonite in public headers and dependencies, while allowing approved private static use. Tests confirm that built libraries do not link dynamically to Carbonite or Kit. Modules with a stable C ABI may export only their declared symbols. Keep host adapters and Kit lifecycle code outside this tree.
A pure Python module registers its leaf package without declaring a compiled library or binding:
isaacsim_add_python_module(
NAME isaacsim.example.utilities
)A compatibility distribution can preserve an old import without placing its logical module under that deprecated namespace:
isaacsim_add_compat_python_module(
NAME isaacsim.deprecated.core.experimental.objects
IMPORT_NAME isaacsim.core.experimental.objects
)NAME still matches the source path and identifies the module during the build. IMPORT_NAME sets the legacy Python
import used for staging, installation, manifests, and wheels. Two modules cannot own the same import.
The python/ directory contains the module's leaf package; it is not another package root. Do not repeat the namespace
as python/isaacsim/.... Define the public API in python/impl/__init__.py with impl.__all__, and use this fixed
public python/__init__.py after the required license header:
from .impl import *
from .impl import __all__ as __all__Pure-Python implementation files and binding adapters live under python/impl/; include py.typed at the python/
root. A pure Python module does not need include/, src/, bindings/, abi/, tests/c/, or tests/cpp/.
All Python modules stage into one build tree. Parent directories are implicit namespace packages; only registered leaf modules contain the authored facade and typing marker:
<build>/python/isaacsim/
├── lib/ # Shared-library closure needed by bindings.
└── <registered-import-path>/ # Public API, implementation, typing, and optional binding.
For development, the build copies __init__.py and py.typed, then links impl/ and the tests to their source
directories when the platform supports directory symlinks. This makes Python code and test changes visible without
restaging. Otherwise, the build uses copies that update when their sources change.
This editable behavior applies only to the build tree. Installs and wheels contain regular copied files, and tests are
never installed. Tools that use the editable package must not write generated data beside __file__; use a temporary
directory instead.
Each group with Python imports provides a <group>-python install component. It contains that group's Python modules,
bindings, generated stubs, and required native libraries from the same group. Code from other groups remains a package
dependency and is not copied into the component.
Installing this CMake component creates an importable Python directory, not a complete Python distribution. The wheel
tool packages the component and adds standard distribution metadata. Modules do not define their own __version__.
Use importlib.metadata.version("<group-name>") to read the installed distribution version.
isaacsim_add_nanobind(
MODULE isaacsim.common.logging
SOURCES bindings/python/Bindings.cpp
DEPENDENCIES SomeBindingSupportTarget
STUB_PRELOADS dependency.module
)The helper registers the Python leaf package, then builds a private bindings._bindings extension with nanobind and
the stable CPython ABI. It generates bindings/_bindings.pyi and installs the type stub beside the binary. Register
the native module first with isaacsim_add_module or isaacsim_add_header_module.
Use NO_STABLE_ABI with a non-empty STABLE_ABI_EXCEPTION only when the binding cannot use the stable ABI. SOURCE
is shorthand for one file; use SOURCES for one or more. DEPENDENCIES lists extra targets used only by the binding.
STUB_PRELOADS lists nanobind modules that must load before stub generation so cross-module C++ types receive their
Python names. On Windows, use WINDOWS_RUNTIME_SIBLING_DIRECTORY only for an SDK whose runtime directory sits beside
the binding runtime directory.
Export headers, native binding binaries, and _bindings.pyi files are generated in the build tree. Do not check them
into a module's source directory. py.typed is authored source: it tells type checkers that the installed Python
package supplies typing information.
Do not maintain a second package-level .pyi for re-exported binding functions. Put richer annotations in Python
wrappers, or use nb::sig when stub generation cannot infer the public type. The check-python-stubs target builds
all registered stubs without modifying source files.
Relative loader paths are calculated from the full module depth. On Linux and macOS, shared libraries install under
python/isaacsim/lib; on Windows, required DLLs install next to the binding.
isaacsim_add_c_tests(
MODULE isaacsim.common.logging
SOURCES
tests/c/Logging.cpp
)
isaacsim_add_cpp_tests(
MODULE isaacsim.common.logging
SOURCES
tests/cpp/Logging.cpp
RESOURCE_DIR resources/tests
)
isaacsim_add_python_tests(
MODULE isaacsim.example.utilities
)Add REQUIRES_BINDINGS when a Python test imports a nanobind extension. Use TEST_SUPPORT <module>... when a Python
suite imports test-only helpers from another registered module. These helpers remain in the source tree and are never
installed.
Add REQUIRES_NO_BINDINGS to a C++ test only when a dependency has separate, incompatible native and Python-enabled
variants. Put C and C++ API doctest cases under tests/c and tests/cpp, and put Python tests under tests/python.
Never put tests inside the importable python/ package. C API tests use .cpp because doctest is a C++ framework, but
they may include only public C headers and call only C symbols.
For native tests, RESOURCE_DIR sets the working directory. For Python tests, it limits resource lookup. In both
cases, the directory must contain TEST_RESOURCES.md.
Set TIMEOUT <seconds> on isaacsim_add_python_tests when one Python suite needs a positive per-test CTest timeout;
the standalone --test-timeout option sets the command-wide default for tests without their own timeout.
When BUILD_TESTING=ON, the build includes:
- C API doctest unit tests authored under
tests/cand compiled as C++ so individual cases can be listed and filtered. - C++ API doctest unit tests authored under
tests/cpp. The test helpers add the shared doctest entry point automatically; moduleSOURCESlists contain only module-owned.cpptest sources and rejectMain.cpp. - Python pytest and Hypothesis tests from an isolated test tree against the staged package when Python support is enabled. Binding-dependent tests run only when bindings are enabled.
- A binary dependency check for every C++ module.
- An exact stable C symbol check only when
PUBLIC_C_SYMBOLS_FILEis supplied. - One isolated installation test for each complete distribution. It installs the package and its dependencies, compiles every public header independently against its exported target, runs the consumers, and imports installed Python modules in a fresh process. It also verifies exact internal dependencies and confirms that an incorrect dependency version is rejected.
These installation tests are generated only for test builds. Adding a package, public header, Python module, or binding automatically extends the appropriate test.
The standalone library tree uses C11, C++17, and Python 3.12. C and C++ share the repository .clang-format
configuration: Allman braces, four-space indentation, a 120-column limit, and left-aligned pointers. The shared
formatter controls mechanical layout; the language rules control naming, ownership, error handling, and API design.
File extensions identify the native-language contract:
.hand.care C and usePascalCasefile stems. Public C headers must compile independently as C11 and when included from C++17..hppand.cppare C++ and usePascalCasefile stems. A.cppfile that implements or tests a C ABI still follows C++ source style.- C API doctest cases live under
tests/cbut are.cppbecause doctest is a C++ framework. They include and call only the public C API; the install contract compiles the installed headers and consumer with the C compiler.
Public C APIs use the same identifier casing as C++: module-prefixed camelCase functions, PascalCase types, and
camelCase fields, parameters, and local variables. Dotted module names are flattened without separators, so
isaacsim.common.logging becomes the isaacsimCommonLogging function prefix and the IsaacSimCommonLogging type
prefix. Macros and unscoped C enum constants remain uppercase and module-prefixed. C API Doxygen comments document
pointer ownership, nullability, buffer sizes, units, result values, thread safety, callback behavior, and ABI
initialization. Public C++ APIs use Doxygen and document the same caller-visible contract, including exceptions only
when the API can throw.
Python implementation code lives under python/impl, owns __all__, uses type annotations and Google-style
docstrings, and targets Python 3.12. The outer python/__init__.py remains the fixed packaging facade. Python API tests
use pytest and Hypothesis under tests/python; build and packaging tool tests may use unittest. Python-facing
docstrings authored in nanobind C++ sources follow the Python documentation convention and remain consistent with the
generated stubs.
Repository guidance under .cursor/rules is global by language: C and C++ have separate code-style and Doxygen rules,
and Python has shared code-style and Python API docstring rules. Python-facing strings in nanobind sources follow the
same Python docstring contract while their surrounding code follows C++ style. Module-specific requirements are
limited to the structure, build, testing, packaging, and ABI contracts documented here. CMake files use the global
CMake style: target-based dependencies, explicit inventories, lowercase commands, and four-space indentation. Do not
hand-format generated export headers, generated .pyi files, package manifests, or ABI symbol output.
CMake and the test suite enforce rules that affect package identity, binary compatibility, installation, and repeatable builds. Rules that require human judgment are checked during review.
| Contract | Enforcement |
|---|---|
| Module and group names, unique registration, version syntax, and exact group membership | Configure time |
| Required sources, public-header inventory and extensions, Python package shape, and documentation entry points | Configure time |
C, C++, and Python test placement under the matching tests/<language> directory |
Configure time |
| Cross-package native target links and exact shared-version dependencies | Configure time |
| C11/C++17, hidden visibility, group-derived binary versions, and relative loader paths | Configure and build time |
| Forbidden framework source/public dependencies and dynamic Carbonite or Kit libraries | Configure time and CTest |
| Nanobind stable ABI policy and rejection of the alternate binding framework | Configure time |
| Generated export headers remaining outside the source tree | Configure-time rejection and build layout |
| Stable C symbol baseline | Opt-in CTest check; updates require an explicit target |
| Installed C/C++ headers, relocated consumers, Python imports, metadata, and dependency closure | Install-contract CTest |
| Separation of Python tests, caches, bytecode, and symlinks from installed packages | Source layout, install rules, and install-contract CTest |
| Wheel identity, exact internal dependencies, import inventory, typing, namespace layout, and content exclusions | Wheel assembly validation |
| Wheel-staging discovery, artifact identity, direct SDK installation, and wheel/SDK agreement | Root preflight, staging, and tool tests |
| Mirroring module package dependencies in Kit extension metadata | Source review |
CMake generates package metadata, install components, and installation tests only when registered modules exactly
match MODULES and every dependency is complete. Set ISAACSIM_PACKAGE_GROUP or
ISAACSIM_ENFORCE_COMPLETE_PACKAGES to make an incomplete package a configuration error instead of reporting and
skipping it.
Each pyproject.toml owns its Python dependency declarations. Wheel validation confirms that every internal Python
requirement exists in the native dependency graph and uses the shared version. Native-only dependencies do not need to
appear in wheel metadata, and external Python dependencies may use supported version ranges. CMake does not read
Python project metadata.
Reviewers check rules that depend on intent, including dependency order, source file extensions, documentation, changelog releases, generated-file cleanliness, and whether an API should promise a stable C ABI. Add an automated check only when it provides enough value to justify the maintenance cost.
source/libraries/VERSION is the only version source for all packages and modules. isaacsim_add_group verifies the
module list, and isaacsim_finalize_modules generates release metadata only for complete groups. Every module needs a
CHANGELOG.md. Package-level documentation is optional, but a package docs/ directory must contain index.rst.
VERSION contains only the package version and a trailing newline:
7.0.0a2
Update the shared version with:
python3.12 source/libraries/tools/update_version.py <version>Run python3.12 source/libraries/tools/update_version.py --check to verify the version and internal dynamic dependency
metadata without changing the source tree.
Versions use a limited form of PEP 440: three release numbers, followed by optional
alpha (aN), beta (bN), release-candidate (rcN), post-release (.postN), development (.devN), or local
(+local.parts) suffixes. Use lowercase identifiers and no leading zeros in numeric fields. The first alpha of 7.0.0,
for example, is 7.0.0a1. Other valid examples include 7.0.0.dev0 and 7.0.0rc1.
The build writes this version to package manifests, CMake configuration, and Python distribution metadata. Native
libraries use only the three numeric release fields because platform library versions cannot represent PEP 440
suffixes. They do not use a separate SOVERSION. A version change rebuilds and relinks all libraries and consumers
because they are released together.
Review ABI compatibility manually against the latest published artifact. Check changed public headers, exported symbols, data layouts, calling conventions, and public dependency types. The build can verify declared C symbol lists, but it cannot determine C++ binary compatibility.
Library versions follow the Isaac Sim release train; individual libraries do not use independent semantic versions. A minor Isaac Sim release may break the API or ABI of a module, while patch releases should remain compatible.
Modules in one package always ship together. Dependencies between packages require the exact full version from
source/libraries/VERSION, including any PEP 440 suffix. The build records and checks that version in native and
Python package metadata. CMake's numeric package lookup treats versions as compatible only within the same major and
minor release; consumers must explicitly opt into a later minor release.
Module-level docs/ directories remain next to the API they describe and are also optional. When present, module
registration requires docs/index.rst and installs the documentation automatically; module CMakeLists.txt files do
not need a separate documentation call. The <group>-documentation component uses:
share/isaacsim/packages/<group>/
├── VERSION
├── package.json # Package identity, membership, components, and exact dependencies.
├── index.rst # Present only when the group has docs/.
├── ... # Other optional group documentation files and assets.
└── modules/<module-name>/
├── CHANGELOG.md # Always present.
└── ... # Optional module documentation.
Use reStructuredText in package and module docs/ directories. Keep changelogs in Markdown. The recommended module
layout is:
docs/
├── index.rst # Required overview, local table of contents, and entry point.
├── api_c.rst # Optional C reference for modules exposing C.
├── api_cpp.rst # Optional C++ reference for modules exposing C++.
└── api_python.rst # Optional Python reference for modules exposing Python.
Put the module overview and local table of contents in index.rst. Link longer concept, example, or migration guides
from that table of contents, and create only the language reference files the module needs. Document public APIs in
their source headers, Python facades, binding docstrings, and type information as well. CMake installs the
reStructuredText files but does not build a Sphinx site. Do not copy Python signatures into prose; the facade or
binding docstring is the source of truth.
Follow Keep a Changelog in each module's CHANGELOG.md. Keep ## [Unreleased] at the top, even when it is empty. Add
only populated Added, Changed, Deprecated, Removed, Fixed, or Security sections. At release, move entries
into a dated version section that matches source/libraries/VERSION. Do not add empty entries for unchanged modules.
Record changes users can observe, not implementation details or issue numbers.
During alpha, changelogs describe the net user-visible delta since the last release; an entry is not required for
every code change or merge request. Routine build fixes, internal cleanup, and test-only changes do not need entries.
Revise existing Unreleased entries as features evolve instead of adding Fixed entries for behavior that has not
shipped. CI checks shared-version and dependency metadata consistency when library metadata or its validation
tools change. The optional local pre_merge_validate.py --libraries command checks shared-version consistency
and scoped Python lint. Neither checks changelog content, formatting, or whether each changed library has an entry.
# Changelog
## [Unreleased]
### Added
- `isaacsim.common.logging`: add the new public capability.
## [6.1.0] - 2026-07-13
### Added
- `isaacsim.common.logging`: add the initial logging APIs.A symbol baseline is opt-in. Supply PUBLIC_C_SYMBOLS_FILE only after committing to maintain a stable C ABI. The check
compares the baseline with the exact exported set under the module's derived C prefix, such as isaacsimCommonLogging.
This catches removed, renamed, missing, and accidentally added exports; it does not validate function signatures.
Run cmake --build <build> --target check-abi for a read-only check. After approving an intentional C ABI addition or
removal, run the module-specific update-abi-baseline-<module-target> target. The aggregate update-abi-baselines
target updates every registered baseline and should be used cautiously. Normal builds and tests never rewrite a
baseline.
Use source/libraries/build.sh on Linux and source/libraries/build.bat on Windows. These scripts start the verified
Pixi launcher with Packman's bootstrap Python, then run the build in the locked Python 3.12.13 environment. Pixi
provides CMake, Ninja, DLPack, and the required Python packages. Profiles without Python receive only the small native
schema runtime. These standalone scripts do not run repo.sh, Premake, linbuild, Kit, or the extension build.
Run these commands from source/libraries:
# Linux
./build.sh -r
./build.sh -r --test
./build.sh -r --test --coverage
./build.sh -r --test-only
./build.sh -r --wheel
./build.sh -r --test --stage-wheel isaacsim.common
./build.sh -r --test --wheel --dependency-profile minimum
# Windows
build.bat -r
build.bat -r --test
build.bat -r --test-only
build.bat -r --wheel
build.bat -r --test --stage-wheel isaacsim.common
The scripts download the repository-pinned Pixi release from its official GitHub URL, verify its committed SHA-256 digest, and install only locked environments. Packman continues to provide private, patched, and binary native dependencies, as well as the Python interpreter used to start Pixi.
Release is the default when neither -r nor -d is present. Passing both builds both configurations. The remaining
entry-point options are:
| Option | Purpose |
|---|---|
-c, --clean |
Remove the selected profile and configuration build trees, then exit. |
-x, --rebuild |
Remove the selected build trees before configuring and building. |
-g, --generate |
Configure without building. |
-t, --target <name> |
Build one CMake target. |
-j, --jobs <count> |
Limit parallel build jobs. |
--profile <name> |
Select standard, cpp-tests, python-modules, cpp-library, or werror. |
--test |
Run CTest after the build; Python-enabled configurations always record locked test dependencies so CI may test the artifact later. |
--coverage |
Instrument native targets for coverage; requires GCC or Clang. |
--test-only |
Restore test dependencies and run CTest from the matching existing build tree without rebuilding. |
--junit-output <path> |
Write CTest results as JUnit XML; requires --test or --test-only. |
--test-timeout <seconds> |
Set the default per-test CTest timeout; requires --test or --test-only. |
--test-jobs <count> |
Limit parallel CTest jobs; requires --test or --test-only. |
--wheel |
Assemble wheels from a completed standard build without invoking CMake from the PEP 517 backend. |
--stage-wheel <extension> |
Build the distribution declared by an extension's wheel-staging.toml, then stage its wheel and SDK; repeat as needed. |
--carrier <extension> |
M1-compatible alias for --stage-wheel. |
--group <name> |
Limit --wheel to a distribution; repeat to select more than one. |
--output-dir <path> |
Override the wheel output directory for --wheel or --stage-wheel. |
--dependency-profile <name> |
Select locked (default) or minimum external Python dependencies. |
--no-pull |
Require current local Packman and locked Pixi environments without network access. |
--pull-only |
Populate Packman and every supported Pixi environment, including locked source-recipe packages, then exit. |
The locked dependency profile uses the exact versions selected for normal and release builds. The minimum profile
uses the lowest supported version of each direct Python dependency. Ordinary builds never resolve floating versions;
only the reviewed dependency-update workflow evaluates ranges and updates pixi.toml and pixi.lock.
Each non-default build profile has separate dependency and CMake directories, so profiles cannot reuse stale files.
Tests and wheel builds use only the selected profile on PYTHONPATH. Profiles choose the versions used to build and
test; they do not change the dependency requirements written into wheel metadata. Pixi recreates an environment when
its locked contents change.
--test-only supports CI jobs that restore a configured build from another job, possibly at a different checkout
path. It updates generated CMake paths, restores the locked build and test environments, recreates the generated
developer-environment, and runs CTest without rebuilding. Windows CI also restores the matching MSVC and Windows
SDK. Use --junit-output for GitLab reports, --test-timeout to stop hung tests, and the test regex options to select
or exclude CTest tests.
The profile names have the same feature selections as the CMake presets:
./build.sh -r --profile standard --test
./build.sh -r --profile cpp-tests --test
./build.sh -r --profile python-modules --test
./build.sh -r --profile cpp-library
./build.sh -r --profile werror --test
CI performs one clean build followed by a complete CTest run from the saved build output. Run the same pair before
pushing changes to source/libraries or source/examples:
# Linux
./build.sh -r --rebuild --profile standard
./build.sh -r --profile standard --test-only --no-pull --test-timeout 600 \
--junit-output ../../_cmake_build/isaacsim-libraries-release/source-libraries-tests.xml
# Windows
build.bat -r --rebuild --profile standard
build.bat -r --profile standard --test-only --no-pull --test-timeout 600 ^
--junit-output ..\..\_cmake_build\isaacsim-libraries-release\source-libraries-tests.xml
The full CTest run includes the installed examples integration test. For a quicker examples-only check, add
--test-regex '^tests-examples$' to the second command. Remove it before pushing so you run the full CI suite.
The supported options are:
| Option | Default | Purpose |
|---|---|---|
BUILD_TESTING |
ON |
Build unit tests and the install contract. |
ISAACSIM_ENABLE_PYTHON |
ON |
Stage, install, and test Python modules. |
ISAACSIM_ENABLE_PYTHON_BINDINGS |
ON |
Build, stage, install, and test nanobind APIs; requires Python. |
ISAACSIM_WARNINGS_AS_ERRORS |
OFF |
Promote compiler warnings to errors. |
ISAACSIM_ENABLE_COVERAGE |
OFF |
Add native coverage instrumentation; requires GCC or Clang. |
ISAACSIM_PACKAGE_GROUP |
empty | Require one named group to be complete and packageable. |
ISAACSIM_ENFORCE_COMPLETE_PACKAGES |
OFF |
Fail configuration if any registered group is incomplete. |
ISAACSIM_TARGET_DEPS_DIR |
<repo>/_cmake_build/isaacsim-libraries-target-deps |
Override library dependencies. |
ISAACSIM_NATIVE_RUNTIME_DEPS_DIR |
empty | Native-support schema packages selected by the Pixi launcher. |
ISAACSIM_PUBLIC_DEPS_ROOT |
empty | Pixi prefix containing pinned public build tools, headers, and sources. |
ISAACSIM_PYTHON_RUNTIME_DEPS_DIR |
empty | Python runtime packages selected by the Pixi launcher. |
ISAACSIM_EXTENSION_USD_ROOT |
empty | Add the extension-compatible schema variant using a Kit OpenUSD root. |
ISAACSIM_PYTHON_TEST_DEPS_DIR |
empty | Test packages selected by the Pixi launcher. |
ISAACSIM_PYTHON_INSTALL_DIR |
python |
Set the import-package root for a direct component install. |
Sanitizers and release portability matrices are CI or toolchain concerns rather than module CMake options.
The presets describe the CMake settings for each profile, but they do not prepare dependencies. Use build.sh or
build.bat for normal builds so Packman and Pixi paths are set consistently.
standard builds the C and C++ libraries, Python modules and bindings, and all tests. cpp-tests proves that the
libraries and native C and C++ tests do not depend on Python or nanobind. python-modules builds the compiled libraries
and pure Python packages and runs the applicable tests with nanobind disabled.
cpp-library builds only the independently consumable C and C++ libraries.
Build reusable code as a distribution in source/libraries, then stage its wheel and, when needed, its native SDK in a
Kit extension. The extension can provide the complete distribution or a declared selection of its Python packages.
Add wheel-staging.toml at the extension root:
[wheel]
distribution = "isaacsim_common"Normally, one extension provides the complete distribution. Multiple extensions can share one wheel by declaring non-overlapping sets of Python leaf packages:
[wheel]
distribution = "isaacsim_asset"
python-modules = ["isaacsim.asset.transformer"]Every extension that shares a distribution must declare python-modules, and their module paths must not overlap. The
wheel remains complete; only the files staged for each Kit extension are filtered.
Use wheel-paths to project additional top-level runtime payloads owned by the same package, such as a native Python
module and its private libraries. Use platform-wheel-paths for payloads present only on one normalized Python
platform tag:
[wheel]
distribution = "isaacsim_robot_motion"
python-modules = ["isaacsim.robot_motion.cumotion"]
wheel-paths = ["_cumotion*", "cumotion"]
[wheel.platform-wheel-paths]
win_amd64 = ["cumotion.dll"]Each path is relative to the installed wheel and may use * only in its final path component. An extension with
wheel-paths must also declare python-modules. Staging fails when a path is unsafe, matches nothing, or overlaps
another projected payload.
Repository builds use tools/repoman/repoman.py to find each wheel-staging.toml and prepare its wheel and SDK before
Repo generates and stages the application. Internal Linux builds do this after relaunching in linbuild; Windows and
--no-docker builds do it directly. The generated output stays under _cmake_build, outside Repo's _build
directory, so rebuilding the application does not remove it before staging. To stage one extension directly, run
source/libraries/build.sh -r --stage-wheel <extension> or the equivalent Windows command.
The build configures the complete CMake module graph, then packages only the distribution named in the manifest. It
creates the wheel, installs the runtime and development components into an SDK directory, and installs the wheel into a
temporary staging directory. For a complete distribution, that installation becomes pip_prebundle. For a selected
set of packages, the tool copies only the declared leaf packages and omits distribution metadata because the result is
not a complete pip installation.
The intermediate artifact directory contains only the wheel. Create a separately shippable SDK archive through the explicit packaging workflow. Staging fails when the wheel is missing or ambiguous, the package manifest is incomplete, a selected module is absent, two extensions claim the same module, or the wheel and SDK describe different packages.
The distribution and extension have separate versions. source/libraries/VERSION identifies the wheel, SDK, and
package manifest. config/extension.toml controls the extension version. They do not need to match. Use the optional
wheel-variant field when an extension needs a nondefault distribution payload, such as schemas generated for Kit's
OpenUSD version.
Root build options apply consistently to wheel staging. A normal build prepares the selected Debug and Release
configurations. --build-only uses existing dependencies without network access. --rebuild or -x removes and
rebuilds the selected library and wheel staging output. --clean removes that output before cleaning the application.
--fetch-only downloads dependencies without configuring CMake, and --generate configures without compiling or
staging. --enable-gcov enables native coverage for the staged library modules. Help, post-build-only, and stage-only
commands do not stage library wheels.
Each extension's staged directory has two inputs for the extension build:
_cmake_build/extension-wheel-stages/<configuration>/<extension>/
├── pip_prebundle/ # Complete wheel install or selected Python leaf-package projection.
└── sdk/ # CMake-installed headers, libraries, and package metadata.
In the extension's premake5.lua, load tools/isaac_build/extension_wheel.lua.
stage_isaacsim_extension_wheel links the generated pip_prebundle into the built extension. Set its optional third
argument to true to also link SDK headers. If the extension adds its own Python adapters at paths inside the staged
package, use stage_isaacsim_extension_wheel_with_python_overlays to copy the wheel contents before adding those
files; the shared stage then stays unchanged. Both helpers put the installed files in the built extension's
pip_prebundle, which is packaged at exts/<extension>/pip_prebundle.
use_isaacsim_module_sdk adds SDK include and library directories to a native extension project. Enable
add_local_runtime_rpath only for a native project inside the extension that owns the adjacent pip_prebundle.
Other extensions depend on that extension and leave it disabled. Consumers must still list the libraries they use in
links.
In extension.toml, declare the installed Python path with [[python.module]], preload required shared libraries with
platform-filtered [[native.library]] entries, and declare any runtime host adapter with [[native.plugin]]. A
compatibility wrapper is regular extension Python code; keep it separate from wheel staging and native host
adapters.
Native-library paths may use Kit's ${lib_prefix}, ${lib_ext}, ${platform}, and ${config} tokens. Do not use
wildcards; Kit treats them as literal characters for native-library preloads. Staging resolves the tokens and confirms
that each file exists. Reference the unversioned library name so releases do not require manifest changes.
Add the extension that stages the wheel as a dependency of every consuming extension. This loads the library runtime before plugins that link its SDK libraries. Do not copy the SDK or wheel into extension source, and do not commit generated staging output.
An extension stages only the wheel declared in its manifest because installation uses pip --no-deps. Kit must load
every dependency from another extension first. This prevents multiple extensions from loading separate copies of the
same native library.
Usually, another extension stages the dependency's wheel. Add that extension to [dependencies] in the current
extension's config/extension.toml.
If other Kit extensions provide a wheel dependency, map the distribution to those extensions in wheel-staging.toml.
For example:
[wheel.dependency-extensions]
isaacsim_deprecated = [
"isaacsim.core.experimental.objects",
"isaacsim.core.experimental.utils",
]This mapping says that the two listed extensions provide the isaacsim_deprecated wheel dependency. Also list both
extensions in the current extension's config/extension.toml:
[dependencies]
"isaacsim.core.experimental.objects" = {}
"isaacsim.core.experimental.utils" = {}Staging first looks for an extension with a matching wheel-staging.toml, then checks the explicit provider mapping.
It fails if neither exists or if extension.toml omits a required provider. When several extensions split one wheel,
list all of them because wheel metadata does not identify the extension that provides each module. The tool validates
these files but does not edit them.
For a native extension project that directly includes or links a staged library, call use_isaacsim_module_sdk to
add that library's SDK include and library directories. This applies whether the extension stages its own wheel or
depends on another extension's wheel. Enable add_local_runtime_rpath only when that native project owns the adjacent
pip_prebundle. A dependency used only inside the already-built feature library needs the Kit extension dependency
and runtime preload, but no extra host-adapter include or link path.
werror is a configure, build, and test preset rather than a workflow preset. Run it with:
cmake --preset werror --fresh
cmake --build --preset werror
ctest --preset werror
Every complete group owns four group-specific components. Replace <group> below with a registered distribution name:
cmake --install <build> --prefix <prefix> --component <group>-runtime
cmake --install <build> --prefix <prefix> --component <group>-development
cmake --install <build> --prefix <prefix> --component <group>-python
cmake --install <build> --prefix <prefix> --component <group>-documentation
<group>-runtimecontains the package's versioned shared libraries, registered runtime data, and explicitly registered third-party runtime libraries.<group>-developmentcontains public headers, import libraries, and the relocatablefind_package(<group> CONFIG)export. Install it with the runtime component for a native SDK.<group>-pythoncontains the package's Python APIs, implementation, typing, bindings, and same-group shared-library closure; it excludes Python distribution metadata and source tests. Install the exact-version internal dependency packages' Python components into the same prefix when their Python APIs or native libraries are needed.<group>-documentationcontains the shared version, every module changelog, and optional group or module docs.
Each component includes share/isaacsim/packages/<group>/package.json and VERSION, allowing an installer to identify
it without inspecting file names. The manifest records modules, Python imports, component names, and exact internal
dependencies. Python metadata and requirements remain in pyproject.toml.
The four components are selectable parts of one versioned package, not separate packages. A native runtime archive
usually contains runtime; an SDK contains runtime and development; and a Python installation contains python
plus required dependency packages. Documentation may ship separately or with any of them.
Use the matching workflow for each release format. Build native runtime and SDK archives without bindings
(cpp-library to assemble them and cpp-tests to validate them), so they never rely on Python. Build a Python
distribution by packaging the installed <group>-python component with its PEP 517 backend. Wheel assembly does not
compile CMake targets.
Do not publish the runtime or development files from a bindings-enabled build as the standalone native release. Installation tests load native libraries without bindings and test Python imports separately with bindings enabled.
The generated CMake configuration finds each internal package and checks its full version before loading its targets.
It also finds external CMake dependencies. When a wheel needs an internal package, add the distribution name to the
isaacsim_libraries_metadata provider in pyproject.toml. The provider adds the exact shared-version requirement.
Native-only dependencies may be omitted from wheel metadata.
packaging/package.py creates native runtime and SDK archives from an existing CMake build.
./build.sh -r --wheel installs each distribution's Python component and runs its PEP 517 backend without invoking
CMake. The wheel tool gives the backend a temporary private staging directory; pyproject.toml files do not refer to
repository staging paths. See
packaging/README.md for commands and validation expectations.
- Select the package that will ship the module. For a new package, normally add its two-component source root, such
as
isaacsim/navigationforisaacsim_navigation, withisaacsim_add_group(NAME <distribution-name> MODULES ...). A flat root named for the distribution may instead declareMODULE_PREFIX <dotted-logical-prefix>. Give it apyproject.toml, declare already registered dependencies withisaacsim_add_group_dependency, and add the package root explicitly tosource/libraries/CMakeLists.txt. Configure scikit-build-core withwheel.cmake = falseand an emptywheel.packageslist; the wheel tool supplies the installed component as packaging input. - Add the module below that root using its dotted-name suffix as directories. For example,
isaacsim.navigation.route_plannerlives atisaacsim/navigation/route_planner. AddCMakeLists.txtandCHANGELOG.md, then register it explicitly in the distribution'sCMakeLists.txt; do not give it an independent release version. - For a compiled module, use
.h/.cfor C and.hpp/.cppfor C++, then declare sources, public headers, and target dependencies withisaacsim_add_module. - For a Python API, add a typed leaf package under
python/and register it withisaacsim_add_python_module, either directly for a pure Python module or indirectly throughisaacsim_add_nanobind. - Add C, C++, and Python tests under
tests/c,tests/cpp, andtests/python, respectively. Mark binding-dependent Python tests withREQUIRES_BINDINGS. - If the module adds dependencies, update the root Pixi manifest or the library-only Packman manifest according to
ownership; do not add them to Kit dependency manifests. Add native cross-package dependencies with
isaacsim_add_group_dependencyand add equivalent Python dependency names to the package'sisaacsim_libraries_metadataprovider when its wheel needs them. External Python runtime dependencies may use supported ranges in[project.dependencies]. - Add a nanobind definition only when the Python API wraps compiled code; binding stub generation is automatic.
- Add a C symbol baseline only if the C ABI is intentionally stable.
- Add the module name to the group's
MODULES, update the moduleCHANGELOG.md, and add module reStructuredText documentation rooted atdocs/index.rstwhen the public contract needs more than header and Python documentation. - Run the
standard,cpp-tests,python-modules,cpp-library, andwerrorprofiles through the standalone entry point.
--carrier remains an alias for --stage-wheel. Source extensions can retain
module-carrier.toml and its [carrier] table; the build and staging tools accept
that manifest when wheel-staging.toml is absent. If both exist, their staging
tables must match. The old tools/isaac_build/module_carrier.lua helper and
source/libraries/tools/stage_carrier.py entry point forward to the current staging
implementation and use its output directories.