* Add ARCH_PORTDUINO_WASM build: meshtasticd in WebAssembly over WebUSB
Compile the full portduino firmware to WebAssembly (Emscripten) so a real node runs in a browser tab or headless Node, driving a LoRa radio over WebUSB through a CH341 — the desktop Ch341Hal path with its libusb backend swapped for a WebUSB one. The native/desktop portduino build is unchanged.
New build env under src/platform/portduino/wasm/ (excluded from the native build_src_filter): WebUSB libpinedio backend, config/FS/region/MAC/PhoneAPI glue, wasm setup/loop, JS WebUSB runtime, and build stubs. bin/build-portduino-wasm.sh runs a standalone cached emcc build to build/wasm/meshnode.{mjs,wasm}.
Six firmware sources gain #ifdef ARCH_PORTDUINO_WASM guards (single-threaded cooperative emscripten_sleep loop, continuous RX, US region default, std RNG, no-popen exec); none affect non-wasm builds.
* PortDuino WASM: CI build job, cross-platform libdeps, configurable adapter
bin/build-portduino-wasm.sh: auto-detect native-macos (macOS) vs native (Linux/CI) libdeps with a NATIVE_ENV override, and use the SAME env's Crypto with an XEdDSA-present guard. Drops the heltec-v3/Crypto borrow — the meshtastic/Crypto pin already ships XEdDSA; the native libdeps cache was just stale. No env pin change.
Add .github/workflows/build_portduino_wasm.yml: build the ARCH_PORTDUINO_WASM target in CI (ubuntu + emsdk, native libdeps) so it can't silently bit-rot; asserts build/wasm/meshnode.{mjs,wasm}.
src/platform/portduino/wasm: add wasm_set_lora_* setters so the JS host can configure any CH341 LoRa adapter (module, USB ids, DIO/TCXO, SPI speed, pins); wasm_config_apply falls back to the MeshToad defaults when unset.
* WASM: build as a first-class [env:wasm] via platform-wasm (retire emcc script)
Replace the standalone emcc build (bin/build-portduino-wasm.sh) with a normal
PlatformIO env, `pio run -e wasm`, using the new meshtastic/platform-wasm
platform (emcc/em++ + Asyncify, the WASM sibling of platform-native). The
portduino WebAssembly node is now built the same way as every other target.
- variants/native/portduino/platformio.ini: add [env:wasm] (platform pinned to
platform-wasm, board wasm). Translates the script's source set into a curated
build_src_filter, the ~30 EXCLUDE_* defines, and the lib set; defines
ARCH_PORTDUINO_WASM in-repo so correctness doesn't hinge on the platform's
board.json.
- extra_scripts/wasm_link_flags.py: the firmware-specific emcc *link* settings
(EXPORT_NAME, EXPORTED_RUNTIME_METHODS, EXPORTED_FUNCTIONS, ASYNCIFY_IMPORTS).
PlatformIO feeds build_flags to compile only, so these must ride LINKFLAGS;
without it the WebUSB Asyncify seam and the JS host's runtime methods are
dropped (the _wasm_* exports survive only via EMSCRIPTEN_KEEPALIVE).
- PortduinoGlue.{h,cpp}: guard the yaml-cpp dependency out of the WASM build
(#ifndef ARCH_PORTDUINO_WASM around the include, emit_yaml/loadConfig/
readGPIOFromYaml). The browser node configures via the wasm_set_lora_* setters
and dead-strips the YAML path; this drops the host yaml-cpp build dependency
entirely. Native is unchanged (guards are inert there).
- portduino_glue_wasm.cpp / portduino_main_wasm.cpp: repair EM_ASM JS that a
formatter had mangled (!== -> != =, regex split) in the prior landing; the
emcc link succeeds regardless, so CI now runs `node --check meshnode.mjs`.
- .github/workflows/build_portduino_wasm.yml: build via `pio run -e wasm`
(artifacts under .pio/build/wasm/), trigger on the shared inputs the env
inherits (root platformio.ini, bin/platformio-*.py).
- NodeDB.cpp: drop the dead ARCH_PORTDUINO_WASM region-default branch (region
now defaults the same as native).
- Crypto renovate pins: add the missing gitBranch so they track upstream.
Output: .pio/build/wasm/meshnode.{mjs,wasm} (ES module, factory createMeshNode).
Verified: pio run -e wasm (against the published platform archive), node --check,
module instantiates in Node with all exports; native-macos + Docker native unit
tests (450/450) still pass.
* Fix name on the Piggystick
* wasm: pin platform-wasm at the GPL-3.0-relicensed commit
platform-wasm's LICENSE was always GPLv3 (matching this firmware), but its
platform.json/README still declared Apache-2.0 (mis-copied from platform-native).
That's fixed upstream in b83fa5b; bump the [env:wasm] pin to it. Build output is
unchanged (license metadata only). Verified: pio run -e wasm against b83fa5b.
* wasm: make reboot() actually restart the node (was a no-op)
In wasm the reboot path is live (main.cpp -> Power::powerCommandsCheck ->
Power::reboot), but Power::reboot's ARCH_PORTDUINO arm tore down SPI/Wire/Serial
and then called the no-op ::reboot() stub — leaving the node running with a dead
radio until the tab was manually reloaded. Triggers include an admin/phone
reboot, factory reset, the "reconfigure failed" path, and the 60 s stuck-TX
hardware watchdog (RadioLibInterface).
- Power::reboot(): add an ARCH_PORTDUINO_WASM arm (before ARCH_PORTDUINO, since
the wasm build defines both) that skips the host teardown and just calls
::reboot(). notifyReboot already let modules persist.
- ::reboot() (glue): hand off to the JS host — browser reloads the tab (NodeDB
state survives via IDBFS, same identity returns); headless calls Module.onReboot
if provided, else logs. Loose !=/== so clang-format doesn't mangle the EM_ASM JS.
- README: document the reboot handoff + the Module.onReboot hook.
Verified: pio run -e wasm + node --check (EM_ASM intact); native-macos unaffected.
* wasm: rename env to native-wasm and run it in the main CI matrix
Rename [env:wasm] -> [env:native-wasm] for consistency with the portduino
native family (native, native-macos, native-tft). The build dir follows to
.pio/build/native-wasm/ (artifact is still meshnode.{mjs,wasm}); the PIOENV
guard in extra_scripts/wasm_link_flags.py, the README, and the companion wrapper
move with it. The board stays `wasm`.
Also wire the build into normal CI: build_portduino_wasm.yml becomes a reusable
workflow (workflow_call) invoked as the `build-wasm` job of main_matrix.yml, so
the WebAssembly node is built like every other platform instead of on a separate
path trigger.
* native-wasm: auto-locate the Emscripten SDK (pre-build script)
`pio run -e native-wasm` failed with "emcc not found" whenever it was invoked
from a shell that hadn't sourced emsdk_env.sh — a VS Code task, an IDE build
button, a bare terminal. Add a pre: extra script that probes the usual emsdk
locations ($EMSDK_ENV, $EMSDK, ~/emsdk, ./.emsdk, the sibling companion
checkout), sources emsdk_env.sh, and imports the resulting environment so the
platform builder and emcc see PATH/EMSDK/EM_CONFIG. No-op when emcc is already
reachable (CI), silent when no SDK is found (the platform emits its own error).
* wasm: address PR review feedback
- js/bridge.js: import CH341 from "./ch341.js" (sibling in this layout), not
"../src/ch341.js" which doesn't resolve here.
- js/ch341.js: a zero-length transferIn while MISO bytes are still outstanding
now throws instead of breaking out with a partially-filled buffer — silent SPI
corruption becomes a loud error, matching the comment above it.
- libpinedio_webusb.c: webusb_set_auto_cs honors the AUTO_CS option (? 1 : 0)
instead of the always-on ? 1 : 1. Runtime behavior is unchanged — Ch341Hal sets
AUTO_CS=0 right after pinedio_init (RadioLib drives the active-low NSS); the
option just isn't set yet at init, so this now correctly defaults off.
- SX126xInterface.cpp: the RX-start error log now names the method actually
called (startReceive vs startReceiveDutyCycleAuto) instead of hardcoding the
duty-cycle name in the WASM branch.
* native-wasm: drop the emsdk bootstrap shim (now in platform-wasm)
The Emscripten SDK auto-location moved into the platform-wasm builder, so the
firmware no longer needs its own pre: extra script. Remove
extra_scripts/wasm_emsdk_env.py and bump the platform pin to the build that
carries the bootstrap. The wasm_link_flags.py post script stays — those exported
fns / runtime methods / Asyncify import seam are firmware-app-specific.
* wasm: use the canonical companion name (meshtasticd-wasm-node)
The companion repo was renamed meshtastic-web-node -> meshtasticd-wasm-node; fix
the stale name in the wasm README and bump the platform pin to the build that
promotes the canonical name in its emsdk auto-location.
* wasm: re-entrancy guard for the API/region entry points + flaky-open retry
Two robustness fixes for the browser node:
- Re-entrancy guard. The node is single-threaded + Asyncify: while setup()/loop()
is suspended inside a WebUSB transfer, the JS event loop is free, so a stray
DOM/timer callback that re-enters a wasm_* entry point starts a second Asyncify
unwind ("async operation already in flight" abort) or clobbers shared PhoneAPI
state (observed as a "PhoneAPI::available unexpected state" flood). Add a
g_wasm_in_firmware flag set around setup()/loop() (portduino_main_wasm.cpp); the
wasm_set_region / wasm_api_to_radio / wasm_api_from_radio / wasm_api_available
entry points now reject a mid-tick call (return busy) instead of corrupting or
aborting. The host must still call them between ticks — this is the safety net
the design lacked, not a substitute for the JS queue.
- CH341 open retry (js/bridge.js). First-connect WebUSB is flaky — the interface
is briefly unclaimable right after the grant, or held by a prior session,
giving a transient "Could not open SPI: -1". Retry the open with a short
backoff, closing the device between attempts so claimInterface starts clean.
* wasm: exclude emscripten-only sources from cppcheck
The `check` board matrix runs `pio check` (cppcheck) over all of src/,
including src/platform/portduino/wasm/. cppcheck can't parse the EM_ASYNC_JS/
EM_JS macros (Syntax Error: AST broken at libpinedio_webusb.c:39,
internalAstError) and these sources are not part of any checked board build
([env:native-wasm] is board_level=extra, compiled by the build-wasm CI job).
Suppress the wasm dir in suppressions.txt, the same way generated/ and .pio/
are already excluded.
* wasm: coalesce FS.syncfs so two never run at once
IDBFS syncfs is async; the explicit wasm_fs_sync (5s timer + post-save +
beforeunload) could overlap a prior in-flight sync, warning "2 FS.syncfs
operations in flight at once". Serialize: if a sync is running, mark a pending
re-sync and let the in-flight one chain it on completion — at most one in flight,
trailing writes still flushed. (Companion drops IDBFS autoPersist so this is the
single persistence path.)
* wasm: silence false-positive SAST on the emscripten glue
- extra_scripts/wasm_link_flags.py: restore the trunk-ignore-all(ruff/F821,
flake8/F821) header every other SCons extra_script carries; Import/env are
SConscript-injected globals, so ruff/flake8 flag them as undefined.
- .semgrepignore: exclude src/platform/portduino/wasm/js/ (browser WebUSB glue,
not part of the firmware binary). The unsafe-formatstring rule false-positives
on its benign retry/diagnostic console logs.
* Update .github/workflows/build_portduino_wasm.yml
Co-authored-by: Austin <vidplace7@gmail.com>
---------
Co-authored-by: Austin <vidplace7@gmail.com>
356 lines
16 KiB
INI
356 lines
16 KiB
INI
[native_base]
|
|
extends = portduino_base
|
|
build_flags = ${portduino_base.build_flags} -I variants/native/portduino
|
|
-I /usr/include
|
|
board = cross_platform
|
|
board_level = extra
|
|
lib_deps =
|
|
${portduino_base.lib_deps}
|
|
# renovate: datasource=custom.pio depName=Melopero RV3028 packageName=melopero/library/Melopero RV3028
|
|
melopero/Melopero RV3028@1.2.0
|
|
|
|
build_src_filter = ${portduino_base.build_src_filter}
|
|
|
|
[env:native]
|
|
extends = native_base
|
|
; The pkg-config commands below optionally add link flags.
|
|
; the || : is just a "or run the null command" to avoid returning an error code
|
|
build_flags = ${native_base.build_flags}
|
|
!pkg-config --libs libulfius --silence-errors || :
|
|
!pkg-config --libs openssl --silence-errors || :
|
|
!pkg-config --cflags --libs sdl2 --silence-errors || :
|
|
!pkg-config --cflags --libs libbsd-overlay --silence-errors || :
|
|
|
|
[env:native-tft]
|
|
extends = native_base
|
|
build_type = release
|
|
lib_deps =
|
|
${native_base.lib_deps}
|
|
${device-ui_base.lib_deps}
|
|
build_flags = ${native_base.build_flags} -Os -lX11 -linput -lxkbcommon -ffunction-sections -fdata-sections -Wl,--gc-sections
|
|
-D RAM_SIZE=16384
|
|
-D USE_X11=1
|
|
-D HAS_TFT=1
|
|
-D HAS_SCREEN=1
|
|
-D LV_CACHE_DEF_SIZE=6291456
|
|
-D LV_BUILD_TEST=0
|
|
-D LV_USE_LIBINPUT=1
|
|
-D LV_LVGL_H_INCLUDE_SIMPLE
|
|
-D LV_CONF_INCLUDE_SIMPLE
|
|
-D LV_COMP_CONF_INCLUDE_SIMPLE
|
|
-D USE_LOG_DEBUG
|
|
-D LOG_DEBUG_INC=\"DebugConfiguration.h\"
|
|
-D USE_PACKET_API
|
|
-D VIEW_320x240
|
|
!pkg-config --libs libulfius --silence-errors || :
|
|
!pkg-config --libs openssl --silence-errors || :
|
|
!pkg-config --cflags --libs sdl2 --silence-errors || :
|
|
!pkg-config --cflags --libs libbsd-overlay --silence-errors || :
|
|
build_src_filter =
|
|
${native_base.build_src_filter}
|
|
|
|
[env:native-fb]
|
|
extends = native_base
|
|
build_type = release
|
|
lib_deps =
|
|
${native_base.lib_deps}
|
|
${device-ui_base.lib_deps}
|
|
build_flags = ${native_base.build_flags} -Os -ffunction-sections -fdata-sections -Wl,--gc-sections
|
|
-D RAM_SIZE=8192
|
|
-D USE_FRAMEBUFFER=1
|
|
-D LV_COLOR_DEPTH=32
|
|
-D HAS_TFT=1
|
|
-D HAS_SCREEN=1
|
|
-D LV_BUILD_TEST=0
|
|
-D LV_USE_LOG=0
|
|
-D LV_USE_EVDEV=1
|
|
-D LV_LVGL_H_INCLUDE_SIMPLE
|
|
-D LV_CONF_INCLUDE_SIMPLE
|
|
-D LV_COMP_CONF_INCLUDE_SIMPLE
|
|
-D USE_LOG_DEBUG
|
|
-D LOG_DEBUG_INC=\"DebugConfiguration.h\"
|
|
-D USE_PACKET_API
|
|
-D VIEW_320x240
|
|
-D MAP_FULL_REDRAW
|
|
!pkg-config --libs libulfius --silence-errors || :
|
|
!pkg-config --libs openssl --silence-errors || :
|
|
!pkg-config --cflags --libs libbsd-overlay --silence-errors || :
|
|
build_src_filter =
|
|
${native_base.build_src_filter}
|
|
|
|
[env:native-tft-debug]
|
|
extends = native_base
|
|
build_type = debug
|
|
lib_deps =
|
|
${native_base.lib_deps}
|
|
${device-ui_base.lib_deps}
|
|
build_flags = ${native_base.build_flags} -O0 -fsanitize=address -lX11 -linput -lxkbcommon
|
|
-D DEBUG_HEAP
|
|
-D RAM_SIZE=16384
|
|
-D USE_X11=1
|
|
-D HAS_TFT=1
|
|
-D HAS_SCREEN=0
|
|
-D LV_CACHE_DEF_SIZE=6291456
|
|
-D LV_BUILD_TEST=0
|
|
-D LV_USE_LOG=1
|
|
-D LV_USE_SYSMON=1
|
|
-D LV_USE_PERF_MONITOR=1
|
|
-D LV_USE_MEM_MONITOR=0
|
|
-D LV_USE_PROFILER=0
|
|
-D LV_USE_LIBINPUT=1
|
|
-D LV_LVGL_H_INCLUDE_SIMPLE
|
|
-D LV_CONF_INCLUDE_SIMPLE
|
|
-D LV_COMP_CONF_INCLUDE_SIMPLE
|
|
-D USE_LOG_DEBUG
|
|
-D LOG_DEBUG_INC=\"DebugConfiguration.h\"
|
|
-D USE_PACKET_API
|
|
-D VIEW_320x240
|
|
!pkg-config --libs libulfius --silence-errors || :
|
|
!pkg-config --libs openssl --silence-errors || :
|
|
!pkg-config --cflags --libs libbsd-overlay --silence-errors || :
|
|
build_src_filter = ${env:native-tft.build_src_filter}
|
|
|
|
[env:coverage]
|
|
extends = env:native
|
|
build_flags = -lgcov --coverage -fprofile-abs-path -fsanitize=address ${env:native.build_flags}
|
|
; https://docs.platformio.org/en/latest/projectconf/sections/env/options/test/test_testing_command.html
|
|
test_testing_command =
|
|
${platformio.build_dir}/${this.__env__}/meshtasticd
|
|
-s
|
|
|
|
; ---------------------------------------------------------------------------
|
|
; Native build for macOS (Darwin / arm64 + x86_64). Headless meshtasticd that
|
|
; runs in SimRadio mode (`-s`) or against real LoRa hardware via a CH341
|
|
; USB-SPI bridge. No BlueZ, libgpiod, or Linux I2C — those require Linux.
|
|
;
|
|
; Prerequisites (Homebrew):
|
|
; brew install platformio yaml-cpp libuv openssl@3 libusb argp-standalone pkg-config jsoncpp
|
|
; # Optional: enable the HTTP API (PiWebServer) on macOS:
|
|
; brew install ulfius
|
|
;
|
|
; The macOS-side patches now live upstream:
|
|
; * meshtastic/platform-native — `String.h`-shadow shim, `-Wno-enum-constexpr-conversion`,
|
|
; empty-variant-dir guard. Pulled via `portduino_base.platform` zip pin.
|
|
; * meshtastic/framework-portduino — LinuxHardwareI2C macOS stubs, AsyncUDP
|
|
; SOCK_NONBLOCK fallback, Common.h __APPLE__ guard, WiFiServer.cpp extern-C
|
|
; fix, package.json URL refresh. Pulled by platform-native at its pinned commit.
|
|
; This env therefore only carries the firmware-side build flags and src filter.
|
|
;
|
|
; Real LoRa hardware on macOS:
|
|
; The same lib_dep `pine64/libch341-spi-userspace` used on Linux works on
|
|
; macOS as-is — its `libusb_detach_kernel_driver()` call is `__linux__`-
|
|
; guarded, but on macOS the kernel doesn't bind a driver to a CH341A SPI
|
|
; bridge (PID 0x5512; bDeviceClass=0xff vendor-specific) by default, so
|
|
; no detach is needed. Apple's bundled CH34x driver targets the CH340
|
|
; *UART* variant (PID 0x7523) — different product. libusb opens the device
|
|
; and claims interface 0 directly via IOUSBHostInterface.
|
|
;
|
|
; To use, point `meshtasticd` at any of the existing `bin/config.d/lora-*.yaml`
|
|
; files that specify `spidev: ch341` — they're platform-agnostic. Example:
|
|
; pio run -e native-macos
|
|
; mkdir -p ~/.meshtasticd && cp bin/config-dist.yaml ~/.meshtasticd/config.yaml
|
|
; # Edit ~/.meshtasticd/config.yaml: ConfigDirectory: ./config.d/
|
|
; mkdir ~/.meshtasticd/config.d && cp bin/config.d/lora-meshstick-1262.yaml ~/.meshtasticd/config.d/
|
|
; cd ~/.meshtasticd && /path/to/firmware/.pio/build/native-macos/meshtasticd
|
|
;
|
|
; The MAC address auto-derives from the CH341's USB serial + product string
|
|
; (PortduinoGlue.cpp ~497-518); on Linux a BlueZ HCI socket is the fallback
|
|
; when that path isn't taken, but BlueZ is `__linux__`-guarded so the
|
|
; serial-derivation path is mandatory on macOS. Override with
|
|
; `MACAddress: AA:BB:CC:DD:EE:FF` in config.yaml's `General:` section if
|
|
; the device's serial isn't 8 hex chars.
|
|
;
|
|
; Diagnosing CH341 issues on macOS:
|
|
; ioreg -p IOUSB -l -w 0 | grep -B2 -A30 0x5512
|
|
; Children should be `IOUSBHostInterface`. If a vendor driver class
|
|
; (e.g. `com.wch.CH34xVCPDriver` from a third-party WCH installer)
|
|
; claims interface 0, libusb will fail with LIBUSB_ERROR_BUSY.
|
|
; Workaround: `sudo kmutil unload -b <bundleID>`.
|
|
; LIBUSB_DEBUG=4 .pio/build/native-macos/meshtasticd
|
|
; Verbose libusb trace — useful when claim_interface fails.
|
|
; ---------------------------------------------------------------------------
|
|
[env:native-macos]
|
|
extends = native_base
|
|
; Apple's ld doesn't accept GNU ld's `-Wl,-Map,<file>` syntax (inherited from
|
|
; the top-level platformio.ini). Strip it; the linker map isn't useful for
|
|
; the macOS dev loop anyway, and Apple ld's equivalent (`-Wl,-map,<file>`)
|
|
; uses different argument shape.
|
|
build_unflags = -Wl,-Map,"${platformio.build_dir}"/output.map
|
|
; libi2c is Linux-only but build_flags_common carries -li2c (also duplicated in the Linux-only
|
|
; build_flags); macOS has no libi2c, so strip it here to let the link succeed.
|
|
-li2c
|
|
build_flags = ${portduino_base.build_flags_common}
|
|
-I variants/native/portduino
|
|
-I/opt/homebrew/include
|
|
-I/opt/homebrew/opt/argp-standalone/include
|
|
-I/opt/homebrew/opt/yaml-cpp/include
|
|
-L/opt/homebrew/lib
|
|
-L/opt/homebrew/opt/argp-standalone/lib
|
|
-L/opt/homebrew/opt/yaml-cpp/lib
|
|
-largp
|
|
-DPORTDUINO_DARWIN
|
|
; Headless build — variants/native/portduino/variant.h would otherwise
|
|
; default HAS_SCREEN to 1 and pull in screen-renderer source that uses
|
|
; VLA-with-initializer (a GNU/GCC extension Apple Clang rejects).
|
|
; MESHTASTIC_EXCLUDE_SCREEN gates the optional `screen->setHeading(...)`-
|
|
; style screen-driver hooks scattered through sensor sources.
|
|
-DHAS_SCREEN=0
|
|
-DMESHTASTIC_EXCLUDE_SCREEN=1
|
|
; openssl@3 is the keg-only Homebrew formula; --cflags is required so the
|
|
; compiler finds <openssl/*.h> in the Homebrew prefix (not just the linker).
|
|
!pkg-config --cflags --libs openssl --silence-errors || :
|
|
; PiWebServer (src/mesh/raspihttp/PiWebServer.cpp) auto-engages when ulfius
|
|
; headers are reachable via `#if __has_include(<ulfius.h>)`. The `|| :`
|
|
; tail keeps the build green when the user hasn't run `brew install ulfius`
|
|
; — they just don't get the HTTP API in that case.
|
|
!pkg-config --cflags --libs liborcania --silence-errors || :
|
|
!pkg-config --cflags --libs libyder --silence-errors || :
|
|
!pkg-config --cflags --libs libulfius --silence-errors || :
|
|
; src/input/Linux*.{cpp,h} drive evdev (`<linux/input.h>`) which doesn't exist
|
|
; on macOS. graphics/Panel_sdl.* and graphics/TFTDisplay.cpp pull LovyanGFX
|
|
; (which we lib_ignore on macOS for the <malloc.h> issue). Neither is needed
|
|
; for the headless build.
|
|
build_src_filter = ${native_base.build_src_filter}
|
|
-<input/LinuxInput.cpp>
|
|
-<input/LinuxInputImpl.cpp>
|
|
-<graphics/Panel_sdl.cpp>
|
|
-<graphics/TFTDisplay.cpp>
|
|
; LovyanGFX includes <malloc.h> (Linux-only) and is only needed by TFT
|
|
; variants — not relevant for the headless macOS build.
|
|
lib_ignore =
|
|
${portduino_base.lib_ignore}
|
|
LovyanGFX
|
|
|
|
; ---------------------------------------------------------------------------
|
|
; Same as [env:native-macos] but built with AddressSanitizer for catching
|
|
; use-after-free, leaks, and OOB access during local development. Headless
|
|
; (no SDL/X11/libinput) so it stays cheap to build. Mirrors the shape of
|
|
; [env:native-tft-debug] but without the TFT/X11 dependencies.
|
|
;
|
|
; pio run -e native-macos-debug
|
|
; .pio/build/native-macos-debug/meshtasticd -s
|
|
;
|
|
; ASan runtime tuning (set in the shell before launching):
|
|
; ASAN_OPTIONS=detect_leaks=1:halt_on_error=0:abort_on_error=1
|
|
; MallocStackLogging=1 # macOS: nicer stack traces in malloc reports
|
|
; ---------------------------------------------------------------------------
|
|
[env:native-macos-debug]
|
|
extends = native_base
|
|
build_type = debug
|
|
build_unflags = ${env:native-macos.build_unflags}
|
|
build_flags = ${env:native-macos.build_flags}
|
|
-O0
|
|
-g
|
|
-fsanitize=address
|
|
-fno-omit-frame-pointer
|
|
build_src_filter = ${env:native-macos.build_src_filter}
|
|
lib_ignore = ${env:native-macos.lib_ignore}
|
|
|
|
; ---------------------------------------------------------------------------
|
|
; WASM (Emscripten) — the portduino node compiled to WebAssembly, driving a real
|
|
; LoRa radio over WebUSB through a CH341 (src/platform/portduino/wasm/). The same
|
|
; setup()/loop() firmware that runs native, but the radio HAL talks WebUSB and
|
|
; the cooperative loop suspends via Asyncify. Software/CI build target; the radio
|
|
; path itself is hardware (CH341/WebUSB, Chromium). See the README in that dir.
|
|
;
|
|
; Toolchain comes from the meshtastic/platform-wasm PlatformIO platform (emcc/
|
|
; em++). Prereq: an Emscripten SDK on PATH — `source <emsdk>/emsdk_env.sh` (or
|
|
; export EMSDK=<path>) — so the platform builder can locate emcc.
|
|
;
|
|
; Build: pio run -e native-wasm -> .pio/build/native-wasm/meshnode.{mjs,wasm}
|
|
; ---------------------------------------------------------------------------
|
|
[env:native-wasm]
|
|
platform =
|
|
# renovate: datasource=git-refs depName=platform-wasm packageName=https://github.com/meshtastic/platform-wasm gitBranch=master
|
|
https://github.com/meshtastic/platform-wasm/archive/7834113c8ee05bedc6af9c9cce7f515a1560e2c6.zip
|
|
framework = arduino
|
|
board = wasm
|
|
board_level = extra
|
|
|
|
; wasm-ld doesn't accept GNU ld's `-Wl,-Map,<file>` (inherited from [env]); strip
|
|
; it. The linker map isn't meaningful for the emcc/Asyncify output anyway.
|
|
build_unflags = -Wl,-Map,"${platformio.build_dir}"/output.map
|
|
|
|
build_flags = ${arduino_base.build_flags}
|
|
-I variants/native/portduino
|
|
-I src/platform/portduino
|
|
; FIRST: our <argp.h> stub shadows the missing glibc header
|
|
-I src/platform/portduino/wasm/stubs
|
|
-I src/platform/portduino/wasm/include
|
|
-I src/platform/portduino/wasm
|
|
-D ARCH_PORTDUINO
|
|
; ARCH_PORTDUINO_WASM gates every wasm guard in the firmware (the glue/main
|
|
; entry points, the single-threaded cooperative paths, region/RNG, etc.). The
|
|
; platform's board.json also injects it, but define it here too so the build's
|
|
; correctness never hinges on an out-of-repo board file.
|
|
-D ARCH_PORTDUINO_WASM
|
|
-DRADIOLIB_EEPROM_UNSUPPORTED
|
|
-fexceptions
|
|
; firmware uses gettimeofday(); the native toolchain pulls <sys/time.h> in
|
|
; transitively but emscripten doesn't, so force it.
|
|
-include sys/time.h
|
|
; Headless browser node — no screen / GPS / I2C / sensors / host services.
|
|
; Same exclusions the standalone emcc build used; gate out hardware/host code
|
|
; the tab can't run (the EXCLUDE_* defines also keep LDF from pulling the libs).
|
|
-DHAS_SCREEN=0
|
|
-DMESHTASTIC_EXCLUDE_SCREEN=1
|
|
-DMESHTASTIC_EXCLUDE_GPS=1 -DNO_GPS=1 -DNO_EXT_GPIO=1
|
|
-DMESHTASTIC_EXCLUDE_I2C=1
|
|
-DMESHTASTIC_EXCLUDE_ACCELEROMETER=1 -DMESHTASTIC_EXCLUDE_MAGNETOMETER=1
|
|
-DMESHTASTIC_EXCLUDE_AUDIO=1 -DMESHTASTIC_EXCLUDE_INPUTBROKER=1
|
|
-DMESHTASTIC_EXCLUDE_MQTT=1 -DMESHTASTIC_EXCLUDE_TZ=1
|
|
-DMESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR=1 -DMESHTASTIC_EXCLUDE_DETECTIONSENSOR=1
|
|
-DMESHTASTIC_EXCLUDE_EXTERNALNOTIFICATION=1 -DMESHTASTIC_EXCLUDE_CANNEDMESSAGES=1
|
|
-DMESHTASTIC_EXCLUDE_STOREFORWARD=1 -DMESHTASTIC_EXCLUDE_SERIAL=1
|
|
-DMESHTASTIC_EXCLUDE_PAXCOUNTER=1 -DMESHTASTIC_EXCLUDE_WAYPOINT=1
|
|
|
|
; The firmware-specific emcc *link* settings (exported fns, runtime methods, the
|
|
; WebUSB Asyncify import seam, the ES-module factory name) can't ride in
|
|
; build_flags — PlatformIO only feeds those to the compile step — so they're
|
|
; appended to LINKFLAGS by this post script. (The generic Asyncify/MODULARIZE/
|
|
; memory flags and emsdk auto-location both come from the platform-wasm builder.)
|
|
extra_scripts =
|
|
${env.extra_scripts}
|
|
post:extra_scripts/wasm_link_flags.py
|
|
|
|
; chain+ so the EXCLUDE_* / HAS_SCREEN defines gate sensor/screen #includes out
|
|
; of LDF (otherwise it would try to build host/incompatible sensor libs).
|
|
lib_ldf_mode = chain+
|
|
lib_deps =
|
|
${env.lib_deps}
|
|
${radiolib_base.lib_deps}
|
|
# renovate: datasource=git-refs depName=meshtastic/Crypto packageName=https://github.com/meshtastic/Crypto gitBranch=master
|
|
https://github.com/meshtastic/Crypto/archive/1aa30eb536bd52a576fde6dfa393bf7349cf102d.zip
|
|
# renovate: datasource=custom.pio depName=Melopero RV3028 packageName=melopero/library/Melopero RV3028
|
|
melopero/Melopero RV3028@1.2.0
|
|
|
|
lib_ignore =
|
|
LovyanGFX
|
|
SD
|
|
|
|
; Curated source set — the proven standalone emcc build's file list expressed as
|
|
; a PlatformIO filter. Deny everything, then add exactly what the browser node
|
|
; links: the wasm cooperative-loop entry, the mesh stack (top-level + generated),
|
|
; concurrency, the portduino glue, and the non-esp32 modules (the EXCLUDE_*
|
|
; defines gate the unwanted module bodies). serialization/ stays excluded — the
|
|
; wasm stub replaces MeshPacketSerializer (jsoncpp is MQTT-only).
|
|
build_src_filter =
|
|
-<*>
|
|
+<main.cpp>
|
|
+<PowerFSM.cpp> +<Power.cpp> +<airtime.cpp> +<sleep.cpp>
|
|
+<RedirectablePrint.cpp> +<SerialConsole.cpp> +<Observer.cpp>
|
|
+<FSCommon.cpp> +<SafeFile.cpp> +<MessageStore.cpp> +<meshUtils.cpp>
|
|
+<memGet.cpp> +<GpioLogic.cpp> +<PowerMon.cpp> +<SPILock.cpp>
|
|
+<xmodem.cpp> +<DisplayFormatters.cpp>
|
|
+<detect/ScanI2C.cpp> +<detect/ScanI2CTwoWire.cpp> +<detect/ScanI2CConsumer.cpp>
|
|
+<power/PowerHAL.cpp>
|
|
+<gps/RTC.cpp>
|
|
+<buzz/buzz.cpp> +<buzz/BuzzerFeedbackThread.cpp>
|
|
+<mesh/*.cpp> +<mesh/*.c>
|
|
-<mesh/LR2021Interface.cpp> -<mesh/LR20x0Interface.cpp>
|
|
+<mesh/generated/>
|
|
+<concurrency/>
|
|
+<platform/portduino/PortduinoGlue.cpp> +<platform/portduino/SimRadio.cpp>
|
|
+<platform/portduino/wasm/>
|
|
+<modules/> -<modules/esp32/>
|