Skip to content
Open
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
93 changes: 93 additions & 0 deletions .github/workflows/appimage.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
name: Build AppImage

on:
# Build on version tags
push:
tags:
- 'v*'
# Manual trigger
workflow_dispatch:
inputs:
create_release:
description: 'Create a GitHub release'
type: boolean
default: false

jobs:
build-appimage:
name: Build AppImage (${{ matrix.arch }})
runs-on: ${{ matrix.runner }}
strategy:
matrix:
include:
- arch: x86_64
runner: ubuntu-22.04
- arch: aarch64
runner: ubuntu-22.04-arm

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y \
build-essential \
cmake \
libhidapi-dev \
libcurl4-openssl-dev \
wget \
file

- name: Build AppImage
run: ./appimage/build-appimage.sh

- name: Verify AppImage
run: |
ls -lh MDS_Bridge-*.AppImage
file MDS_Bridge-*.AppImage

- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: MDS_Bridge-${{ matrix.arch }}
path: MDS_Bridge-*.AppImage
retention-days: 30

# Create release when triggered by tag
release:
name: Create Release
needs: build-appimage
runs-on: ubuntu-latest
if: startsWith(github.ref, 'refs/tags/') || (github.event_name == 'workflow_dispatch' && github.event.inputs.create_release == 'true')

permissions:
contents: write

steps:
- name: Download all artifacts
uses: actions/download-artifact@v4
with:
path: artifacts

- name: Prepare release files
run: |
mkdir -p release
find artifacts -name '*.AppImage' -exec mv {} release/ \;
ls -la release/

- name: Generate checksums
working-directory: release
run: |
sha256sum *.AppImage > SHA256SUMS.txt
cat SHA256SUMS.txt

- name: Create Release
uses: softprops/action-gh-release@v1
with:
draft: ${{ github.event_name == 'workflow_dispatch' }}
generate_release_notes: true
files: |
release/*.AppImage
release/SHA256SUMS.txt
10 changes: 10 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -128,3 +128,13 @@ install(FILES
${CMAKE_CURRENT_BINARY_DIR}/mds_bridge-config-version.cmake
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/mds_bridge
)

# AppImage target (Linux only)
if(UNIX AND NOT APPLE)
add_custom_target(appimage
COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/appimage/build-appimage.sh
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
COMMENT "Building AppImage package..."
VERBATIM
)
endif()
102 changes: 102 additions & 0 deletions appimage/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
# AppImage Packaging for MDS Bridge

This directory contains files for building a self-contained AppImage for Linux.

## Quick Start

```bash
# On Ubuntu/Debian, install dependencies first:
sudo apt-get install libhidapi-dev libcurl4-openssl-dev cmake build-essential wget

# Build the AppImage
./appimage/build-appimage.sh
```

This creates `MDS_Bridge-<version>-<arch>.AppImage` in the project root.

## Usage

```bash
# Show help
./MDS_Bridge-2.0.0-x86_64.AppImage --help

# Run gateway (default)
./MDS_Bridge-2.0.0-x86_64.AppImage 2fe3 0007
./MDS_Bridge-2.0.0-x86_64.AppImage gateway 2fe3 0007

# Run monitor
./MDS_Bridge-2.0.0-x86_64.AppImage monitor 2fe3 0007

# Run demo version
./MDS_Bridge-2.0.0-x86_64.AppImage demo 2fe3 0007

# Dry-run mode
./MDS_Bridge-2.0.0-x86_64.AppImage gateway 2fe3 0007 --dry-run
```

## HID Device Permissions

On Linux, non-root users typically can't access HID devices. Create a udev rule:

```bash
# Create /etc/udev/rules.d/99-mds-bridge.rules
SUBSYSTEM=="hidraw", ATTRS{idVendor}=="2fe3", MODE="0666"

# Or for specific device:
SUBSYSTEM=="hidraw", ATTRS{idVendor}=="2fe3", ATTRS{idProduct}=="0007", MODE="0666"

# Reload rules
sudo udevadm control --reload-rules
sudo udevadm trigger
```

## Files

- `build-appimage.sh` - Main build script
- `mds-bridge.desktop` - Desktop entry file
- `mds-bridge.svg` - Application icon

## How It Works

1. Downloads `linuxdeploy` tool (if not cached)
2. Builds MDS Bridge with static libraries
3. Bundles executables and shared library dependencies
4. Creates self-contained AppImage

## Customizing

Edit `mds-bridge.desktop` to change:
- Application name and description
- Default command (currently `mds_gateway`)
- Categories

## Troubleshooting

**AppImage won't run:**
```bash
# Check if FUSE is available
fusermount --version

# If not, extract and run directly
./MDS_Bridge-*.AppImage --appimage-extract
./squashfs-root/usr/bin/mds_gateway 2fe3 0007
```

**Missing libraries:**
```bash
# Check what's bundled
./MDS_Bridge-*.AppImage --appimage-extract
ldd ./squashfs-root/usr/bin/mds_gateway
```

**Build fails with missing deps:**
```bash
# Ubuntu/Debian
sudo apt-get install libhidapi-dev libcurl4-openssl-dev

# Fedora
sudo dnf install hidapi-devel libcurl-devel

# Arch
sudo pacman -S hidapi curl
```
176 changes: 176 additions & 0 deletions appimage/build-appimage.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
#!/bin/bash
#
# Build AppImage for MDS Bridge
#
# Prerequisites (Ubuntu/Debian):
# sudo apt-get install libhidapi-dev libcurl4-openssl-dev cmake build-essential
#
# Usage:
# ./appimage/build-appimage.sh
#
# Output:
# MDS_Bridge-x86_64.AppImage (or MDS_Bridge-aarch64.AppImage on ARM)
#

set -e

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_DIR="$(dirname "$SCRIPT_DIR")"
BUILD_DIR="${PROJECT_DIR}/build-appimage"
APPDIR="${BUILD_DIR}/AppDir"
ARCH=$(uname -m)

# Version from CMakeLists.txt
VERSION=$(grep "project(mds_bridge VERSION" "${PROJECT_DIR}/CMakeLists.txt" | sed 's/.*VERSION \([0-9.]*\).*/\1/')

echo "=== MDS Bridge AppImage Builder ==="
echo "Project: ${PROJECT_DIR}"
echo "Build: ${BUILD_DIR}"
echo "Version: ${VERSION}"
echo "Arch: ${ARCH}"
echo ""

# Download linuxdeploy if not present
LINUXDEPLOY="${BUILD_DIR}/linuxdeploy-${ARCH}.AppImage"
if [ ! -f "$LINUXDEPLOY" ]; then
echo ">>> Downloading linuxdeploy..."
mkdir -p "$BUILD_DIR"
wget -q --show-progress -O "$LINUXDEPLOY" \
"https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-${ARCH}.AppImage"
chmod +x "$LINUXDEPLOY"
fi

# Clean previous AppDir
rm -rf "$APPDIR"
mkdir -p "$APPDIR"

# Build the project
echo ""
echo ">>> Building MDS Bridge..."
mkdir -p "${BUILD_DIR}/cmake"
cd "${BUILD_DIR}/cmake"
cmake "$PROJECT_DIR" \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=/usr \
-DBUILD_SHARED_LIBS=OFF \
-DBUILD_EXAMPLES=ON \
-DBUILD_TESTS=OFF \
-DENABLE_NODEJS=OFF

make -j$(nproc)

# Install to AppDir
echo ""
echo ">>> Installing to AppDir..."
DESTDIR="$APPDIR" make install

# Also install the example binaries to usr/bin (they're the main apps)
mkdir -p "${APPDIR}/usr/bin"
cp -v "${BUILD_DIR}/cmake/examples/mds_gateway" "${APPDIR}/usr/bin/"
cp -v "${BUILD_DIR}/cmake/examples/mds_gateway_demo" "${APPDIR}/usr/bin/"
cp -v "${BUILD_DIR}/cmake/examples/mds_monitor" "${APPDIR}/usr/bin/"

# Copy desktop file and icon
echo ""
echo ">>> Setting up desktop integration..."
mkdir -p "${APPDIR}/usr/share/applications"
mkdir -p "${APPDIR}/usr/share/icons/hicolor/scalable/apps"

cp "${SCRIPT_DIR}/mds-bridge.desktop" "${APPDIR}/usr/share/applications/"
cp "${SCRIPT_DIR}/mds-bridge.svg" "${APPDIR}/usr/share/icons/hicolor/scalable/apps/"

# Create wrapper script that provides CLI access to all tools
cat > "${APPDIR}/usr/bin/mds-bridge-wrapper" << 'WRAPPER_EOF'
#!/bin/bash
#
# MDS Bridge AppImage wrapper
# Provides access to all MDS Bridge tools
#

# Get the bin directory where this script and the binaries live
BINDIR="$(dirname "$(readlink -f "$0")")"
TOOL="${1:-demo}"

case "$TOOL" in
gateway|mds_gateway)
shift 2>/dev/null || true
exec "${BINDIR}/mds_gateway" "$@"
;;
demo|mds_gateway_demo)
shift 2>/dev/null || true
exec "${BINDIR}/mds_gateway_demo" "$@"
;;
monitor|mds_monitor)
shift 2>/dev/null || true
exec "${BINDIR}/mds_monitor" "$@"
;;
--help|-h)
echo "MDS Bridge - Memfault Diagnostic Service Tools"
echo ""
echo "Usage: $0 <command> [args...]"
echo ""
echo "Commands:"
echo " demo, mds_gateway_demo CES booth demo with auto-reconnect (default)"
echo " gateway, mds_gateway Upload diagnostic chunks"
echo " monitor, mds_monitor Display diagnostic stream data"
echo ""
echo "Examples:"
echo " $0 2fe3 0007"
echo " $0 demo 2fe3 0007"
echo " $0 gateway 2fe3 0007 --dry-run"
exit 0
;;
*)
# Assume it's arguments to mds_gateway_demo (the default tool)
exec "${BINDIR}/mds_gateway_demo" "$@"
;;
esac
WRAPPER_EOF
chmod +x "${APPDIR}/usr/bin/mds-bridge-wrapper"

# Update desktop file to use wrapper
sed -i 's|Exec=mds_gateway|Exec=mds-bridge-wrapper|' "${APPDIR}/usr/share/applications/mds-bridge.desktop"

# Create custom AppRun that uses our wrapper (outside AppDir for linuxdeploy)
cat > "${BUILD_DIR}/AppRun" << 'APPRUN_EOF'
#!/bin/bash
APPDIR="$(dirname "$(readlink -f "$0")")"
exec "${APPDIR}/usr/bin/mds-bridge-wrapper" "$@"
APPRUN_EOF
chmod +x "${BUILD_DIR}/AppRun"

# Create AppImage
echo ""
echo ">>> Creating AppImage..."
cd "$BUILD_DIR"

# Set output name
export OUTPUT="MDS_Bridge-${VERSION}-${ARCH}.AppImage"

# Deploy the actual ELF binaries (not the shell wrapper)
"$LINUXDEPLOY" \
--appdir "$APPDIR" \
--desktop-file "${APPDIR}/usr/share/applications/mds-bridge.desktop" \
--icon-file "${APPDIR}/usr/share/icons/hicolor/scalable/apps/mds-bridge.svg" \
--executable "${APPDIR}/usr/bin/mds_gateway" \
--executable "${APPDIR}/usr/bin/mds_gateway_demo" \
--executable "${APPDIR}/usr/bin/mds_monitor" \
--custom-apprun "${BUILD_DIR}/AppRun" \
--output appimage

# Move to project root
mv "$OUTPUT" "$PROJECT_DIR/"

echo ""
echo "=== Build Complete ==="
echo "AppImage: ${PROJECT_DIR}/${OUTPUT}"
echo ""
echo "Usage:"
echo " ./${OUTPUT} --help"
echo " ./${OUTPUT} 2fe3 0007 # runs demo (default)"
echo " ./${OUTPUT} gateway 2fe3 0007 # runs gateway"
echo " ./${OUTPUT} monitor 2fe3 0007 # runs monitor"
echo ""
echo "Or extract and run directly:"
echo " ./${OUTPUT} --appimage-extract"
echo " ./squashfs-root/usr/bin/mds_gateway_demo 2fe3 0007"
10 changes: 10 additions & 0 deletions appimage/mds-bridge.desktop
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
[Desktop Entry]
Type=Application
Name=MDS Bridge
GenericName=Memfault Diagnostic Bridge
Comment=Bridge diagnostic data from embedded devices to Memfault cloud
Exec=mds_gateway
Icon=mds-bridge
Categories=Development;Utility;
Terminal=true
Keywords=memfault;diagnostic;hid;embedded;iot;
Loading