Full reference for building, testing, and verifying NanoRTC locally. For the minimum cold-start command set, see AGENTS.md § Build.
- CMake ≥ 3.16, a C99 compiler (GCC, Clang, or AppleClang)
clang-format— required for source formatting checksccache(optional but recommended) —brew install ccache; auto-detected byscripts/ci-check.sh- OpenSSL — required for
NANORTC_CRYPTO=openssland interop tests - LLVM
clangwith libFuzzer — required for fuzz harnesses (AppleClang does not ship libFuzzer) gcov+lcov— required for coverage reports- ESP-IDF toolchain — required for the ESP32 target (auto-detected via
IDF_PATH)
Default build: DataChannel only, debug symbols, run unit tests.
cmake -B build -DCMAKE_BUILD_TYPE=Debug
cmake --build build -j$(nproc)
ctest --test-dir build --output-on-failureFlags are orthogonal — any combination is supported. The build system enforces that all 7 canonical combinations compile and pass tests (DATA, AUDIO, MEDIA, MEDIA_H265, AUDIO_ONLY, MEDIA_ONLY, CORE_ONLY).
cmake -B build -DNANORTC_FEATURE_DATACHANNEL=ON # SCTP + DCEP (default ON)
cmake -B build -DNANORTC_FEATURE_AUDIO=ON # RTP/SRTP + jitter buffer
cmake -B build -DNANORTC_FEATURE_VIDEO=ON # RTP/SRTP + BWE (H.264 only by default)
cmake -B build -DNANORTC_FEATURE_H265=ON # H.265/HEVC codec (opt-in; requires VIDEO=ON)
cmake -B build -DNANORTC_FEATURE_DC_RELIABLE=OFF # Disable retransmit (sub-feature of DC)
cmake -B build -DNANORTC_FEATURE_DC_ORDERED=OFF # Disable ordered delivery (sub-feature of DC)
cmake -B build -DNANORTC_FEATURE_IPV6=OFF # Disable IPv6 address support (saves ~300 bytes)
cmake -B build -DNANORTC_FEATURE_TURN=OFF # Disable TURN relay (saves ~700B RAM + ~13KB code)
cmake -B build -DNANORTC_FEATURE_ICE_SRFLX=OFF # Skip srflx local-candidate registration (LAN-only)Common combinations:
# Full media (H.264 only)
cmake -B build -DNANORTC_FEATURE_DATACHANNEL=ON -DNANORTC_FEATURE_AUDIO=ON -DNANORTC_FEATURE_VIDEO=ON
# Full media + H.265
cmake -B build -DNANORTC_FEATURE_DATACHANNEL=ON -DNANORTC_FEATURE_AUDIO=ON -DNANORTC_FEATURE_VIDEO=ON -DNANORTC_FEATURE_H265=ON
# Audio only (no SCTP)
cmake -B build -DNANORTC_FEATURE_DATACHANNEL=OFF -DNANORTC_FEATURE_AUDIO=ONFor RAM/flash footprint per combination and tuning knobs, see memory-profiles.md.
Pick one. mbedtls is the default and targets embedded; openssl is typical for Linux host development and required for interop tests.
cmake -B build -DNANORTC_CRYPTO=openssl
cmake -B build -DNANORTC_CRYPTO=mbedtlsExamples are Linux-host applications and are not built by default.
# Build examples (Linux host, full media)
cmake -B build -DNANORTC_FEATURE_DATACHANNEL=ON -DNANORTC_FEATURE_AUDIO=ON -DNANORTC_FEATURE_VIDEO=ON \
-DNANORTC_CRYPTO=openssl -DNANORTC_BUILD_EXAMPLES=ONOverride compile-time tunables without modifying the repo:
cmake -B build -DNANORTC_CONFIG_FILE=\"my_nanortc_config.h\"Runs end-to-end tests against libdatachannel. Requires OpenSSL and a C++ compiler.
cmake -B build -DNANORTC_CRYPTO=openssl -DNANORTC_BUILD_INTEROP_TESTS=ON
cmake --build build -j$(nproc)
ctest --test-dir build -R interop --output-on-failurecmake -B build -DADDRESS_SANITIZER=ONRequires LLVM clang with libFuzzer (not AppleClang).
./scripts/run-fuzz.sh # 30s per harness (default)
./scripts/run-fuzz.sh 300 # 5min per harness
./scripts/run-fuzz.sh 30 fuzz_stun # Single harnessRequires gcov and lcov.
./scripts/coverage.sh # Generate HTML report
./scripts/coverage.sh --threshold 80 # Fail if < 80%
./scripts/coverage.sh --open # Open report in browserAuto-detected via IDF_PATH. The standard way to load the ESP-IDF environment once per shell session (exports IDF_PATH, idf.py, and the cross-toolchain) is the get_idf alias from the ESP-IDF install script:
get_idfget_idf is defined by ESP-IDF's install.sh / install.fish and typically resolves to something like alias get_idf='. $HOME/esp/esp-idf/export.sh'. If it's not defined in your shell, source export.sh directly from wherever your IDF checkout lives.
Configure, build, flash, and view logs from the project directory (for example examples/esp32_datachannel/):
idf.py set-target esp32p4 # one-time per project; esp32s3 / esp32c6 also supported
idf.py menuconfig # optional — adjust Kconfig knobs (feature flags, buffer sizes)
idf.py build # compile firmware
idf.py -p /dev/tty.usbmodem* flash # write firmware to the attached board
idf.py -p /dev/tty.usbmodem* monitor # serial log viewer (Ctrl-] to quit)
idf.py -p /dev/tty.usbmodem* flash monitor # flash then immediately open monitorOmit -p to let idf.py auto-detect the USB serial port. On Linux the device usually appears as /dev/ttyUSB0 or /dev/ttyACM0.
The esp32_camera example uses esp_board_manager for sensor / codec / LDO wiring. The per-board components/gen_bmgr_codes/board_manager.defaults file is generated from the YAML under boards/ and intentionally not tracked in git.
When boards/ contains exactly one board directory (the default — esp32_p4_nano), CMakeLists.txt auto-runs the generator at configure time, so idf.py set-target esp32p4 && idf.py build just works.
Run the generator manually only when you have multiple boards under boards/ (e.g. during custom-board bring-up) and need to pick:
python managed_components/espressif__esp_board_manager/gen_bmgr_config_codes.py \
-b <board-name> -c boardsIf the auto-generator ever fails, configure aborts with the generator's stderr; inspect components/gen_bmgr_codes/ for partial output. Other examples/esp32_* targets don't use esp_board_manager and don't need this step.
clang-format -i src/*.c src/*.h include/*.h crypto/*.h crypto/*.cscripts/ci-check.sh runs the same matrix as GitHub Actions. It auto-detects ccache and keeps build directories across runs for incremental compilation.
./scripts/ci-check.sh # full matrix; mirrors GitHub Actions
./scripts/ci-check.sh --fast # tier-1 subset for tight pre-push loops (DATA + MEDIA + ASan, ~5s with ccache hit)
./scripts/ci-check.sh --clean # wipe build dirs first