Skip to content

fix(linux): not destination files on linux cmake #73

fix(linux): not destination files on linux cmake

fix(linux): not destination files on linux cmake #73

Workflow file for this run

name: Build Test
on:
push:
branches:
- flutter
paths-ignore:
- "**.md"
- ".gitignore"
- "LICENSE"
pull_request:
branches:
- flutter
paths-ignore:
- "**.md"
- ".gitignore"
- "LICENSE"
permissions:
contents: read
checks: write
pull-requests: write
jobs:
analyze:
name: Analyze & Test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: subosito/flutter-action@v2
with:
flutter-version: "3.x"
channel: stable
cache: true
- name: Install dependencies
run: flutter pub get
- name: Dart analyze
run: flutter analyze --no-fatal-infos
- name: Run unit tests
run: flutter test --reporter=github
continue-on-error: true
prepare-dummy-binaries:
name: Prepare dummy binaries
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Create dummy binary placeholders
run: |
mkdir -p assets/binaries/windows
mkdir -p assets/binaries/linux
mkdir -p assets/binaries/android/arm64-v8a
mkdir -p assets/binaries/android/armeabi-v7a
mkdir -p assets/binaries/android/x86_64
# Windows
printf '\x4D\x5A' > assets/binaries/windows/ffmpeg.exe
printf '\x4D\x5A' > assets/binaries/windows/ffprobe.exe
printf '\x4D\x5A' > assets/binaries/windows/yt-dlp.exe
# Linux
printf '\x7fELF' > assets/binaries/linux/ffmpeg
printf '\x7fELF' > assets/binaries/linux/ffprobe
printf '\x7fELF' > assets/binaries/linux/yt-dlp
chmod +x assets/binaries/linux/*
# Android
printf '\x7fELF' > assets/binaries/android/arm64-v8a/yt-dlp
printf '\x7fELF' > assets/binaries/android/armeabi-v7a/yt-dlp
printf '\x7fELF' > assets/binaries/android/x86_64/yt-dlp
find assets/binaries -type f | sort
- uses: actions/upload-artifact@v4
with:
name: dummy-binaries
path: assets/binaries
retention-days: 1
# Linux
test-linux:
name: Build Test — Linux (deb + AppImage + portable)
needs: [analyze, prepare-dummy-binaries]
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
- name: Install system dependencies
run: |
sudo apt-get update -y
sudo apt-get install -y \
clang cmake ninja-build pkg-config \
libgtk-3-dev liblzma-dev libstdc++-12-dev \
dpkg-dev fakeroot wget file
- name: Download dummy binaries
uses: actions/download-artifact@v4
with:
name: dummy-binaries
path: assets/binaries
- uses: subosito/flutter-action@v2
with:
flutter-version: "3.x"
channel: stable
cache: true
- name: Get Flutter dependencies
run: flutter pub get
# Installer (deb)
- name: Build Linux release (installer)
run: flutter build linux --release --dart-define=PORTABLE=false
- name: Inject binaries
run: |
mkdir -p build/linux/x64/release/bundle/bin
cp assets/binaries/linux/ffmpeg build/linux/x64/release/bundle/bin/
cp assets/binaries/linux/yt-dlp build/linux/x64/release/bundle/bin/
chmod +x build/linux/x64/release/bundle/bin/*
- name: Build .deb package
run: |
VERSION="0.0.0-test"
PKG="frameextractor_${VERSION}_amd64"
BUNDLE="build/linux/x64/release/bundle"
mkdir -p "$PKG/DEBIAN"
mkdir -p "$PKG/opt/frameextractor"
mkdir -p "$PKG/usr/bin"
mkdir -p "$PKG/usr/share/applications"
mkdir -p "$PKG/usr/share/icons/hicolor/256x256/apps"
cp -r "$BUNDLE/." "$PKG/opt/frameextractor/"
EXE=$(find "$PKG/opt/frameextractor" -maxdepth 1 -type f ! -name "*.so" ! -name "*.desktop" | head -1)
EXE_NAME=$(basename "$EXE")
[ "$EXE_NAME" != "frameextractor" ] && mv "$EXE" "$PKG/opt/frameextractor/frameextractor"
ln -s /opt/frameextractor/frameextractor "$PKG/usr/bin/frameextractor"
cat > "$PKG/usr/share/applications/frameextractor.desktop" << 'DESKTOP'
[Desktop Entry]
Version=1.0
Type=Application
Name=FrameExtractor
Exec=/opt/frameextractor/frameextractor
Icon=frameextractor
Categories=Video;AudioVideo;
Terminal=false
DESKTOP
[ -f "assets/icons/icon_256.png" ] && \
cp "assets/icons/icon_256.png" "$PKG/usr/share/icons/hicolor/256x256/apps/frameextractor.png"
cat > "$PKG/DEBIAN/control" << CTRL
Package: frameextractor
Version: ${VERSION}
Architecture: amd64
Maintainer: nokarin <contact@nokarin.my.id>
Description: Effortless video frame extraction
Depends: libgtk-3-0, libblkid1, liblzma5
Section: video
Priority: optional
CTRL
printf '#!/bin/sh\nchmod +x /opt/frameextractor/frameextractor 2>/dev/null||true\nexit 0' \
> "$PKG/DEBIAN/postinst"
chmod 755 "$PKG/DEBIAN/postinst"
fakeroot dpkg-deb --build "$PKG"
echo "✓ .deb built: $(du -h ${PKG}.deb | cut -f1)"
dpkg-deb --info "${PKG}.deb"
- name: Build .AppImage
run: |
BUNDLE="build/linux/x64/release/bundle"
wget -q "https://github.com/AppImage/AppImageKit/releases/download/continuous/appimagetool-x86_64.AppImage" \
-O /tmp/appimagetool.AppImage
chmod +x /tmp/appimagetool.AppImage
cd /tmp && ./appimagetool.AppImage --appimage-extract > /dev/null 2>&1
APPIMAGETOOL="/tmp/squashfs-root/AppRun"
cd "$GITHUB_WORKSPACE"
mkdir -p AppDir/app
mkdir -p AppDir/usr/share/icons/hicolor/256x256/apps
cp -r "$BUNDLE/." AppDir/app/
[ -f "assets/icons/icon_256.png" ] \
&& cp "assets/icons/icon_256.png" AppDir/usr/share/icons/hicolor/256x256/apps/frameextractor.png \
&& cp "assets/icons/icon_64.png" AppDir/frameextractor.png \
|| printf 'PNG' > AppDir/frameextractor.png
cat > AppDir/frameextractor.desktop << 'DESKTOP'
[Desktop Entry]
Type=Application
Name=FrameExtractor
Exec=frameextractor
Icon=frameextractor
Categories=Video;AudioVideo;
Terminal=false
DESKTOP
cat > AppDir/AppRun << 'APPRUN'
#!/bin/sh
APPDIR="$(dirname "$(readlink -f "$0")")"
export PATH="$APPDIR/app/bin:$PATH"
export LD_LIBRARY_PATH="$APPDIR/app/lib:$LD_LIBRARY_PATH"
EXE_NAME=$(find "$APPDIR/app" -maxdepth 1 -type f ! -name "*.so" ! -name "*.desktop" \
| xargs -I{} basename {} | head -1)
[ -z "$EXE_NAME" ] && echo "Executable not found" >&2 && exit 1
cd "$APPDIR/app"
exec "./$EXE_NAME" "$@"
APPRUN
chmod +x AppDir/AppRun
ARCH=x86_64 "$APPIMAGETOOL" --no-appstream AppDir "FrameExtractor-linux.AppImage"
echo "✓ AppImage built: $(du -h FrameExtractor-linux.AppImage | cut -f1)"
# Portable
- name: Build Linux release (portable)
run: flutter build linux --release --dart-define=PORTABLE=true
- name: Inject binaries (portable)
run: |
mkdir -p build/linux/x64/release/bundle/bin
cp assets/binaries/linux/ffmpeg build/linux/x64/release/bundle/bin/
cp assets/binaries/linux/yt-dlp build/linux/x64/release/bundle/bin/
chmod +x build/linux/x64/release/bundle/bin/*
- name: Package portable (.tar.gz)
run: |
tar -czf FrameExtractor-linux-portable.tar.gz \
-C build/linux/x64/release/bundle .
echo "✓ portable tarball: $(du -h FrameExtractor-linux-portable.tar.gz | cut -f1)"
- name: Verify all Linux artifacts
run: |
echo "=== Linux build artifacts ==="
ls -lh frameextractor_*_amd64.deb FrameExtractor-linux.AppImage FrameExtractor-linux-portable.tar.gz
echo "✓ All Linux builds OK"
# Linux (RPM)
test-linux-rpm:
name: Build Test — Linux (RPM)
needs: [analyze, prepare-dummy-binaries]
runs-on: ubuntu-latest
container:
image: fedora:latest
env:
GIT_CONFIG_GLOBAL: /root/.gitconfig-ci
steps:
- uses: actions/checkout@v4
- name: Install build dependencies
run: |
sudo dnf install -y @development-tools \
clang cmake ninja-build pkg-config \
gtk3-devel xz-devel libstdc++-devel \
rpm-build jq which
- name: Configure Git safe directory
run: |
git config --global --add safe.directory '*'
- name: Download dummy binaries
uses: actions/download-artifact@v4
with:
name: dummy-binaries
path: assets/binaries
- uses: subosito/flutter-action@v2
with:
flutter-version: "3.x"
channel: stable
cache: true
- name: Get Flutter dependencies
run: flutter pub get
- name: Build Linux (debug)
run: flutter build linux --debug --dart-define=PORTABLE=false
- name: Inject binaries
run: |
mkdir -p build/linux/x64/debug/bundle/bin
cp assets/binaries/linux/ffmpeg build/linux/x64/debug/bundle/bin/
cp assets/binaries/linux/yt-dlp build/linux/x64/debug/bundle/bin/
chmod +x build/linux/x64/debug/bundle/bin/*
- name: Build .rpm package
run: |
VERSION="0.0.0"
BUNDLE_DIR="$GITHUB_WORKSPACE/build/linux/x64/debug/bundle"
RPMROOT="$GITHUB_WORKSPACE/rpmbuild"
mkdir -p "$RPMROOT"/{BUILD,BUILDROOT,RPMS,SOURCES,SPECS,SRPMS}
echo "$BUNDLE_DIR" > "$RPMROOT/SOURCES/bundle_path.txt"
[ -f "$GITHUB_WORKSPACE/assets/icons/icon_256.png" ] && \
cp "$GITHUB_WORKSPACE/assets/icons/icon_256.png" "$RPMROOT/SOURCES/frameextractor.png"
cat > "$RPMROOT/SOURCES/frameextractor.desktop" << 'DESKTOP'
[Desktop Entry]
Type=Application
Name=FrameExtractor
Exec=/opt/frameextractor/frameextractor
Icon=frameextractor
Categories=Video;AudioVideo;
Terminal=false
DESKTOP
cat > "$RPMROOT/SPECS/frameextractor.spec" << SPEC
Name: FrameExtractor
Version: ${VERSION}
Release: 1%{?dist}
Summary: Effortless video frame extraction
License: GPLv3
BuildArch: x86_64
Requires: gtk3, xz-libs
%description
FrameExtractor — effortless video frame extraction.
%install
BUNDLE=\$(cat $RPMROOT/SOURCES/bundle_path.txt)
mkdir -p %{buildroot}/opt/frameextractor
mkdir -p %{buildroot}/usr/bin
mkdir -p %{buildroot}/usr/share/applications
mkdir -p %{buildroot}/usr/share/icons/hicolor/256x256/apps
cp -r \$BUNDLE/. %{buildroot}/opt/frameextractor/
EXE=\$(find %{buildroot}/opt/frameextractor -maxdepth 1 -type f ! -name "*.so" ! -name "*.desktop" | head -1)
EXE_NAME=\$(basename \$EXE)
[ "\$EXE_NAME" != "frameextractor" ] && \
mv "\$EXE" %{buildroot}/opt/frameextractor/frameextractor
chmod +x %{buildroot}/opt/frameextractor/frameextractor
ln -s /opt/frameextractor/frameextractor %{buildroot}/usr/bin/frameextractor
cp $RPMROOT/SOURCES/frameextractor.desktop \
%{buildroot}/usr/share/applications/frameextractor.desktop
if [ -f "$RPMROOT/SOURCES/frameextractor.png" ]; then
cp $RPMROOT/SOURCES/frameextractor.png \
%{buildroot}/usr/share/icons/hicolor/256x256/apps/frameextractor.png
fi
%files
%attr(0755, root, root) /usr/bin/frameextractor
/opt/frameextractor/*
/usr/share/applications/frameextractor.desktop
/usr/share/icons/hicolor/256x256/apps/frameextractor.png
SPEC
rpmbuild -bb \
--define "_topdir $RPMROOT" \
--define "_builddir $RPMROOT/BUILD" \
--define "__os_install_post %{nil}" \
"$RPMROOT/SPECS/frameextractor.spec"
- name: Verify RPM
run: |
find $GITHUB_WORKSPACE/rpmbuild/RPMS -name "*.rpm" | grep . \
&& echo "✓ RPM build OK" \
|| (echo "✗ RPM not found" && exit 1)
# Windows
test-windows:
name: Build Test — Windows (installer + portable)
needs: [analyze, prepare-dummy-binaries]
runs-on: windows-latest
steps:
- uses: actions/checkout@v4
- name: Download dummy binaries
uses: actions/download-artifact@v4
with:
name: dummy-binaries
path: assets/binaries
- uses: subosito/flutter-action@v2
with:
flutter-version: "3.x"
channel: stable
cache: true
- name: Get Flutter dependencies
run: flutter pub get
# Installer
- name: Build Windows release (installer)
run: flutter build windows --release --dart-define=PORTABLE=false
- name: Inject binaries — installer
shell: pwsh
run: |
$dest = "build\windows\x64\runner\Release\bin"
New-Item -ItemType Directory -Force -Path $dest | Out-Null
Copy-Item "assets\binaries\windows\ffmpeg.exe" $dest
Copy-Item "assets\binaries\windows\yt-dlp.exe" $dest
- name: Create Inno Setup script
shell: pwsh
run: |
@"
[Setup]
AppName=Frame Extractor
AppVersion=0.0.0-test
AppPublisher=nokarin
DefaultDirName={localappdata}\FrameExtractor
DefaultGroupName=FrameExtractor
AllowNoIcons=yes
OutputDir=.
OutputBaseFilename=FrameExtractor-windows-installer
Compression=lzma2/ultra64
SolidCompression=yes
WizardStyle=modern
PrivilegesRequired=lowest
PrivilegesRequiredOverridesAllowed=dialog
UninstallDisplayIcon={app}\frameextractor.exe
[Languages]
Name: "english"; MessagesFile: "compiler:Default.isl"
[Files]
Source: "build\windows\x64\runner\Release\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs
[Icons]
Name: "{userprograms}\Frame Extractor"; Filename: "{app}\frameextractor.exe"
"@ | Out-File -FilePath "installer.iss" -Encoding UTF8
- name: Compile Inno Setup installer
shell: pwsh
run: |
& "C:\Program Files (x86)\Inno Setup 6\ISCC.exe" "installer.iss"
if (!(Test-Path "FrameExtractor-windows-installer.exe")) {
Write-Error "Installer .exe not produced"; exit 1
}
Write-Host "✓ Installer: $('{0:N1} MB' -f ((Get-Item 'FrameExtractor-windows-installer.exe').Length / 1MB))"
# Portable
- name: Build Windows release (portable)
run: flutter build windows --release --dart-define=PORTABLE=true
- name: Inject binaries — portable
shell: pwsh
run: |
$dest = "build\windows\x64\runner\Release\bin"
New-Item -ItemType Directory -Force -Path $dest | Out-Null
Copy-Item "assets\binaries\windows\ffmpeg.exe" $dest
Copy-Item "assets\binaries\windows\yt-dlp.exe" $dest
- name: Package Windows portable
shell: pwsh
run: |
Compress-Archive -Path "build\windows\x64\runner\Release\*" `
-DestinationPath "FrameExtractor-windows-portable.zip"
Write-Host "✓ Portable: $('{0:N1} MB' -f ((Get-Item 'FrameExtractor-windows-portable.zip').Length / 1MB))"
- name: Verify Windows artifacts
shell: pwsh
run: |
$ok = $true
@("FrameExtractor-windows-installer.exe", "FrameExtractor-windows-portable.zip") | ForEach-Object {
if (Test-Path $_) { Write-Host "✓ $_" }
else { Write-Error "✗ $_ missing"; $ok = $false }
}
if (!$ok) { exit 1 }
# Android
test-android:
name: Build Test — Android (arm64 & arm32 & x86_64)
needs: [analyze, prepare-dummy-binaries]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Download dummy binaries
uses: actions/download-artifact@v4
with:
name: dummy-binaries
path: assets/binaries
- uses: actions/setup-java@v4
with:
distribution: temurin
java-version: "17"
- uses: subosito/flutter-action@v2
with:
flutter-version: "3.x"
channel: stable
cache: true
- name: Get Flutter dependencies
run: flutter pub get
- name: Build split APKs (debug)
run: flutter build apk --debug --dart-define=PORTABLE=false --split-per-abi
- name: Verify all three APK ABIs
run: |
ok=true
for abi in arm64-v8a armeabi-v7a x86_64; do
APK="build/app/outputs/flutter-apk/app-${abi}-debug.apk"
if [ -f "$APK" ]; then
echo "✓ $abi — $(du -h $APK | cut -f1)"
else
echo "✗ $abi — NOT FOUND"
ok=false
fi
done
$ok || exit 1
# Gate
all-tests-pass:
name: All build tests passed
needs: [analyze, test-linux, test-linux-rpm, test-windows, test-android]
runs-on: ubuntu-latest
if: always()
steps:
- name: Check all jobs
run: |
echo "analyze: ${{ needs.analyze.result }}"
echo "test-linux: ${{ needs.test-linux.result }}"
echo "test-linux-rpm: ${{ needs.test-linux-rpm.result }}"
echo "test-windows: ${{ needs.test-windows.result }}"
echo "test-android: ${{ needs.test-android.result }}"
if [[ \
"${{ needs.analyze.result }}" == "success" && \
"${{ needs.test-linux.result }}" == "success" && \
"${{ needs.test-linux-rpm.result }}" == "success" && \
"${{ needs.test-windows.result }}" == "success" && \
"${{ needs.test-android.result }}" == "success" \
]]; then
echo "✅ All build tests passed."
else
echo "❌ One or more build tests failed."
exit 1
fi