Set up POSIX
The SDK also builds as a plain CMake library for Linux and macOS. The result is a normal host process that speaks the same MQTT contract as a real device: same node data model, same shadow updates, same OTA job handling.
The POSIX build is currently intended for testing and development without hardware — products ship on ESP-IDF. Within that role it is the fastest way to work on app-side, backend, or protocol behaviour, and it is what the SDK's own integration tests run against. Everything platform-specific sits behind the osal abstraction layer, so your app_main.c is identical to the ESP-IDF version.
For hardware builds, see Set up ESP-IDF.
What POSIX gives you (and what it doesn't)
| POSIX host | |
|---|---|
| RainMaker Neo core, data model, MQTT, shadows | Real |
| Schedules, automations, timezone, system service | Real |
| Local control HTTP server, challenge-response | Real |
| OTA over MQTT | Real, against a mock bootloader with ota_0 / ota_1 files instead of flash partitions |
| Factory NVS | Real, as files under nvs_persistent/ |
| Wi-Fi provisioning | No-op. The host is already on a network; app_network_provision() returns success without doing anything. |
| LED, button, GPIO | Stubbed. app_led / app_button log !!!HARDWARE!!! instead of driving pins. |
1. Toolchain
Install a native toolchain:
- CMake 3.16 or newer
- A C compiler (GCC or Clang)
- Ninja or Make
2. Python environment
Some POSIX dependencies — notably the mbedTLS configuration scripts and the Kconfig tooling — need Python packages available on PATH when CMake runs. CMake installs them for you, but only if a virtual environment is active.
From the SDK repository root:
python3 -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
python -m pip install -U pip
pip install -r posix_requirements.txt
Keep the environment activated for every configure and build. If CMake reports missing Python modules, this is almost always why.
Upstream sources for mbedTLS, Unity, and protobuf-c are fetched by CMake FetchContent on first configure (see third_party/install_scripts/), so the first build needs network access. They are never committed to the SDK.
3. Build an example
cd examples/light
cmake -B build
cmake --build build
The build tree comes out like this:
build/
├── light # mock bootloader, named after the project
├── partitions/
│ ├── ota_0 # the app image — this is what you upload for OTA
│ └── ota_1 # the second OTA slot
│ └── ota_config.bin
└── nvs_persistent/ # factory NVS lives here (see below)
Run it from the build directory so the relative paths for NVS and the OTA partitions resolve:
cd build
./light
./light is the mock bootloader; it launches the app image from partitions/. Send SIGINT (Ctrl-C) for a clean teardown.
Before the node can connect it needs credentials: generate a factory NVS image and copy the generated nvs_persistent/ directory next to the executable — see Factory NVS.
4. Add the SDK to your own project
A POSIX project consumes the SDK with add_subdirectory() and links against the esp_rmaker_neo target. Order matters, because esp_rmaker_neo transitively defines the osal platform targets that the example helpers depend on:
cmake_minimum_required(VERSION 3.16)
# Firmware version — must be set before project()
set(PROJECT_VER "1.0.0" CACHE STRING "Firmware version")
project(my_app C ASM)
add_executable(${PROJECT_NAME} main/app_main.c main/app_driver.c)
set(RMNG_ROOT /path/to/esp-rainmaker-neo-firmware)
add_subdirectory(${RMNG_ROOT}/components/esp_rmaker_neo components/esp_rmaker_neo)
add_subdirectory(${RMNG_ROOT}/components/esp_rmaker_neo_ota components/esp_rmaker_neo_ota) # optional
target_link_libraries(${PROJECT_NAME} PRIVATE esp_rmaker_neo esp_rmaker_neo_ota)
To seed Kconfig defaults for the SDK subtree, prepend to SDKCONFIG_DEFAULTS before the add_subdirectory() call:
list(PREPEND SDKCONFIG_DEFAULTS ${CMAKE_CURRENT_LIST_DIR}/sdkconfig.defaults)
If you link esp_rmaker_neo_ota, it exports the mock-bootloader variables the examples use to lay out their build tree:
| Variable | Meaning |
|---|---|
RMNG_OTA_POSIX_BOOTLOADER_NAME | Target name of the mock bootloader — rename it to your project name |
RMNG_OTA_POSIX_PARTITION_FOLDER | Directory the app image must be built into (partitions/) |
RMNG_OTA_POSIX_DEFAULT_FIRST_PARTITION | Output name for the initial app image (ota_0) |
See examples/light/CMakeLists.txt for the full pattern, and Start your own project.
Next steps
- Configure and build —
menuconfigon POSIX - Factory NVS — required before the node can connect
- Code basics