From 91b8de706bc05481b3832ae91946843cf23812b0 Mon Sep 17 00:00:00 2001 From: k4yt3x Date: Fri, 10 Jan 2025 00:00:00 +0000 Subject: [PATCH] build(appimage): add AppImage build script Signed-off-by: k4yt3x --- .github/workflows/build.yml | 56 ++++++++++++++++++++++++++++- .justfile | 46 ++++++++++++++++++++++++ packaging/appimage/video2x.desktop | 10 ++++++ packaging/appimage/video2x.png | Bin 0 -> 10335 bytes 4 files changed, 111 insertions(+), 1 deletion(-) create mode 100644 packaging/appimage/video2x.desktop create mode 100644 packaging/appimage/video2x.png diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 8435f2af0..0e0e2b32d 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -82,7 +82,7 @@ jobs: shell: pwsh run: | $ffmpegVersion = "7.1" - $ncnnVersion = "20240820" + $ncnnVersion = "20241226" git submodule update --init --recursive @@ -122,3 +122,57 @@ jobs: image: video2x tags: latest pushImage: false + + appimage: + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Install dependencies + run: | + sudo apt-get update + sudo apt-get install -y --no-install-recommends \ + build-essential cmake clang pkg-config ninja-build curl file fuse \ + libavcodec-dev \ + libavdevice-dev \ + libavfilter-dev \ + libavformat-dev \ + libavutil-dev \ + libswscale-dev \ + libvulkan-dev \ + glslang-tools \ + libomp-dev \ + libboost-program-options1.83-dev \ + libboost-program-options1.83.0 \ + libspdlog-dev + + - name: Build Video2X + run: | + cmake -G Ninja -B build -S . \ + -DVIDEO2X_USE_EXTERNAL_NCNN=OFF \ + -DNCNN_BUILD_SHARED_LIBS=ON \ + -DCMAKE_CXX_COMPILER=clang++ \ + -DCMAKE_BUILD_TYPE=Release \ + -DNCNN_AVX512=OFF \ + -DCMAKE_INSTALL_PREFIX=AppDir/usr + cmake --build build --config Release --target install --parallel + + - name: Build AppImage + run: | + sudo curl -Lo /usr/local/bin/linuxdeploy \ + https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage + sudo chmod +x /usr/local/bin/linuxdeploy + LD_LIBRARY_PATH=AppDir/usr/lib linuxdeploy \ + --appdir AppDir \ + --executable AppDir/usr/bin/video2x \ + --exclude-library "libvulkan.so.1" \ + --desktop-file packaging/appimage/video2x.desktop \ + --icon-file packaging/appimage/video2x.png \ + --output appimage + + - name: Upload artifacts + uses: actions/upload-artifact@v4 + with: + name: Video2X-x86_64.AppImage + path: Video2X-x86_64.AppImage diff --git a/.justfile b/.justfile index 87ddd2804..7d287d7c3 100644 --- a/.justfile +++ b/.justfile @@ -155,6 +155,52 @@ ubuntu2204: cp packaging/debian/control.ubuntu2204 video2x-linux-ubuntu-amd64/DEBIAN/control dpkg-deb --build video2x-linux-ubuntu-amd64 +[unix] +[group('build')] +appimage: + apt-get update + DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ + build-essential cmake clang pkg-config ninja-build curl file fuse \ + libavcodec-dev \ + libavdevice-dev \ + libavfilter-dev \ + libavformat-dev \ + libavutil-dev \ + libswscale-dev \ + libvulkan-dev \ + glslang-tools \ + libomp-dev \ + libboost-program-options1.83-dev \ + libboost-program-options1.83.0 \ + libspdlog-dev + cmake -G Ninja -B build -S . \ + -DVIDEO2X_USE_EXTERNAL_NCNN=OFF \ + -DNCNN_BUILD_SHARED_LIBS=ON \ + -DCMAKE_CXX_COMPILER=clang++ \ + -DCMAKE_BUILD_TYPE=Release \ + -DNCNN_AVX512=OFF \ + -DCMAKE_INSTALL_PREFIX=AppDir/usr + cmake --build build --config Release --target install --parallel + rm -rf AppDir/usr/share/video2x/models/rife/rife \ + AppDir/usr/share/video2x/models/rife/rife-HD \ + AppDir/usr/share/video2x/models/rife/rife-UHD \ + AppDir/usr/share/video2x/models/rife/rife-anime \ + AppDir/usr/share/video2x/models/rife/rife-v2 \ + AppDir/usr/share/video2x/models/rife/rife-v2.3 \ + AppDir/usr/share/video2x/models/rife/rife-v2.4 \ + AppDir/usr/share/video2x/models/rife/rife-v3.0 \ + AppDir/usr/share/video2x/models/rife/rife-v3.1 + curl -Lo /usr/local/bin/linuxdeploy \ + https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage + chmod +x /usr/local/bin/linuxdeploy + LD_LIBRARY_PATH=AppDir/usr/lib linuxdeploy \ + --appdir AppDir \ + --executable AppDir/usr/bin/video2x \ + --exclude-library "libvulkan.so.1" \ + --desktop-file packaging/appimage/video2x.desktop \ + --icon-file packaging/appimage/video2x.png \ + --output appimage + [unix] [group('misc')] clean: diff --git a/packaging/appimage/video2x.desktop b/packaging/appimage/video2x.desktop new file mode 100644 index 000000000..439449523 --- /dev/null +++ b/packaging/appimage/video2x.desktop @@ -0,0 +1,10 @@ +[Desktop Entry] +Name=Video2X +Comment=A machine learning-based video super resolution and frame interpolation framework +TryExec=video2x +Exec=video2x +Icon=video2x +Type=Application +Terminal=true +Categories=AudioVideo;Video;Qt + diff --git a/packaging/appimage/video2x.png b/packaging/appimage/video2x.png new file mode 100644 index 0000000000000000000000000000000000000000..f7cd40919d06c6768d9fea71edbc8c9639fa662f GIT binary patch literal 10335 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%0AWC2Pyh+czC!tK#A5KVUDr023tAAw0H8fW3Z= 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 SE!e;sNL5Kgu|&b__5T3{p#jYR literal 0 HcmV?d00001