Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ on:
- main
tags:
- '*'
- '!mspmaptool*' # map tool releases are published by hand, not firmware
pull_request:
branches:
- main
Expand All @@ -20,7 +21,7 @@ jobs:
- name: Build
run: |
sudo apt-get update
DEBIAN_FRONTEND=noninteractive TZ=Etc/UTC sudo apt-get -y install git make wget gcc libevent-dev libcsfml-dev file g++ cpio unzip rsync bc bzip2 libcairo-dev
DEBIAN_FRONTEND=noninteractive TZ=Etc/UTC sudo apt-get -y install git make wget gcc libevent-dev libcsfml-dev file g++ cpio unzip rsync bc bzip2 libcairo-dev libsqlite3-dev
./build.sh goke
./build.sh hisi
./build.sh star6b0
Expand Down
46 changes: 46 additions & 0 deletions .github/workflows/preflight-pack.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
name: preflight-pack

# Build the standalone preflight map app (gs/mapserver.py + web/) into a single
# self-contained binary for Linux, macOS and Windows. Run manually or by pushing
# a `preflight-v*` tag; grab the binaries from the run's Artifacts.

on:
workflow_dispatch:
push:
tags:
- "preflight-v*"

jobs:
build:
strategy:
fail-fast: false
matrix:
include:
- os: ubuntu-latest
artifact: mspmaptool_linux
- os: macos-latest
artifact: mspmaptool_macos
- os: windows-latest
artifact: mspmaptool_windows
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4

- uses: actions/setup-python@v5
with:
python-version: "3.12"

# certifi: bundled root CAs so the Windows binary verifies Let's Encrypt
# tile sources (OpenTopoMap) regardless of the client's certificate store.
- name: Install PyInstaller
run: python -m pip install --upgrade pyinstaller certifi

- name: Build
run: python -m PyInstaller --clean --noconfirm --distpath gs/dist --workpath gs/build gs/pack/mapserver.spec

- name: Upload binary
uses: actions/upload-artifact@v4
with:
name: ${{ matrix.artifact }}
path: gs/dist/mspmaptool_*
if-no-files-found: error
10 changes: 10 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,18 @@ msposd_star6b0
msposd_star6e
msposd_star6c
msposd
msposd_x
msposd_rockchip
version.h
serial_monitor.c
*.ini
# PyInstaller output (gs/pack standalone build)
/build/
/dist/
gs/build/
gs/dist/
*.spec.bak


.claude/
AGENTS.md
6 changes: 4 additions & 2 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
"program": "${workspaceFolder}/msposd",
"args": [
"--master",
"127.0.0.1:14550",
"127.0.0.1:14560",
"--baudrate",
"115200",
"--osd",
Expand Down Expand Up @@ -54,7 +54,9 @@
"args": [
"-m",
"/tmp/inav_pty",
"-d",
"-d",
"--out",
"127.0.0.1:14560",
"-r",
"1030",
"--ahi",
Expand Down
27 changes: 23 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ CFLAGS ?=
CFLAGS += -Wno-address-of-packed-member -DVERSION_STRING="\"$(VERSION_STRING)\""

SRCS := compat.c msposd.c bmp/bitmap.c bmp/region.c bmp/lib/schrift.c bmp/text.c osd/net/network.c osd/msp/msp.c osd/msp/msp_displayport.c libpng/lodepng.c osd/util/interface.c osd/util/settings.c osd/util/ini_parser.c osd/msp/vtxmenu.c osd/util/subtitle.c osd/util/simple_ini.c
GS_SRCS := osd/util/terrain_elevation.c osd/util/terrain_agl.c
OUTPUT ?= $(PWD)
BUILD = $(CC) $(SRCS) -I $(SDK)/include -I$(TOOLCHAIN)/usr/include -I$(PWD) -L$(DRV) $(CFLAGS) $(LIB) -levent_core -Os -s $(CFLAGS) -o $(OUTPUT)

Expand Down Expand Up @@ -60,13 +61,31 @@ star6e: version.h
native: version.h
$(eval SDK = ./sdk/gk7205v300)
$(eval CFLAGS += -D_x86)
$(eval LIB = -lcsfml-graphics -lcsfml-window -lcsfml-system `pkg-config --libs cairo x11 xext` -lXext -lm)
$(eval BUILD = $(CC) $(SRCS) -I $(SDK)/include -L $(DRV) $(CFLAGS) $(LIB) -levent_core -O0 -g -o $(OUTPUT))
$(eval LIB = -lcsfml-graphics -lcsfml-window -lcsfml-system `pkg-config --libs cairo x11 xext` -lXext -lm -lsqlite3)
$(eval BUILD = $(CC) $(SRCS) $(GS_SRCS) -I $(SDK)/include -L $(DRV) $(CFLAGS) $(LIB) -levent_core -O0 -g -o $(OUTPUT))
$(BUILD)

rockchip: version.h
$(eval SDK = ./sdk/gk7205v300)
$(eval CFLAGS += -D__ROCKCHIP__)
$(eval LIB = `pkg-config --libs cairo x11 xext` -lXext -lm -lrt)
$(eval BUILD = $(CC) $(SRCS) -I $(SDK)/include -L $(DRV) $(CFLAGS) $(LIB) -levent_core -O0 -g -o $(OUTPUT))
$(eval LIB = `pkg-config --libs cairo x11 xext` -lXext -lm -lrt -lsqlite3)
$(eval BUILD = $(CC) $(SRCS) $(GS_SRCS) -I $(SDK)/include -L $(DRV) $(CFLAGS) $(LIB) -levent_core -O0 -g -o $(OUTPUT))
$(BUILD)

test-terrain-elevation:
$(CC) tests/terrain_elevation_test.c osd/util/terrain_elevation.c -I$(PWD) \
-DTERRAIN_ELEVATION_DB_PATH='"/tmp/msposd-terrain-elevation-test.db"' \
-Wall -Wextra -Werror -O1 -g -fsanitize=address,undefined -fno-omit-frame-pointer -no-pie \
-o /tmp/msposd-terrain-elevation-test -lsqlite3 -lm
ASAN_OPTIONS=detect_leaks=0:abort_on_error=1:handle_segv=0 \
/tmp/msposd-terrain-elevation-test

test-terrain-agl:
$(CC) tests/terrain_agl_test.c osd/util/terrain_agl.c osd/util/terrain_elevation.c \
-I$(PWD) -DTERRAIN_ELEVATION_DB_PATH='"/tmp/msposd-terrain-agl-test.db"' \
-Wall -Wextra -Werror -O1 -g -fsanitize=address,undefined -fno-omit-frame-pointer -no-pie \
-o /tmp/msposd-terrain-agl-test -lsqlite3 -lm
ASAN_OPTIONS=detect_leaks=0:abort_on_error=1:handle_segv=0 \
/tmp/msposd-terrain-agl-test

test-terrain: test-terrain-elevation test-terrain-agl
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,8 @@ This keywords can be added using the PilotName/CraftName fields(INAV/BF/Ardu), o
- ```!TMP!``` Camera board temp
- ```!TMW!``` WiFi module temperature (only 8812EU2/8733BU chipsets supported)
- ```!RC!``` Sticks Position widget (Ground Side only)
- ```!AGL!``` GPS-calibrated height above terrain in metres (Ground Side only);
displays ```----m``` while unavailable

### Usage Example:

Expand Down
2 changes: 1 addition & 1 deletion build_rockchip.sh
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ if [ ! -f $output/tmp/prepare_chroot.done ]; then
echo 'deb [signed-by=/usr/share/keyrings/radxa-archive-keyring.gpg] https://radxa-repo.github.io/bullseye rockchip-bullseye main' > /etc/apt/sources.list.d/80-rockchip.list

apt-get update
apt-get install -y git gcc make pkg-config libspdlog-dev libevent-dev libcairo-dev
apt-get install -y git gcc make pkg-config libspdlog-dev libevent-dev libcairo-dev libsqlite3-dev
apt clean
touch /tmp/prepare_chroot.done
EOL
Expand Down
86 changes: 86 additions & 0 deletions documentation/build-preflight-release.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
# Build a release package — preflight map

How to package the preflight map (`map.sh preflight` / `gs/mapserver.py`) into a **single
self-contained binary per OS** that end users run without installing Python. It starts a
local server and opens the map in the user's **default browser** (no Python/WebKit to
install). Writable `config.ini`, `state.ini` and `maps/` are created next to the
executable on first run. Map tiles, shared landmarks and shared elevation data live
inside `maps/`.

## Prerequisites
- Python **3.9+** and `pip` on the build machine (`pyinstaller` is installed automatically).
The Windows build needs **3.12+** like CI, and bundles `certifi` so HTTPS tile sources
verify on every client PC regardless of its certificate store.
- Build **on each target OS** — a Windows `.exe` needs Windows, a macOS build needs a Mac.

PyInstaller bundles a bootloader for the host OS; it does not cross-compile. Running
`build.sh` on Linux or WSL produces a Linux ELF executable. Copying or renaming that
file to `.exe` will produce Windows' “not a valid app” error. Use native Windows with
`build.bat`, or use the Windows artifact from CI.

## Build (current OS)
```bash
./gs/pack/build.sh # Linux / macOS
gs\pack\build.bat # Windows
```
Output: **`gs/dist/mspmaptool_linux`** (`mspmaptool_macos` on macOS, `mspmaptool_windows.exe` on Windows) — one file.

On Linux, verify the artifact type before publishing it:

```bash
file gs/dist/mspmaptool_linux
# ... ELF 64-bit ...
```

## Build all three OSes at once (CI)
The `.github/workflows/preflight-pack.yml` matrix builds Linux/macOS/Windows. Trigger it:
- **Manually:** GitHub → Actions → *preflight-pack* → *Run workflow*, or
- **By tag:** push a tag matching `preflight-v*`, e.g.
```bash
git tag preflight-v1.0 && git push origin preflight-v1.0
```
Download the three binaries from the run's **Artifacts**.

## Run / verify
```bash
./gs/dist/mspmaptool_linux # starts server, opens the browser
./gs/dist/mspmaptool_linux --port 9000 # custom port
./gs/dist/mspmaptool_linux --no-browser # server only
```
Ctrl+C (or closing the console) stops it.

## Install elsewhere on Linux

No installation step is required. The binary can be copied to another writable folder
on the same Linux system:

```bash
mkdir -p ~/Apps/mspmaptool
cp gs/dist/mspmaptool_linux ~/Apps/mspmaptool/
chmod +x ~/Apps/mspmaptool/mspmaptool_linux
~/Apps/mspmaptool/mspmaptool_linux
```

Its new containing directory becomes the writable application directory. Copy the old
`config.ini`, `state.ini` and `maps/` into that directory to preserve settings, map
packs, landmarks and elevation data. Otherwise it starts with defaults and creates data
as needed. Only one server can own the default HTTP port; stop the old copy or start the
new one with `--port 9000`.

## Ship it
Give users the single binary. On first run it creates its data folder alongside itself;
each area download creates a new `maps/<pack>.mbtiles` without modifying older packs.
Select the desired entry under **Downloaded maps**, then use **Export selected map…** to
create a zip containing that pack plus `landmarks.db` and `elevation.db` for the
OSD/flight station.

## Notes
- **Unsigned binaries** trip macOS Gatekeeper / Windows SmartScreen — code-sign (and
notarize on macOS) for public release; fine as-is for internal use.
- Some Windows AV engines false-positive on PyInstaller one-file builds.
- For distribution across different Linux releases, build on an appropriately old
compatible Linux baseline; copying within the build machine itself is safe.
- The dev launcher opens preflight in the system browser by default. Use
`./map.sh preflight --GTK` for the compatibility WebKit `mapwin` window.

See [`../gs/pack/README.md`](../gs/pack/README.md) for how the packaging works internally.
Loading
Loading