#!/usr/bin/env bash # ============================================================ # 打包 C++ 项目为 .deb(自包含:可执行文件 + 运行库,装到 /opt/fpv-relay) # 用法: # ./packaging/build-deb.sh # 仅命令行版 # ./packaging/build-deb.sh --with-gui # 含 GUI(需 QT_PREFIX) # 产物: dist/fpv-relay_<版本>_amd64.deb # ============================================================ set -e REPO="$(cd "$(dirname "$0")/.." && pwd)" WITH_GUI=0 [ "$1" = "--with-gui" ] && WITH_GUI=1 VERSION="$(cd "$REPO" && git describe --tags --always 2>/dev/null | tr -d 'v' || date +%Y%m%d)" [ -z "$VERSION" ] && VERSION="$(date +%Y%m%d)" DEB_VER="${VERSION}-1" PKG="fpv-relay" ARCH="amd64" DIST="${REPO}/dist" ROOT="$(mktemp -d)" APP="${ROOT}/opt/fpv-relay" echo "==> 构建(CLI)" cd "${REPO}" cmake --preset cli >/dev/null cmake --build --preset cli -j"$(nproc)" >/dev/null if [ "$WITH_GUI" = "1" ]; then : "${QT_PREFIX:?--with-gui 需要设置 QT_PREFIX}" echo "==> 构建(GUI)" cmake --preset gui >/dev/null cmake --build --preset gui -j"$(nproc)" >/dev/null fi echo "==> 准备 ${APP}" mkdir -p "${APP}/bin" "${APP}/lib" "${APP}/tools" "${ROOT}/DEBIAN" "${ROOT}/usr/bin" cp "${REPO}/build/fpv-relay" "${APP}/bin/" cp "${REPO}/tools/play-udp.sh" "${APP}/tools/" 2>/dev/null || true cp "${REPO}/config.example.yaml" "${APP}/" cp "${REPO}/README.md" "${APP}/" 2>/dev/null || true bundle_libs() { ldd "$1" 2>/dev/null | awk '{print $3}' | grep '^/' | while read -r lib; do base="$(basename "$lib")" case "$base" in libc.so*|libm.so*|libpthread*|librt*|libdl*|libgcc_s*|libstdc++*|ld-linux*|libnsl*|libresolv*) continue ;; libgst*|libglib-2.0*|libgobject-2.0*|libgmodule-2.0*|libgio-2.0*|libgthread-2.0*|liborc-0.4*|libav*|libswscale*|libswresample*|libpostproc*|libx264*|libx265*|libvpx*) continue ;; esac if [ ! -e "${APP}/lib/${base}" ]; then cp -L "$lib" "${APP}/lib/${base}" bundle_libs "$lib" fi done } echo "==> 收集运行库" bundle_libs "${APP}/bin/fpv-relay" if [ "$WITH_GUI" = "1" ]; then echo "==> 打包 GUI 与 Qt 运行环境" cp "${REPO}/build-gui/fpv-relay-gui" "${APP}/bin/" bundle_libs "${APP}/bin/fpv-relay-gui" cp -L "${QT_PREFIX}/lib/"libQt6*.so* "${APP}/lib/" 2>/dev/null || true for l in "${APP}"/lib/libQt6*.so*; do [ -e "$l" ] && bundle_libs "$l" done cp -rL "${REPO}/build-gui/FpvRelay" "${APP}/bin/" 2>/dev/null || true mkdir -p "${APP}/plugins/platforms" "${APP}/plugins/xcbglintegrations" "${APP}/qml" for p in libqxcb.so libqminimal.so libqoffscreen.so; do [ -f "${QT_PREFIX}/plugins/platforms/${p}" ] && cp -L "${QT_PREFIX}/plugins/platforms/${p}" "${APP}/plugins/platforms/" done cp -L "${QT_PREFIX}/plugins/xcbglintegrations/"*.so "${APP}/plugins/xcbglintegrations/" 2>/dev/null || true for m in QtQml QtQuick Qt Qt5Compat; do [ -d "${QT_PREFIX}/qml/${m}" ] && cp -rL "${QT_PREFIX}/qml/${m}" "${APP}/qml/" done find "${APP}/qml" "${APP}/plugins" -name "*.so" 2>/dev/null | while read -r so; do bundle_libs "$so" done fi cat > "${APP}/run.sh" <<'EOF' #!/usr/bin/env bash DIR="$(cd "$(dirname "$0")" && pwd)" export LD_LIBRARY_PATH="$DIR/lib:${LD_LIBRARY_PATH}" exec "$DIR/bin/fpv-relay" "$@" EOF chmod 755 "${APP}/run.sh" if [ "$WITH_GUI" = "1" ]; then cat > "${APP}/run-gui.sh" <<'EOF' #!/usr/bin/env bash DIR="$(cd "$(dirname "$0")" && pwd)" export LD_LIBRARY_PATH="$DIR/lib:${LD_LIBRARY_PATH}" export QT_PLUGIN_PATH="$DIR/plugins" export QT_QPA_PLATFORM_PLUGIN_PATH="$DIR/plugins/platforms" export QML2_IMPORT_PATH="$DIR/qml" export QML_IMPORT_PATH="$DIR/qml" exec "$DIR/bin/fpv-relay-gui" "$@" EOF chmod 755 "${APP}/run-gui.sh" fi # /usr/bin 下的启动器 cat > "${ROOT}/usr/bin/fpv-relay" <<'EOF' #!/bin/sh exec /opt/fpv-relay/run.sh "$@" EOF chmod 755 "${ROOT}/usr/bin/fpv-relay" if [ "$WITH_GUI" = "1" ]; then cat > "${ROOT}/usr/bin/fpv-relay-gui" <<'EOF' #!/bin/sh exec /opt/fpv-relay/run-gui.sh "$@" EOF chmod 755 "${ROOT}/usr/bin/fpv-relay-gui" fi cat > "${ROOT}/DEBIAN/control" < Section: net Priority: optional Depends: libc6, iw, ffmpeg Description: Multi-input FPV video relay (capture + low-latency forward) RTL8812AU capture (wfb-ng), low-latency UDP forwarding, DVR recording, RTSP output, mavlink uplink/downlink. Self-contained build with bundled runtime libraries under /opt/fpv-relay. EOF mkdir -p "${DIST}" dpkg-deb --build --root-owner-group "${ROOT}" "${DIST}/${PKG}_${DEB_VER}_${ARCH}.deb" rm -rf "${ROOT}" echo echo "完成: ${DIST}/${PKG}_${DEB_VER}_${ARCH}.deb" du -sh "${DIST}/${PKG}_${DEB_VER}_${ARCH}.deb"