ci: build Linux release package
Some checks failed
Build Linux Release / build-linux (push) Has been cancelled

This commit is contained in:
luochen570
2026-05-29 22:51:24 +08:00
parent be4446c990
commit 8c9a92f2cb
4 changed files with 169 additions and 1 deletions

View File

@@ -0,0 +1,49 @@
name: Build Linux Release
on:
push:
branches:
- main
tags:
- 'v*'
pull_request:
branches:
- main
workflow_dispatch:
jobs:
build-linux:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install host tools
run: |
sudo apt-get update
sudo apt-get install -y --no-install-recommends \
ca-certificates \
curl \
bzip2 \
tar \
file
- name: Build release package
run: |
chmod +x scripts/*.sh
./scripts/package-linux-release.sh
- name: Verify package
run: |
test -s dist-linux/chengnan-linux-x86_64.tar.gz
sha256sum -c dist-linux/chengnan-linux-x86_64.tar.gz.sha256
tar -tzf dist-linux/chengnan-linux-x86_64.tar.gz | grep -E '^chengnan-linux-x86_64/(bin/chengnan|run-chengnan.sh)$'
- name: Upload artifact
uses: actions/upload-artifact@v3
with:
name: chengnan-linux-x86_64
path: |
dist-linux/chengnan-linux-x86_64.tar.gz
dist-linux/chengnan-linux-x86_64.tar.gz.sha256
if-no-files-found: error

View File

@@ -97,6 +97,29 @@ cd /root/chengnan
build-linux/chengnan build-linux/chengnan
``` ```
### 生成发布包
如需生成可分发的 Linux x86_64 发布包,执行:
```bash
cd /root/chengnan
./scripts/package-linux-release.sh
```
脚本会先执行 Release 构建,再将程序、项目内 Qt/OpenCV 运行时库、Qt 插件和启动脚本打包到:
```text
dist-linux/chengnan-linux-x86_64.tar.gz
dist-linux/chengnan-linux-x86_64.tar.gz.sha256
```
解压后在有 X11 / Wayland 图形会话的 Linux 桌面环境中运行:
```bash
tar -xzf chengnan-linux-x86_64.tar.gz
./chengnan-linux-x86_64/run-chengnan.sh
```
### 分步构建 ### 分步构建
如果希望先准备依赖,再单独构建: 如果希望先准备依赖,再单独构建:

View File

@@ -0,0 +1,96 @@
#!/usr/bin/env bash
set -euo pipefail
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
ENV_DIR="$ROOT_DIR/tools/linux-build-env"
BUILD_DIR="$ROOT_DIR/build-linux"
DIST_DIR="$ROOT_DIR/dist-linux"
PACKAGE_ROOT="$DIST_DIR/chengnan-linux-x86_64"
APP_BIN="$PACKAGE_ROOT/bin/chengnan"
LIB_DIR="$PACKAGE_ROOT/lib"
PLUGIN_DIR="$PACKAGE_ROOT/plugins"
QT_CONF="$PACKAGE_ROOT/bin/qt.conf"
ARCHIVE="$DIST_DIR/chengnan-linux-x86_64.tar.gz"
"$ROOT_DIR/scripts/build-linux-binary.sh"
rm -rf "$PACKAGE_ROOT" "$ARCHIVE"
mkdir -p "$PACKAGE_ROOT/bin" "$LIB_DIR" "$PLUGIN_DIR"
"$ENV_DIR/bin/cmake" --install "$BUILD_DIR" --prefix "$PACKAGE_ROOT"
if [[ ! -x "$APP_BIN" ]]; then
echo "[package] 未找到可执行文件:$APP_BIN" >&2
exit 1
fi
copy_lib() {
local lib="$1"
if [[ -f "$lib" ]]; then
cp -L -n "$lib" "$LIB_DIR/"
fi
}
# 只打包项目内二进制环境中的依赖,避免把系统 /lib、/usr/lib 复制进制品。
while IFS= read -r lib; do
case "$lib" in
"$ENV_DIR"/*) copy_lib "$lib" ;;
esac
done < <(LD_LIBRARY_PATH="$ENV_DIR/lib:${LD_LIBRARY_PATH:-}" ldd "$APP_BIN" | awk '/=>/ {print $3}' | sort -u)
# Qt GUI 程序运行需要平台插件;同时带上常用图片格式插件,保证 jpg/png 等格式可打开。
for subdir in platforms imageformats xcbglintegrations platformthemes styles iconengines; do
if [[ -d "$ENV_DIR/plugins/$subdir" ]]; then
mkdir -p "$PLUGIN_DIR/$subdir"
cp -L "$ENV_DIR/plugins/$subdir"/*.so "$PLUGIN_DIR/$subdir/" 2>/dev/null || true
fi
done
# 平台插件自身还有二级依赖,继续收集项目内环境中的 .so。
if [[ -d "$PLUGIN_DIR" ]]; then
while IFS= read -r plugin; do
while IFS= read -r lib; do
case "$lib" in
"$ENV_DIR"/*) copy_lib "$lib" ;;
esac
done < <(LD_LIBRARY_PATH="$ENV_DIR/lib:$LIB_DIR:${LD_LIBRARY_PATH:-}" ldd "$plugin" | awk '/=>/ {print $3}' | sort -u || true)
done < <(find "$PLUGIN_DIR" -type f -name '*.so' | sort)
fi
cat > "$QT_CONF" <<'QTCFG'
[Paths]
Plugins = ../plugins
QTCFG
cat > "$PACKAGE_ROOT/run-chengnan.sh" <<'RUNNER'
#!/usr/bin/env bash
set -euo pipefail
APP_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
export LD_LIBRARY_PATH="$APP_DIR/lib:${LD_LIBRARY_PATH:-}"
export QT_PLUGIN_PATH="$APP_DIR/plugins"
exec "$APP_DIR/bin/chengnan" "$@"
RUNNER
chmod +x "$PACKAGE_ROOT/run-chengnan.sh"
if command -v patchelf >/dev/null 2>&1; then
patchelf --set-rpath '$ORIGIN/../lib' "$APP_BIN" || true
elif [[ -x "$ENV_DIR/bin/patchelf" ]]; then
"$ENV_DIR/bin/patchelf" --set-rpath '$ORIGIN/../lib' "$APP_BIN" || true
else
echo "[package] 未找到 patchelf制品可通过 run-chengnan.sh 设置 LD_LIBRARY_PATH 运行。"
fi
find "$PACKAGE_ROOT" -type f -name '*.so*' -exec chmod 0644 {} +
chmod +x "$APP_BIN"
tar -C "$DIST_DIR" -czf "$ARCHIVE" "$(basename "$PACKAGE_ROOT")"
if [[ ! -s "$ARCHIVE" ]]; then
echo "[package] 打包失败:$ARCHIVE 为空或不存在" >&2
exit 1
fi
sha256sum "$ARCHIVE" > "$ARCHIVE.sha256"
echo "[package] 发布包:$ARCHIVE"
echo "[package] 校验文件:$ARCHIVE.sha256"

View File

@@ -20,7 +20,7 @@ fi
if [[ ! -x "$ENV_DIR/bin/cmake" || ! -x "$ENV_DIR/bin/ninja" || ! -x "$ENV_DIR/bin/clang++" ]]; then if [[ ! -x "$ENV_DIR/bin/cmake" || ! -x "$ENV_DIR/bin/ninja" || ! -x "$ENV_DIR/bin/clang++" ]]; then
echo "[setup] 在项目目录内创建 Linux 二进制构建环境..." echo "[setup] 在项目目录内创建 Linux 二进制构建环境..."
"$MICROMAMBA_BIN" create -y -p "$ENV_DIR" -c conda-forge \ "$MICROMAMBA_BIN" create -y -p "$ENV_DIR" -c conda-forge \
cmake make clangxx qt-main opencv pkg-config cmake ninja make clangxx qt-main opencv pkg-config patchelf
fi fi
# README 中约定的路径,使用软链接指向隔离环境,便于 CMake 查找。 # README 中约定的路径,使用软链接指向隔离环境,便于 CMake 查找。