Debian trixie-based build-compile-deploy workflow
This commit is contained in:
@@ -11,16 +11,62 @@ UI_DIR="$PROJECT_ROOT/pi/ui"
|
||||
echo "=== Smart Serow Build ==="
|
||||
echo "Project: $UI_DIR"
|
||||
|
||||
# Check for flutter-elinux
|
||||
if ! command -v flutter-elinux &> /dev/null; then
|
||||
echo "ERROR: flutter-elinux not found in PATH"
|
||||
echo "Install it or check your PATH"
|
||||
echo ""
|
||||
echo "Current PATH: $PATH"
|
||||
which flutter 2>/dev/null && echo "Found flutter at: $(which flutter)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Using: $(which flutter-elinux)"
|
||||
|
||||
# Cross-compilation toolchain for ARM64
|
||||
export CC=aarch64-linux-gnu-gcc
|
||||
export CXX=aarch64-linux-gnu-g++
|
||||
export AR=aarch64-linux-gnu-ar
|
||||
export LD=aarch64-linux-gnu-ld
|
||||
# CMake-specific vars
|
||||
export CMAKE_C_COMPILER=aarch64-linux-gnu-gcc
|
||||
export CMAKE_CXX_COMPILER=aarch64-linux-gnu-g++
|
||||
|
||||
echo "Cross-compiler: $CXX"
|
||||
|
||||
cd "$UI_DIR"
|
||||
|
||||
# Clean previous build (optional, comment out for faster incremental builds)
|
||||
# flutter-elinux clean
|
||||
# Initialize elinux project if not already configured
|
||||
if [ ! -d "elinux" ]; then
|
||||
echo "Initializing elinux project structure..."
|
||||
flutter-elinux create . --project-name smartserow_ui --org com.smartserow
|
||||
fi
|
||||
|
||||
# Clean CMake cache on --clean flag
|
||||
# (CMake caches compiler choice, so stale cache = wrong linker)
|
||||
if [ "${1:-}" = "--clean" ]; then
|
||||
echo "Cleaning CMake cache..."
|
||||
rm -rf build/elinux/arm64
|
||||
fi
|
||||
|
||||
echo "Fetching dependencies..."
|
||||
flutter-elinux pub get
|
||||
|
||||
echo "Building for ARM64 (elinux)..."
|
||||
flutter-elinux build elinux --target-arch=arm64 --release
|
||||
echo "Building for ARM64 (elinux) with DRM-GBM backend..."
|
||||
|
||||
# Use Pi sysroot if available (for proper cross-linking)
|
||||
SYSROOT_FLAG=""
|
||||
if [ -d "$PROJECT_ROOT/pi_sysroot" ]; then
|
||||
echo "Using Pi sysroot: $PROJECT_ROOT/pi_sysroot"
|
||||
SYSROOT_FLAG="--target-sysroot=$PROJECT_ROOT/pi_sysroot"
|
||||
fi
|
||||
|
||||
flutter-elinux build elinux \
|
||||
--target-arch=arm64 \
|
||||
--target-backend-type=gbm \
|
||||
--target-compiler-triple=aarch64-linux-gnu \
|
||||
$SYSROOT_FLAG \
|
||||
--release
|
||||
|
||||
BUILD_OUTPUT="$UI_DIR/build/elinux/arm64/release/bundle"
|
||||
|
||||
|
||||
@@ -14,14 +14,21 @@ if [ ! -f "$CONFIG_FILE" ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
HOST=$(jq -r '.host' "$CONFIG_FILE")
|
||||
REMOTE_PATH=$(jq -r '.remote_path' "$CONFIG_FILE")
|
||||
SERVICE_NAME=$(jq -r '.service_name' "$CONFIG_FILE")
|
||||
# Parse JSON with Python (more universal than jq)
|
||||
read_json() {
|
||||
python3 -c "import json; print(json.load(open('$CONFIG_FILE'))['$1'])"
|
||||
}
|
||||
|
||||
PI_USER=$(read_json user)
|
||||
PI_HOST=$(read_json host)
|
||||
REMOTE_PATH=$(read_json remote_path)
|
||||
SERVICE_NAME=$(read_json service_name)
|
||||
|
||||
SSH_TARGET="$PI_USER@$PI_HOST"
|
||||
BUILD_DIR="$PROJECT_ROOT/pi/ui/build/elinux/arm64/release/bundle"
|
||||
|
||||
echo "=== Smart Serow Deploy ==="
|
||||
echo "Target: $HOST:$REMOTE_PATH"
|
||||
echo "Target: $SSH_TARGET:$REMOTE_PATH"
|
||||
echo "Source: $BUILD_DIR"
|
||||
|
||||
if [ ! -d "$BUILD_DIR" ]; then
|
||||
@@ -34,20 +41,20 @@ echo ""
|
||||
echo "Syncing files..."
|
||||
rsync -avz --delete \
|
||||
"$BUILD_DIR/" \
|
||||
"$HOST:$REMOTE_PATH/bundle/"
|
||||
"$SSH_TARGET:$REMOTE_PATH/bundle/"
|
||||
|
||||
# Restart service if requested
|
||||
RESTART="${1:-}"
|
||||
if [ "$RESTART" = "--restart" ] || [ "$RESTART" = "-r" ]; then
|
||||
echo ""
|
||||
echo "Restarting service: $SERVICE_NAME"
|
||||
ssh "$HOST" "sudo systemctl restart $SERVICE_NAME"
|
||||
ssh "$SSH_TARGET" "sudo systemctl restart $SERVICE_NAME"
|
||||
sleep 2
|
||||
ssh "$HOST" "systemctl status $SERVICE_NAME --no-pager"
|
||||
ssh "$SSH_TARGET" "systemctl status $SERVICE_NAME --no-pager"
|
||||
else
|
||||
echo ""
|
||||
echo "Deploy complete. To restart service, run:"
|
||||
echo " ssh $HOST 'sudo systemctl restart $SERVICE_NAME'"
|
||||
echo " ssh $SSH_TARGET 'sudo systemctl restart $SERVICE_NAME'"
|
||||
echo ""
|
||||
echo "Or run this script with --restart flag"
|
||||
fi
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
{
|
||||
"host": "pi@smartserow.local",
|
||||
"user": "mikkeli",
|
||||
"host": "192.168.2.102",
|
||||
"remote_path": "/opt/smartserow",
|
||||
"service_name": "smartserow-ui"
|
||||
}
|
||||
|
||||
@@ -6,6 +6,11 @@ set -e
|
||||
|
||||
echo "=== Smart Serow Pi Setup ==="
|
||||
|
||||
# Use current user (whoever is running this script on the Pi)
|
||||
PI_USER="${USER:-$(whoami)}"
|
||||
PI_UID=$(id -u "$PI_USER")
|
||||
echo "Setting up for user: $PI_USER (uid: $PI_UID)"
|
||||
|
||||
# Check if running on Pi (arm architecture)
|
||||
ARCH=$(uname -m)
|
||||
if [[ "$ARCH" != "aarch64" && "$ARCH" != "armv7l" ]]; then
|
||||
@@ -15,11 +20,12 @@ fi
|
||||
|
||||
APP_DIR="/opt/smartserow"
|
||||
SERVICE_FILE="/etc/systemd/system/smartserow-ui.service"
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
|
||||
# Create app directory
|
||||
echo "Creating app directory: $APP_DIR"
|
||||
sudo mkdir -p "$APP_DIR/bundle"
|
||||
sudo chown -R pi:pi "$APP_DIR"
|
||||
sudo chown -R "$PI_USER:$PI_USER" "$APP_DIR"
|
||||
|
||||
# Install runtime dependencies for flutter-elinux
|
||||
echo "Installing runtime dependencies..."
|
||||
@@ -41,11 +47,15 @@ sudo apt-get install -y \
|
||||
libx11-6 \
|
||||
libxkbcommon-x11-0
|
||||
|
||||
# Copy systemd service
|
||||
# Generate systemd service with correct user
|
||||
echo "Installing systemd service..."
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
if [ -f "$SCRIPT_DIR/smartserow-ui.service" ]; then
|
||||
sudo cp "$SCRIPT_DIR/smartserow-ui.service" "$SERVICE_FILE"
|
||||
# Patch the template with actual user values
|
||||
sed -e "s/User=.*/User=$PI_USER/" \
|
||||
-e "s/Group=.*/Group=$PI_USER/" \
|
||||
-e "s|HOME=/home/.*|HOME=/home/$PI_USER|" \
|
||||
-e "s|XDG_RUNTIME_DIR=/run/user/.*|XDG_RUNTIME_DIR=/run/user/$PI_UID|" \
|
||||
"$SCRIPT_DIR/smartserow-ui.service" | sudo tee "$SERVICE_FILE" > /dev/null
|
||||
else
|
||||
echo "WARNING: Service file not found at $SCRIPT_DIR/smartserow-ui.service"
|
||||
echo "Copy it manually to $SERVICE_FILE"
|
||||
@@ -56,11 +66,11 @@ echo "Enabling service..."
|
||||
sudo systemctl daemon-reload
|
||||
sudo systemctl enable smartserow-ui
|
||||
|
||||
# Add pi user to required groups for DRM/KMS access
|
||||
echo "Setting up permissions..."
|
||||
sudo usermod -aG video pi
|
||||
sudo usermod -aG input pi
|
||||
sudo usermod -aG render pi 2>/dev/null || true
|
||||
# Add user to required groups for DRM/KMS access
|
||||
echo "Setting up permissions for $PI_USER..."
|
||||
sudo usermod -aG video "$PI_USER"
|
||||
sudo usermod -aG input "$PI_USER"
|
||||
sudo usermod -aG render "$PI_USER" 2>/dev/null || true
|
||||
|
||||
echo ""
|
||||
echo "=== Setup Complete ==="
|
||||
|
||||
@@ -5,12 +5,13 @@ Wants=multi-user.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=pi
|
||||
Group=pi
|
||||
User=mikkeli
|
||||
Group=mikkeli
|
||||
WorkingDirectory=/opt/smartserow/bundle
|
||||
|
||||
# DRM/KMS backend for direct framebuffer (no X11 needed)
|
||||
ExecStart=/opt/smartserow/bundle/smartserow_ui -b drm
|
||||
# GBM backend is compiled in. Just specify bundle path.
|
||||
# Scale factor 2.5 for 5.5" 1080p screen (high DPI)
|
||||
ExecStart=/opt/smartserow/bundle/smartserow_ui --bundle=/opt/smartserow/bundle --force-scale-factor=2.5
|
||||
|
||||
# Restart on crash
|
||||
Restart=always
|
||||
@@ -18,7 +19,8 @@ RestartSec=3
|
||||
|
||||
# Environment for DRM/KMS access
|
||||
Environment=XDG_RUNTIME_DIR=/run/user/1000
|
||||
Environment=HOME=/home/pi
|
||||
Environment=HOME=/home/mikkeli
|
||||
Environment=LD_LIBRARY_PATH=/opt/smartserow/bundle/lib
|
||||
|
||||
# Give time for GPU to initialize on boot
|
||||
ExecStartPre=/bin/sleep 2
|
||||
|
||||
Reference in New Issue
Block a user