Spider Lang · Internship 2026

Running Spider
on ESP32

How the Spider Runtime was cross-compiled for the Xtensa architecture and flashed onto physical hardware using ESP-IDF.

Diego Alberto López  ·  Build System  ·  April 2026
script.spider ↓ Spider Compiler bytecode.spd ← Spider's own format, not x86, not Xtensa Spider Runtime (C++) ↓ xtensa-esp-elf-g++ ← ESP-IDF toolchain spider_esp32.bin ↓ esptool.py ESP32 flash memory ← Runtime lives here permanently

Spider's bytecode is a neutral format that belongs to no specific processor. The toolchain's job is not to convert bytecode — it compiles the C++ source of the Runtime itself into Xtensa machine code. Once flashed, the Runtime lives in the ESP32's flash memory and interprets Spider bytecode at runtime.

01

Prerequisites

Install ESP-IDF v5.x and add the Xtensa toolchain to your PATH:

# Add to ~/.bashrc to make it permanent
export PATH=$PATH:/c/Espressif/tools/xtensa-esp-elf/esp-14.2.0_20251107/xtensa-esp-elf/bin
02

Compile flags for ESP32

The Runtime uses compile-time platform detection via distro_mcu.hpp. These flags tell it which hardware it is targeting:

-DESP32
Activates ESP32 detection in distro_mcu.hpp
-DSPIDER_DISTRO_MICRO
Enables microcontroller mode (reduced memory footprint)
-DSPIDER_OS_NONE
Declares bare-metal environment, no OS
-mlongcalls
Required for Xtensa's memory layout and call distances
-fno-exceptions -fno-rtti
Disable C++ features unavailable on bare-metal
-O0
No optimizations — faster compilation during development
03

Build with ESP-IDF (CMake)

The bare-metal Makefile approach caused boot loops because the ESP32 bootloader expects a specific binary format. The correct approach is to use ESP-IDF's CMake build system, which generates the bootloader, partition table, and app binary automatically.

# From spider-micro-buildtools/esp32/idf_project/
idf.py set-target esp32
idf.py build
idf.py -p COM6 flash monitor

The CMakeLists.txt registers the Spider Runtime source files as a component:

set(SPIDER_RUNTIME_SRC
    "${CMAKE_CURRENT_SOURCE_DIR}/../../../../spider-runtime/src"
)

idf_component_register(
    SRCS
        "main.cpp"
        "${SPIDER_RUNTIME_SRC}/spider/runtime/Runtime.cpp"
        "${SPIDER_RUNTIME_SRC}/spider/runtime/cpu/CPU.cpp"
        ... (all Runtime source files)
    PRIV_INCLUDE_DIRS "${SPIDER_RUNTIME_SRC}"
)
Note: Relative paths using CMAKE_CURRENT_SOURCE_DIR are used to avoid exposing personal directory structure in the repository.
04

app_main — The ESP32 entry point

ESP-IDF requires app_main() instead of the standard main(). The Spider Runtime is initialized here with a fixed amount of RAM:

#include "esp_log.h"
#include <spider/runtime/Runtime.hpp>

static const char* TAG = "Spider";

extern "C" void app_main(void) {
    ESP_LOGI(TAG, "Spider Runtime starting...");
    spider::Runtime runtime(32 * 1024);   // 32 KB RAM
    ESP_LOGI(TAG, "Spider Runtime initialized!");
    ESP_LOGI(TAG, "RAM size: 32KB");
    while(1) { vTaskDelay(pdMS_TO_TICKS(1000)); }
}
I (274) Spider: Spider Runtime starting...
I (274) Spider: Spider Runtime initialized!
I (274) Spider: RAM size: 32KB
    
05

Repository structure

The build tools live in spider-micro-buildtools, separate from the Runtime source. Both repos must be cloned at the same level:

Internship/ ├── spider-runtime/ ← Runtime C++ source └── spider-micro-buildtools/ └── esp32/ ├── Makefile ← bare-metal reference build ├── gen_makefile.py ├── main_esp32.cpp ├── README.md └── idf_project/ ← ESP-IDF project (use this) ├── CMakeLists.txt └── main/ ├── CMakeLists.txt └── main.cpp