This commit is contained in:
2026-09-13 13:30:21 +08:00
commit a6bbd520cf
2744 changed files with 1598795 additions and 0 deletions
+119
View File
@@ -0,0 +1,119 @@
#!/usr/bin/env bash
# ============================================================
# 打包 C++ 项目为 tar.gz(自包含:可执行文件 + 运行库)
# 用法:
# ./packaging/build-release.sh # 仅命令行版
# ./packaging/build-release.sh --with-gui # 含 GUI(需 QT_PREFIX)
# 产物: dist/fpv-relay-<版本>-linux-x86_64.tar.gz
# ============================================================
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 || date +%Y%m%d)"
NAME="fpv-relay-${VERSION}-linux-x86_64"
DIST="${REPO}/dist"
STAGE="${DIST}/${NAME}"
LIBDIR="${STAGE}/lib"
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 指向 Qt 安装目录}"
echo "==> 构建(GUI)"
cmake --preset gui >/dev/null
cmake --build --preset gui -j"$(nproc)" >/dev/null
fi
echo "==> 准备目录 ${STAGE}"
rm -rf "${STAGE}"
mkdir -p "${STAGE}/bin" "${LIBDIR}" "${STAGE}/tools"
cp "${REPO}/build/fpv-relay" "${STAGE}/bin/"
cp "${REPO}/tools/play-udp.sh" "${STAGE}/tools/" 2>/dev/null || true
cp "${REPO}/config.example.yaml" "${STAGE}/"
cp "${REPO}/README.md" "${STAGE}/" 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 "${LIBDIR}/${base}" ]; then
cp -L "$lib" "${LIBDIR}/${base}"
bundle_libs "$lib"
fi
done
}
echo "==> 打包命令行版运行库"
bundle_libs "${STAGE}/bin/fpv-relay"
if [ "$WITH_GUI" = "1" ]; then
echo "==> 打包 GUI 与 Qt 运行环境"
cp "${REPO}/build-gui/fpv-relay-gui" "${STAGE}/bin/"
bundle_libs "${STAGE}/bin/fpv-relay-gui"
# 复制全部 Qt6 运行库(含 QML 插件会用到的),并补齐它们的依赖
cp -L "${QT_PREFIX}/lib/"libQt6*.so* "${LIBDIR}/" 2>/dev/null || true
for l in "${LIBDIR}"/libQt6*.so*; do
[ -e "$l" ] && bundle_libs "$l"
done
# QML 模块的 qmldir(依赖“程序目录”作为导入路径)
cp -rL "${REPO}/build-gui/FpvRelay" "${STAGE}/bin/" 2>/dev/null || true
# Qt 插件(平台/GL/图像格式)
mkdir -p "${STAGE}/plugins/platforms" "${STAGE}/plugins/xcbglintegrations"
for p in libqxcb.so libqminimal.so libqoffscreen.so; do
[ -f "${QT_PREFIX}/plugins/platforms/${p}" ] && cp -L "${QT_PREFIX}/plugins/platforms/${p}" "${STAGE}/plugins/platforms/"
done
cp -L "${QT_PREFIX}/plugins/xcbglintegrations/"*.so "${STAGE}/plugins/xcbglintegrations/" 2>/dev/null || true
# 必要 QML 模块
mkdir -p "${STAGE}/qml"
for m in QtQml QtQuick Qt Qt5Compat; do
[ -d "${QT_PREFIX}/qml/${m}" ] && cp -rL "${QT_PREFIX}/qml/${m}" "${STAGE}/qml/"
done
# 打包 QML 插件与 Qt 插件自身的依赖
find "${STAGE}/qml" "${STAGE}/plugins" -name "*.so" 2>/dev/null | while read -r so; do
bundle_libs "$so"
done
fi
cat > "${STAGE}/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 +x "${STAGE}/run.sh"
if [ "$WITH_GUI" = "1" ]; then
cat > "${STAGE}/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 +x "${STAGE}/run-gui.sh"
fi
echo "==> 生成 tar.gz"
tar -C "${DIST}" -czf "${DIST}/${NAME}.tar.gz" "${NAME}"
echo
echo "完成: ${DIST}/${NAME}.tar.gz"
du -sh "${DIST}/${NAME}.tar.gz"