Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Build as a CMake subdirectory

This is one of the two ways to integrate nano-ros into a C or C++ project, and the lower-level one: the repo’s top-level CMakeLists.txt exposes everything via add_subdirectory(...). The higher-level, ament-shaped alternative is find_package(nano_ros REQUIRED)nano_rosConfig.cmake at the checkout root, located via nano_ros_ROOT (RFC-0048) — which every in-tree example now uses. Either way there is NO install step: phase-140 removed the install prefix and the old find_package(NanoRos) (capital) config pipeline. Vendoring the repo into a company tree (pinning, offline CI, upgrade workflow) has its own page: Integrating into a Vendored Tree.

Layout

my_app/
├── CMakeLists.txt
├── main.c
└── third_party/
    └── nano-ros/        # git clone / git submodule of this repo

User project CMakeLists.txt

cmake_minimum_required(VERSION 3.22)
project(my_app C)

# Pick platform + RMW BEFORE add_subdirectory.
set(NANO_ROS_PLATFORM posix)   # posix | freertos | nuttx | threadx | zephyr | baremetal
set(NANO_ROS_RMW     zenoh)    # zenoh | xrce | cyclonedds

add_subdirectory(third_party/nano-ros nano_ros)

add_executable(my_app main.c)
target_link_libraries(my_app PRIVATE NanoRos::NanoRos)
if(COMMAND nros_platform_link_app)   # defined by zephyr/threadx platforms only
    nros_platform_link_app(my_app)
endif()

# Optional — generate C bindings for ROS 2 .msg / .srv / .action files.
# (LANGUAGE defaults to CPP; full spelling table → user-guide
# "Message Generation".)
nano_ros_generate_interfaces(std_msgs LANGUAGE C
    DEPENDENCIES builtin_interfaces)
target_link_libraries(my_app PRIVATE std_msgs__nano_ros_c)

That’s the whole story for the host-POSIX / zenoh case. CMake’s transitive target propagation pulls in libnros_c.a, libnros_rmw_zenoh_staticlib.a, the POSIX platform shim, system libraries (pthread, dl, m), and the per-build nros_config_generated.h header automatically.

Cache variables

VariableDefaultValues
NANO_ROS_PLATFORMposixposix, freertos, nuttx, threadx, esp_idf (legacy spellings: freertos_armcm3, nuttx_armv7a, threadx_linux, threadx_riscv64). Zephyr and bare-metal are not add_subdirectory platforms — they enter via the Zephyr module / cargo directly
NANO_ROS_BOARD(unset)required for threadx (threadx-linux or riscv64-qemu)
NANO_ROS_SKIP_BOOTSTRAPOFFON skips the configure-time bootstrap (git submodule updates + a possible network FetchContent of Corrosion). Required for air-gapped/mirrored CI — pre-seed submodules and install Corrosion first (nros setup --tool corrosion)
NANO_ROS_FEATURES(empty)extra cargo features forwarded to the Rust build
NANO_ROS_RMWzenohzenoh, dds, xrce, cyclonedds
NANO_ROS_ROS_EDITIONhumblehumble, iron, jazzy
NANO_ROS_BUILD_CODEGENONON / OFF

Variables MUST be set(...) BEFORE add_subdirectory(...) — the sub-project consumes them at include time.

What about installing?

Phase-140 deleted every nano-ros-side install(...) rule. nano-ros is consumed in source form — never out of an installed prefix. If you need a shippable artefact, your user project owns the install layout; ship your binary, not nano-ros itself.

For RTOS users who want a more idiomatic surface than raw add_subdirectory, see the integration shells under integrations/<rtos>/ — they translate west / esp-idf / NuttX / PX4 manifests into the same root CMake. Each shell is a ~20-line wrapper around add_subdirectory(<repo>).

Worked example

The examples/native/c/talker/CMakeLists.txt is the canonical copy-out template: it resolves the nano-ros checkout root once (-DNANO_ROS_ROOT cache var → NROS_REPO_DIR env var → in-repo walk-up), includes the workspace helpers, generates the message bindings (nros_find_interfaces), and declares the app via nano_ros_entry(...) — ~55 lines including codegen + per-app fixup. All in-tree C/C++ examples follow the same shape.