Add native macOS simulator app packaging
This commit is contained in:
@@ -99,12 +99,10 @@ logs. HTTP 200 or a package simply appearing in `/api/apps` is insufficient.
|
|||||||
## Host simulator (buildsim) + web viewer
|
## Host simulator (buildsim) + web viewer
|
||||||
|
|
||||||
The POSIX simulator runs the real firmware (LVGL, services, web server) on
|
The POSIX simulator runs the real firmware (LVGL, services, web server) on
|
||||||
macOS/Linux with an SDL backend. macOS has no visible window (upstream
|
macOS/Linux with an SDL backend. On current firmware, `Main.cpp` runs SDL's
|
||||||
`.github/workflows/build-simulator.yml`: "macOS simulator currently fails due
|
event loop on the process main thread while FreeRTOS runs on a separate thread.
|
||||||
to main thread requirement for rendering" — AppKit menu init must happen on
|
This is required by AppKit and supports a native macOS window as well as the
|
||||||
the process main thread, but FreeRTOS-POSIX parks main in `sigwait` and runs
|
web viewer. `SDL_VIDEODRIVER=dummy` remains useful for headless automation.
|
||||||
everything on pthreads). The supported loop is **headless + web viewer**:
|
|
||||||
screenshots render server-side regardless of any window.
|
|
||||||
|
|
||||||
Code locations:
|
Code locations:
|
||||||
|
|
||||||
@@ -133,11 +131,14 @@ env -u ESP_IDF_VERSION -u IDF_PATH cmake --build buildsim --target TactilityKern
|
|||||||
app-module crypt-module gps-module http-module lvgl-module lvgl-window-manager-module service-module
|
app-module crypt-module gps-module http-module lvgl-module lvgl-window-manager-module service-module
|
||||||
env -u ESP_IDF_VERSION -u IDF_PATH python3 Buildscripts/release-sdk-posix.py /tmp/sim-sdk
|
env -u ESP_IDF_VERSION -u IDF_PATH python3 Buildscripts/release-sdk-posix.py /tmp/sim-sdk
|
||||||
|
|
||||||
# release + headless run (MUST run from the firmware root: release-simulator.sh
|
# release (MUST run from the firmware root: release-simulator.sh uses relative
|
||||||
# uses relative version.txt / Data paths)
|
# version.txt / Data paths)
|
||||||
sh Buildscripts/release-simulator.sh buildsim /tmp/simrun
|
sh Buildscripts/release-simulator.sh buildsim /tmp/simrun
|
||||||
(cd /tmp/simrun && SIM_DISPLAY_W=480 SIM_DISPLAY_H=320 SDL_VIDEODRIVER=dummy \
|
# Native macOS window + web API. Run this from the release directory because
|
||||||
nohup ./Tactility > /tmp/sim_web.log 2>&1 &)
|
# data/ and system/ are relative to the process working directory.
|
||||||
|
(cd /tmp/simrun && SIM_DISPLAY_W=480 SIM_DISPLAY_H=320 \
|
||||||
|
nohup ./Tactility > /tmp/sim_gui.log 2>&1 &)
|
||||||
|
# For CI/headless operation, set SDL_VIDEODRIVER=dummy instead.
|
||||||
curl -s --max-time 5 http://127.0.0.1/api/sysinfo | head -c 120
|
curl -s --max-time 5 http://127.0.0.1/api/sysinfo | head -c 120
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -146,7 +147,8 @@ matching on-device screenshots). ES3C35P panel is 320x480 portrait in DTS but
|
|||||||
presents 480x320 landscape; ES3C28P is 320x240. The chosen geometry is logged
|
presents 480x320 landscape; ES3C28P is 320x240. The chosen geometry is logged
|
||||||
as `Simulator Sim display WxH`. `SDL_VIDEODRIVER=dummy` is expected to log one
|
as `Simulator Sim display WxH`. `SDL_VIDEODRIVER=dummy` is expected to log one
|
||||||
`SdlDisplay Failed to create SDL window: Couldn't find matching render
|
`SdlDisplay Failed to create SDL window: Couldn't find matching render
|
||||||
driver` line — LVGL still renders and screenshots work.
|
driver` line — LVGL still renders and screenshots work. A native macOS launch
|
||||||
|
must not emit that line.
|
||||||
|
|
||||||
### Web viewer, touch, screenshots
|
### Web viewer, touch, screenshots
|
||||||
|
|
||||||
@@ -187,6 +189,14 @@ URLs would 404 at the edge (no `/api` mount there).
|
|||||||
- **Rebuild ≠ redeploy.** `cmake --build buildsim` updates `buildsim/` only.
|
- **Rebuild ≠ redeploy.** `cmake --build buildsim` updates `buildsim/` only.
|
||||||
Re-run `release-simulator.sh`, restart the process, then retest. A stale
|
Re-run `release-simulator.sh`, restart the process, then retest. A stale
|
||||||
`/tmp/simrun/Tactility` serves old handlers with new logs nowhere to be found.
|
`/tmp/simrun/Tactility` serves old handlers with new logs nowhere to be found.
|
||||||
|
- **One simulator owns port 80.** Do not launch a second instance while another
|
||||||
|
simulator is listening: it will initialize LVGL but fail `bind/listen`, so its
|
||||||
|
app API and viewer target the other process. Identify the listener with
|
||||||
|
`lsof -nP -iTCP:80 -sTCP:LISTEN`, stop only the intended simulator, then
|
||||||
|
release/restart it before installing or running POSIX apps.
|
||||||
|
- **Input is cross-thread on macOS.** SDL event pumping occurs on the real main
|
||||||
|
thread; LVGL and web touch injection run elsewhere. Keep all shared pointer,
|
||||||
|
key-queue, and touch-override state under `sdl_input.cpp`'s mutex.
|
||||||
- **C array `sizeof` decay.** A helper like
|
- **C array `sizeof` decay.** A helper like
|
||||||
`f(HttpServerRequest*, char uri[256])` sees `sizeof(uri) == 8`, truncating
|
`f(HttpServerRequest*, char uri[256])` sees `sizeof(uri) == 8`, truncating
|
||||||
`get_uri` output to 7 chars (`/api/sy`, `/sim/ap` 404s). Pass the size
|
`get_uri` output to 7 chars (`/api/sy`, `/sim/ap` 404s). Pass the size
|
||||||
|
|||||||
@@ -3,6 +3,8 @@
|
|||||||
|
|
||||||
build*/
|
build*/
|
||||||
!.github/actions/build*/
|
!.github/actions/build*/
|
||||||
|
!Buildscripts/
|
||||||
|
!Buildscripts/release-simulator-macos-app.sh
|
||||||
cmake*/
|
cmake*/
|
||||||
CMakeCache.txt
|
CMakeCache.txt
|
||||||
*.cbp
|
*.cbp
|
||||||
|
|||||||
@@ -0,0 +1,61 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# Usage: release-simulator-macos-app.sh [builddir] [Tactility.app]
|
||||||
|
# Example: release-simulator-macos-app.sh buildsim release/Tactility.app
|
||||||
|
|
||||||
|
set -eu
|
||||||
|
|
||||||
|
build_path=$1
|
||||||
|
bundle_path=$2
|
||||||
|
|
||||||
|
if [ -e "$bundle_path" ]; then
|
||||||
|
echo "Refusing to overwrite existing bundle: $bundle_path" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
contents_path="$bundle_path/Contents"
|
||||||
|
resources_path="$contents_path/Resources"
|
||||||
|
macos_path="$contents_path/MacOS"
|
||||||
|
|
||||||
|
mkdir -p "$resources_path" "$macos_path"
|
||||||
|
|
||||||
|
cp "$build_path/Tactility/Tactility" "$resources_path/Tactility-bin"
|
||||||
|
cp version.txt "$resources_path/"
|
||||||
|
cp -R Data/data "$resources_path/"
|
||||||
|
cp -R Data/system "$resources_path/"
|
||||||
|
|
||||||
|
cat > "$contents_path/Info.plist" <<'EOF'
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>CFBundleDevelopmentRegion</key>
|
||||||
|
<string>en</string>
|
||||||
|
<key>CFBundleExecutable</key>
|
||||||
|
<string>Tactility</string>
|
||||||
|
<key>CFBundleIdentifier</key>
|
||||||
|
<string>org.tactilityproject.simulator</string>
|
||||||
|
<key>CFBundleInfoDictionaryVersion</key>
|
||||||
|
<string>6.0</string>
|
||||||
|
<key>CFBundleName</key>
|
||||||
|
<string>Tactility</string>
|
||||||
|
<key>CFBundlePackageType</key>
|
||||||
|
<string>APPL</string>
|
||||||
|
<key>CFBundleShortVersionString</key>
|
||||||
|
<string>0.8.0-dev</string>
|
||||||
|
<key>CFBundleVersion</key>
|
||||||
|
<string>1</string>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
|
EOF
|
||||||
|
|
||||||
|
cat > "$macos_path/Tactility" <<'EOF'
|
||||||
|
#!/bin/sh
|
||||||
|
set -eu
|
||||||
|
|
||||||
|
resources_path="$(CDPATH= cd -- "$(dirname -- "$0")/../Resources" && pwd)"
|
||||||
|
cd "$resources_path"
|
||||||
|
exec "$resources_path/Tactility-bin" "$@"
|
||||||
|
EOF
|
||||||
|
|
||||||
|
chmod +x "$macos_path/Tactility" "$resources_path/Tactility-bin"
|
||||||
Reference in New Issue
Block a user