Files
VoiletMark/.github/workflows/packages.yml
T
liyepan 98b3b1b20c
安装包 / Linux aarch64 (push) Canceled after 0s
安装包 / Linux x86_64 (push) Canceled after 0s
安装包 / Windows x86_64 (push) Canceled after 0s
安装包 / macOS arm64 (Apple Silicon) (push) Canceled after 0s
安装包 / macOS x86_64 (Intel) (push) Canceled after 0s
安装包 / 发布到 Release (push) Canceled after 0s
fix: v0.12.5 —— 修 Windows 链接器被 Git Bash 抢、macOS 只部署需要的插件
- Windows:Git Bash 的 /usr/bin/link.exe 会先于 MSVC 的 link.exe 被 nmake 找到,
  把 cl.exe 所在目录放到 PATH 最前面;同时给 MSVC 加 /utf-8,
  修掉 C4566 和潜在的中文串码
- macOS:macdeployqt 之后删掉 virtualkeyboard / platforminputcontexts /
  printsupport / iconengines / imageformats / tls / bearer 这些用不到的插件,
  它们会把 /opt/homebrew 的一堆 dylib 拖进来
- bundle-libs.sh:改写失败不再静默吞掉,检查时跳过 otool 的文件名行,
  失败时打印「文件 <- 依赖」方便定位
2026-10-23 14:48:50 +08:00

400 lines
13 KiB
YAML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
name: 安装包
# Gitea 不跑这个工作流;同步到 GitHub 后,这里编译并打出:
# Linux deb / rpm(x86_64、aarch64)
# Windows 安装包(关联 .md)+ 便携 zip
# macOS arm64 / x86_64 两个 dmg(未签名,不是公证版)
on:
push:
branches: [main, master]
tags: ["v*"]
pull_request:
workflow_dispatch:
inputs:
publish:
description: "发布 Release(用 v<版本> 当 tag,不必先打 tag)"
type: boolean
default: false
permissions:
contents: write
concurrency:
group: packages-${{ github.ref }}
cancel-in-progress: true
env:
QT_VERSION: "5.15.2"
jobs:
linux:
name: Linux ${{ matrix.arch }}
runs-on: ${{ matrix.runs-on }}
continue-on-error: ${{ matrix.optional }}
timeout-minutes: 30
strategy:
fail-fast: false
matrix:
include:
- arch: x86_64
runs-on: ubuntu-22.04
deb_arch: amd64
rpm_arch: x86_64
optional: false
- arch: aarch64
runs-on: ubuntu-24.04-arm
deb_arch: arm64
rpm_arch: aarch64
optional: true
steps:
- name: 检出代码
uses: actions/checkout@v4
- name: 安装构建依赖
run: |
sudo apt-get update
sudo apt-get install -y --no-install-recommends \
build-essential file \
qtbase5-dev qtbase5-dev-tools qt5-qmake \
rpm dpkg-dev
- name: 读取版本号
id: meta
run: |
version=$(sed -n 's/^VERSION[[:space:]]*=[[:space:]]*//p' VoiletMark.pro | head -n1 | tr -d '[:space:]')
if [ -z "$version" ]; then
echo "VoiletMark.pro 里没有 VERSION" >&2
exit 1
fi
echo "version=$version" >> "$GITHUB_OUTPUT"
- name: 编译
run: |
qmake_bin=$(command -v qmake-qt5 || command -v qmake || true)
if [ -z "$qmake_bin" ]; then
echo "找不到 qmake(确认装了 qtbase5-dev / qt5-qmake)" >&2
exit 1
fi
"$qmake_bin" -v
mkdir -p build
cd build
"$qmake_bin" ../VoiletMark.pro PREFIX=/usr CONFIG+=release
make -j"$(nproc)"
make install INSTALL_ROOT="$PWD/stage"
find stage -type f | sort
- name: 打 .deb
run: ./packaging/build-deb.sh build/stage "${{ steps.meta.outputs.version }}" "${{ matrix.deb_arch }}" dist
- name: 打 .rpm
run: ./packaging/build-rpm.sh build/stage "${{ steps.meta.outputs.version }}" "${{ matrix.rpm_arch }}" dist
- name: 检查产物
run: |
ls -lh dist
dpkg-deb -I dist/*.deb
rpm -qpi dist/*.rpm
- name: 上传产物
uses: actions/upload-artifact@v4
with:
name: voiletmark-linux-${{ matrix.arch }}
path: dist/*
if-no-files-found: error
windows:
name: Windows x86_64
runs-on: windows-2022
timeout-minutes: 40
steps:
- name: 检出代码
uses: actions/checkout@v4
- name: 准备 MSVC 环境
uses: ilammy/msvc-dev-cmd@v1
with:
arch: x64
- name: 安装 Qt ${{ env.QT_VERSION }}
uses: jurplel/install-qt-action@v4
with:
version: ${{ env.QT_VERSION }}
arch: win64_msvc2019_64
cache: true
- name: 编译并收集 Qt 依赖
shell: bash
run: |
set -euo pipefail
version=$(sed -n 's/^VERSION[[:space:]]*=[[:space:]]*//p' VoiletMark.pro | head -n1 | tr -d '[:space:]')
if [ -z "$version" ]; then
echo "VoiletMark.pro 里没有 VERSION" >&2
exit 1
fi
echo "APP_VERSION=$version" >> "$GITHUB_ENV"
mkdir -p build
cd build
# Git Bash 的 /usr/bin 里也有个 link.exe(coreutils 的硬链接工具),
# 必须把 MSVC 的 bin 放到 PATH 最前面,nmake 才会用真正的 link.exe
cl_path=$(command -v cl.exe || command -v cl || true)
if [ -z "$cl_path" ]; then
echo "PATH 里找不到 cl.exe" >&2
exit 1
fi
msvc_bin=$(dirname "$cl_path")
export PATH="$msvc_bin:$PATH"
echo "cl: $(command -v cl)"
echo "link: $(command -v link)"
qmake ../VoiletMark.pro CONFIG+=release
nmake release || nmake
if [ -f release/VoiletMark.exe ]; then
exe=release/VoiletMark.exe
else
exe=$(find . -name VoiletMark.exe | head -n1)
fi
if [ -z "$exe" ]; then
echo "没找到 VoiletMark.exe" >&2
exit 1
fi
mkdir -p ../deploy
cp "$exe" ../deploy/VoiletMark.exe
cd ..
windeployqt --release --no-translations --compiler-runtime deploy/VoiletMark.exe
find deploy -maxdepth 1 -type f | sort
- name: 打 NSIS 安装包(关联 .md)
shell: bash
run: |
set -euo pipefail
mkdir -p dist
makensis='/c/Program Files (x86)/NSIS/makensis.exe'
if [ ! -x "$makensis" ]; then
makensis=$(find '/c/Program Files (x86)' '/c/Program Files' -maxdepth 3 -iname 'makensis.exe' 2>/dev/null | head -n1)
fi
if [ -z "$makensis" ]; then
choco install nsis -y --no-progress
makensis=$(find '/c/Program Files (x86)' '/c/Program Files' -maxdepth 3 -iname 'makensis.exe' 2>/dev/null | head -n1)
fi
if [ -z "$makensis" ]; then
echo "找不到 makensis(NSIS)" >&2
exit 1
fi
output=$(cygpath -w "$PWD/dist/VoiletMark-$APP_VERSION-win64-setup.exe")
deploy=$(cygpath -w "$PWD/deploy")
icon=$(cygpath -w "$PWD/packaging/voiletmark.ico")
script=$(cygpath -w "$PWD/packaging/windows/installer.nsi")
"$makensis" \
"/DAPP_VERSION=$APP_VERSION" \
"/DDEPLOY_DIR=$deploy" \
"/DICON_FILE=$icon" \
"/DOUTPUT_FILE=$output" \
"$script"
ls -lh dist
- name: 便携版 zip
shell: pwsh
run: |
Compress-Archive -Path deploy/* -DestinationPath "dist/VoiletMark-$env:APP_VERSION-win64-portable.zip"
Get-ChildItem dist | Select-Object Name, Length
- name: 上传产物
uses: actions/upload-artifact@v4
with:
name: voiletmark-windows-x86_64
path: dist/*
if-no-files-found: error
macos-arm64:
name: macOS arm64 (Apple Silicon)
runs-on: macos-15
timeout-minutes: 50
env:
HOMEBREW_NO_AUTO_UPDATE: "1"
steps:
- name: 检出代码
uses: actions/checkout@v4
- name: 安装 Qt 5(Homebrew,原生 arm64)
run: |
set -euo pipefail
brew install qt@5
qt_prefix=$(brew --prefix qt@5)
echo "QT_PREFIX=$qt_prefix" >> "$GITHUB_ENV"
"$qt_prefix/bin/qmake" -v
- name: 编译并打包 Qt 框架
run: |
set -euo pipefail
version=$(sed -n 's/^VERSION[[:space:]]*=[[:space:]]*//p' VoiletMark.pro | head -n1 | tr -d '[:space:]')
if [ -z "$version" ]; then
echo "VoiletMark.pro 里没有 VERSION" >&2
exit 1
fi
echo "APP_VERSION=$version" >> "$GITHUB_ENV"
mkdir -p build
cd build
"$QT_PREFIX/bin/qmake" ../VoiletMark.pro CONFIG+=release
make -j"$(sysctl -n hw.ncpu)"
file VoiletMark.app/Contents/MacOS/VoiletMark | tee /tmp/arch.txt
grep -q arm64 /tmp/arch.txt
"$QT_PREFIX/bin/macdeployqt" VoiletMark.app -always-overwrite
# 只留平台插件和样式插件;虚拟键盘 / 打印 / 图片格式这些用不到,
# 留着只会把 Homebrew 的 dylib 拖进来
rm -rf VoiletMark.app/Contents/PlugIns/virtualkeyboard \
VoiletMark.app/Contents/PlugIns/platforminputcontexts \
VoiletMark.app/Contents/PlugIns/printsupport \
VoiletMark.app/Contents/PlugIns/iconengines \
VoiletMark.app/Contents/PlugIns/imageformats \
VoiletMark.app/Contents/PlugIns/networkinformation \
VoiletMark.app/Contents/PlugIns/tls \
VoiletMark.app/Contents/PlugIns/bearer
otool -L VoiletMark.app/Contents/MacOS/VoiletMark | head -30
- name: 收 Homebrew 依赖 + ad-hoc 签名
run: |
set -euo pipefail
./packaging/macos/bundle-libs.sh build/VoiletMark.app
xattr -cr build/VoiletMark.app
codesign --force --deep --sign - build/VoiletMark.app
codesign --verify --deep --strict build/VoiletMark.app
- name: 打 dmg
run: ./packaging/macos/build-dmg.sh build/VoiletMark.app "$APP_VERSION" arm64 dist
- name: 上传产物
uses: actions/upload-artifact@v4
with:
name: voiletmark-macos-arm64
path: dist/*
if-no-files-found: error
macos-x86_64:
name: macOS x86_64 (Intel)
# Intel 的 GitHub runner;拿不到这个 runner 时这一步会失败,不影响其它产物
runs-on: macos-15-intel
timeout-minutes: 40
steps:
- name: 检出代码
uses: actions/checkout@v4
- name: 安装 Qt ${{ env.QT_VERSION }}
uses: jurplel/install-qt-action@v4
with:
version: ${{ env.QT_VERSION }}
arch: clang_64
cache: true
- name: 编译并打包 Qt 框架
run: |
set -euo pipefail
version=$(sed -n 's/^VERSION[[:space:]]*=[[:space:]]*//p' VoiletMark.pro | head -n1 | tr -d '[:space:]')
if [ -z "$version" ]; then
echo "VoiletMark.pro 里没有 VERSION" >&2
exit 1
fi
echo "APP_VERSION=$version" >> "$GITHUB_ENV"
mkdir -p build
cd build
qmake ../VoiletMark.pro CONFIG+=release
make -j"$(sysctl -n hw.ncpu)"
file VoiletMark.app/Contents/MacOS/VoiletMark | tee /tmp/arch.txt
grep -q x86_64 /tmp/arch.txt
macdeployqt VoiletMark.app -always-overwrite
rm -rf VoiletMark.app/Contents/PlugIns/virtualkeyboard \
VoiletMark.app/Contents/PlugIns/platforminputcontexts \
VoiletMark.app/Contents/PlugIns/printsupport \
VoiletMark.app/Contents/PlugIns/iconengines \
VoiletMark.app/Contents/PlugIns/imageformats \
VoiletMark.app/Contents/PlugIns/networkinformation \
VoiletMark.app/Contents/PlugIns/tls \
VoiletMark.app/Contents/PlugIns/bearer
- name: 收依赖 + ad-hoc 签名
run: |
set -euo pipefail
./packaging/macos/bundle-libs.sh build/VoiletMark.app
xattr -cr build/VoiletMark.app
codesign --force --deep --sign - build/VoiletMark.app
codesign --verify --deep --strict build/VoiletMark.app
- name: 打 dmg
run: ./packaging/macos/build-dmg.sh build/VoiletMark.app "$APP_VERSION" x86_64 dist
- name: 上传产物
uses: actions/upload-artifact@v4
with:
name: voiletmark-macos-x86_64
path: dist/*
if-no-files-found: error
release:
name: 发布到 Release
needs: [linux, windows, macos-arm64, macos-x86_64]
# 打 tag 或手动勾 publish 才发;普通推送/PR 只留 artifact。
# always() 是为了某个平台失败时其它产物还能发出来。
if: >-
always() && (
startsWith(github.ref, 'refs/tags/') ||
(github.event_name == 'workflow_dispatch' && inputs.publish)
)
runs-on: ubuntu-24.04
timeout-minutes: 10
steps:
- name: 检出代码
uses: actions/checkout@v4
- name: 读取版本号
id: meta
run: |
version=$(sed -n 's/^VERSION[[:space:]]*=[[:space:]]*//p' VoiletMark.pro | head -n1 | tr -d '[:space:]')
echo "version=$version" >> "$GITHUB_OUTPUT"
- name: 下载所有产物
uses: actions/download-artifact@v4
with:
path: dist
merge-multiple: true
- name: 检查产物
run: |
ls -lh dist
count=$(find dist -maxdepth 1 -type f | wc -l)
if [ "$count" -eq 0 ]; then
echo "一个安装包都没有,不发布" >&2
exit 1
fi
- name: 生成 SHA256SUMS
run: |
cd dist
find . -maxdepth 1 -type f ! -name SHA256SUMS -printf '%f\n' | sort > /tmp/files.txt
xargs sha256sum < /tmp/files.txt > SHA256SUMS
cat SHA256SUMS
- name: 挂到 Release
uses: softprops/action-gh-release@v2
with:
# 打 tag 时用那个 tag;手动发布时用 v<版本>(不存在就按当前提交新建)
tag_name: ${{ startsWith(github.ref, 'refs/tags/') && github.ref_name || format('v{0}', steps.meta.outputs.version) }}
target_commitish: ${{ github.sha }}
name: VoiletMark ${{ steps.meta.outputs.version }}
files: dist/*
generate_release_notes: true
fail_on_unmatched_files: true