|
| 1 | +name: Build Wheel |
| 2 | + |
| 3 | +on: [push, pull_request, workflow_dispatch] |
| 4 | + |
| 5 | +env: |
| 6 | + dav1d_version: "1.5.3" |
| 7 | + libxml2_version: "v2.15.3" |
| 8 | + nv_version: "n13.0.19.0" |
| 9 | + libmfx_version: "master" |
| 10 | + libvpx_version: "v1.16.0" |
| 11 | + glslang_version: "16.3.0" |
| 12 | + BUILD_COMMANDS: | |
| 13 | + set -e |
| 14 | + JOBS=$(nproc 2>/dev/null || sysctl -n hw.logicalcpu || echo 2) |
| 15 | + REPO_ROOT=$(pwd) |
| 16 | +
|
| 17 | + # Patch obuparse MinGW-w64 (UCRT64) |
| 18 | + if [[ "$PREFIX" == "/ucrt64" ]]; then |
| 19 | + sed -i 's|#define off_t __int64|// #define off_t __int64|g' obuparse/tools/obudump.c |
| 20 | + sed -i 's|#define fseeko _fseeki64|// #define fseeko _fseeki64|g' obuparse/tools/obudump.c |
| 21 | + sed -i 's|#define ftello _fseeki64|// #define ftello _fseeki64|g' obuparse/tools/obudump.c |
| 22 | + fi |
| 23 | +
|
| 24 | + # dav1d |
| 25 | + wget "https://code.videolan.org/videolan/dav1d/-/archive/$dav1d_version/dav1d-$dav1d_version.tar.bz2" -O - | tar xfvj - |
| 26 | + cd dav1d-"$dav1d_version" |
| 27 | + meson setup build -Dprefix="$PREFIX" -Denable_tools=false -Denable_examples=false -Denable_tests=false --default-library=static --buildtype=release --strip |
| 28 | + meson compile -C build |
| 29 | + $SUDO meson install -C build |
| 30 | + cd .. && rm -rf dav1d-"$dav1d_version" |
| 31 | +
|
| 32 | + # mfx_dispatch build (Linux/Windows only) |
| 33 | + if [[ "$EXTRA_FFMPEG_FLAGS" == *"--enable-libmfx"* ]]; then |
| 34 | + git clone -b "$libmfx_version" --depth 1 https://github.com/lu-zero/mfx_dispatch |
| 35 | + cd mfx_dispatch |
| 36 | + autoreconf -i |
| 37 | + CPPFLAGS="-O2 -s -pipe" ./configure --prefix="$PREFIX" |
| 38 | + make -j$(nproc) |
| 39 | + $SUDO make -j "$JOBS" install |
| 40 | + cd .. && rm -rf mfx_dispatch |
| 41 | + fi |
| 42 | +
|
| 43 | + # nv-codec-headers (Linux/Windows only) |
| 44 | + if [[ "$EXTRA_FFMPEG_FLAGS" == *"--enable-nvdec"* ]]; then |
| 45 | + git clone -b "$nv_version" --depth 1 https://git.videolan.org/git/ffmpeg/nv-codec-headers |
| 46 | + cd nv-codec-headers |
| 47 | + $SUDO make install PREFIX="$PREFIX" |
| 48 | + cd .. && rm -rf nv-codec-headers |
| 49 | + fi |
| 50 | +
|
| 51 | + # libxml2 |
| 52 | + git clone -b "$libxml2_version" --depth 1 https://github.com/gnome/libxml2 |
| 53 | + cd libxml2 |
| 54 | + cmake -B build -G Ninja -DLIBXML2_WITH_TESTS=OFF -DLIBXML2_WITH_HTTP=OFF -DLIBXML2_WITH_FTP=OFF -DLIBXML2_WITH_HTML=ON -DLIBXML2_WITH_C14N=ON -DLIBXML2_WITH_CATALOG=OFF -DLIBXML2_WITH_DEBUG=OFF -DLIBXML2_WITH_DOCB=ON -DLIBXML2_WITH_ICONV=OFF -DLIBXML2_WITH_ISO8859X=ON -DLIBXML2_WITH_ZLIB=ON -DLIBXML2_WITH_ICU=OFF -DLIBXML2_WITH_LZMA=OFF -DLIBXML2_WITH_LEGACY=ON -DLIBXML2_WITH_MEM_DEBUG=OFF -DLIBXML2_WITH_MODULES=ON -DLIBXML2_WITH_OUTPUT=ON -DLIBXML2_WITH_PATTERN=ON -DLIBXML2_WITH_PUSH=ON -DLIBXML2_WITH_PYTHON=OFF -DLIBXML2_WITH_READER=ON -DLIBXML2_WITH_REGEXPS=ON -DLIBXML2_WITH_RUN_DEBUG=OFF -DLIBXML2_WITH_SAX1=ON -DLIBXML2_WITH_SCHEMAS=ON -DLIBXML2_WITH_SCHEMATRON=ON -DLIBXML2_WITH_THREADS=ON -DLIBXML2_WITH_THREAD_ALLOC=OFF -DLIBXML2_WITH_TREE=ON -DLIBXML2_WITH_VALID=ON -DLIBXML2_WITH_WRITER=ON -DLIBXML2_WITH_XINCLUDE=ON -DLIBXML2_WITH_XPATH=ON -DLIBXML2_WITH_XPTR=ON -DCMAKE_C_FLAGS_RELEASE="-DIN_LIBXML" -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="$PREFIX" -DCMAKE_INSTALL_PREFIX="$PREFIX" -D BUILD_SHARED_LIBS=OFF -DLIBXML2_WITH_PROGRAMS=OFF -DCMAKE_CL_SHOWINCLUDES_PREFIX="Note: including file:" |
| 55 | + ninja -C build |
| 56 | + $SUDO ninja -C build install |
| 57 | + cd .. && rm -rf libxml2 |
| 58 | +
|
| 59 | + # libvpx |
| 60 | + git clone -b "$libvpx_version" --depth 1 https://github.com/webmproject/libvpx |
| 61 | + cd libvpx |
| 62 | + VPX_TARGET="" |
| 63 | + if [[ "$PREFIX" == "/ucrt64" ]]; then |
| 64 | + VPX_TARGET="--target=x86_64-win64-gcc" |
| 65 | + fi |
| 66 | + ./configure --prefix="$PREFIX" $VPX_TARGET --disable-examples --disable-tools --disable-docs --disable-unit-tests --enable-vp9-highbitdepth --disable-debug-libs --disable-shared --as=nasm --enable-runtime-cpu-detect --disable-debug --disable-vp8 --disable-vp9-encoder --disable-postproc --disable-webm-io --disable-libyuv |
| 67 | + make -j "$JOBS" |
| 68 | + $SUDO make -j "$JOBS" install |
| 69 | + cd .. && rm -rf libvpx |
| 70 | +
|
| 71 | + # glslang |
| 72 | + git clone -b "$glslang_version" --depth 1 https://github.com/KhronosGroup/glslang |
| 73 | + cd glslang |
| 74 | + python3 ./update_glslang_sources.py |
| 75 | + cmake -B build -G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX="$PREFIX" -DBUILD_SHARED_LIBS=OFF -DENABLE_OPT=OFF -DENABLE_HLSL=OFF -DENABLE_SPIRV=ON -DENABLE_GLSLANG_BINARIES=ON -DGLSLANG_TESTS=OFF |
| 76 | + ninja -C build |
| 77 | + $SUDO ninja -C build install |
| 78 | + cd .. && rm -rf glslang |
| 79 | +
|
| 80 | + # FFmpeg |
| 81 | + cd $REPO_ROOT/FFmpeg |
| 82 | + ./configure --prefix="$PREFIX" --disable-muxers --disable-avdevice --disable-encoders --disable-filters --disable-devices --disable-network --enable-libdav1d --enable-zlib --enable-libxml2 --enable-libvpx --disable-programs --disable-doc --disable-debug --enable-gpl --enable-pic --disable-nvenc --enable-hwaccel=ffv1_vulkan --disable-bzlib --disable-iconv --disable-lzma --extra-cflags="-fPIC" --extra-ldflags="-fPIC" $EXTRA_FFMPEG_FLAGS || { |
| 83 | + echo "=====================================================================" |
| 84 | + echo "❌ FFmpeg configure FAILED! Dumping ffbuild/config.log..." |
| 85 | + echo "=====================================================================" |
| 86 | + cat ffbuild/config.log |
| 87 | + echo "=====================================================================" |
| 88 | + exit 1 |
| 89 | + } |
| 90 | +
|
| 91 | + make -j "$JOBS" |
| 92 | + $SUDO make -j "$JOBS" install |
| 93 | + cd .. |
| 94 | +
|
| 95 | +jobs: |
| 96 | + build-non-windows-wheel: |
| 97 | + runs-on: ${{ matrix.os }} |
| 98 | + |
| 99 | + strategy: |
| 100 | + matrix: |
| 101 | + include: |
| 102 | + - os: ubuntu-latest |
| 103 | + arch: linux_x86_64 |
| 104 | + - os: ubuntu-24.04-arm |
| 105 | + arch: linux_aarch64 |
| 106 | + - os: macos-15-intel |
| 107 | + arch: macosx_x86_64 |
| 108 | + - os: macos-15 |
| 109 | + arch: macosx_arm64 |
| 110 | + |
| 111 | + steps: |
| 112 | + - name: Checkout |
| 113 | + uses: actions/checkout@v7 |
| 114 | + with: |
| 115 | + fetch-depth: 0 |
| 116 | + submodules: true |
| 117 | + |
| 118 | + - uses: pypa/cibuildwheel@v4.1.0 |
| 119 | + env: |
| 120 | + CIBW_BUILD: cp314-* |
| 121 | + CIBW_BUILD_FRONTEND: uv |
| 122 | + CIBW_ENVIRONMENT: > |
| 123 | + dav1d_version=${{ env.dav1d_version }} |
| 124 | + libxml2_version=${{ env.libxml2_version }} |
| 125 | + nv_version=${{ env.nv_version }} |
| 126 | + libmfx_version=${{ env.libmfx_version }} |
| 127 | + libvpx_version=${{ env.libvpx_version }} |
| 128 | + glslang_version=${{ env.glslang_version }} |
| 129 | + PKG_CONFIG_PATH=/usr/lib/pkgconfig:/usr/local/lib/pkgconfig:/usr/lib64/pkgconfig |
| 130 | + CMAKE_ARGS="-DZLIB_USE_STATIC_LIBS=OFF -DCMAKE_POSITION_INDEPENDENT_CODE=ON -DCMAKE_C_FLAGS=-fPIC -DCMAKE_CXX_FLAGS=-fPIC -DCMAKE_MODULE_LINKER_FLAGS=-Wl,-Bsymbolic" |
| 131 | + CIBW_ENVIRONMENT_MACOS: > |
| 132 | + MACOSX_DEPLOYMENT_TARGET=15 |
| 133 | + CMAKE_ARGS="-DZLIB_USE_STATIC_LIBS=OFF" |
| 134 | + CIBW_BEFORE_ALL_LINUX: | |
| 135 | + set -e |
| 136 | + if command -v dnf >/dev/null 2>&1; then |
| 137 | + dnf install -y epel-release dnf-plugins-core |
| 138 | + dnf -y install wget curl git make gcc gcc-c++ cmake ninja-build nasm zlib-devel pkgconf-pkg-config diffutils python3-pip vulkan-headers vulkan-loader-devel autoconf automake libtool |
| 139 | + else |
| 140 | + apk add --no-cache wget curl git make gcc g++ cmake ninja nasm zlib-dev pkgconfig diffutils python3 py3-pip vulkan-headers vulkan-loader-dev autoconf automake libtool make |
| 141 | + fi && |
| 142 | + pip3 install meson |
| 143 | + ARCH=$(uname -m) |
| 144 | + if [[ "$ARCH" == "x86_64" ]]; then |
| 145 | + export PREFIX=/usr SUDO="" EXTRA_FFMPEG_FLAGS="--enable-cuvid --enable-nvdec --enable-libmfx" |
| 146 | + else |
| 147 | + export PREFIX=/usr SUDO="" EXTRA_FFMPEG_FLAGS="--enable-cuvid --enable-nvdec" |
| 148 | + fi |
| 149 | + ${{ env.BUILD_COMMANDS }} |
| 150 | + CIBW_BEFORE_ALL_MACOS: | |
| 151 | + brew install cmake meson nasm ninja pkg-config zlib wget vulkan-headers vulkan-loader autoconf automake libtool |
| 152 | + export PREFIX=/usr/local SUDO="sudo" EXTRA_FFMPEG_FLAGS="--disable-videotoolbox --disable-audiotoolbox" |
| 153 | + ${{ env.BUILD_COMMANDS }} |
| 154 | + with: |
| 155 | + output-dir: dist |
| 156 | + extras: uv |
| 157 | + |
| 158 | + - name: Test macOS Wheel |
| 159 | + if: runner.os == 'macOS' |
| 160 | + run: | |
| 161 | + export HOMEBREW_NO_REQUIRE_TAP_TRUST=1 |
| 162 | + brew install vapoursynth |
| 163 | + BREW_PREFIX=$(brew --prefix) |
| 164 | +
|
| 165 | + python3 -m venv test_env |
| 166 | + source test_env/bin/activate |
| 167 | +
|
| 168 | + export LIBRARY_PATH="$BREW_PREFIX/lib:$LIBRARY_PATH" |
| 169 | + export PKG_CONFIG_PATH="$BREW_PREFIX/lib/pkgconfig:$PKG_CONFIG_PATH" |
| 170 | + export DYLD_FALLBACK_LIBRARY_PATH="$BREW_PREFIX/lib:$DYLD_FALLBACK_LIBRARY_PATH" |
| 171 | +
|
| 172 | + pip install --upgrade pip |
| 173 | + pip install vapoursynth |
| 174 | + pip install dist/*macosx*.whl |
| 175 | +
|
| 176 | + python3 -c "import vapoursynth, os; core = vapoursynth.core; plugins = [p.name for p in core.plugins()]; print('Successfully loaded plugins:', plugins); p_dir = os.path.join(os.path.dirname(vapoursynth.__file__), 'plugins'); print('Contents of plugins directory:', os.listdir(p_dir) if os.path.exists(p_dir) else 'DIR NOT FOUND'); assert any('lsmash' in p.lower() for p in plugins), 'lsmashsource plugin failed to autoload!'" |
| 177 | +
|
| 178 | + #- name: Test macOS Wheel |
| 179 | + # if: runner.os == 'macOS' |
| 180 | + # run: | |
| 181 | + # export HOMEBREW_NO_REQUIRE_TAP_TRUST=1 |
| 182 | + # brew install vapoursynth |
| 183 | + # BREW_PREFIX=$(brew --prefix) |
| 184 | + # |
| 185 | + # python3 -m venv test_env |
| 186 | + # source test_env/bin/activate |
| 187 | + # |
| 188 | + # export LIBRARY_PATH="$BREW_PREFIX/lib:$LIBRARY_PATH" |
| 189 | + # export PKG_CONFIG_PATH="$BREW_PREFIX/lib/pkgconfig:$PKG_CONFIG_PATH" |
| 190 | + # export DYLD_FALLBACK_LIBRARY_PATH="$BREW_PREFIX/lib:$DYLD_FALLBACK_LIBRARY_PATH" |
| 191 | + # |
| 192 | + # pip install --upgrade pip |
| 193 | + # pip install vapoursynth |
| 194 | + # pip install dist/*macosx*.whl |
| 195 | + # |
| 196 | + # echo "Locating installed plugin..." |
| 197 | + # # Use Python to find the exact path pip installed the .so file to |
| 198 | + # PLUGIN_PATH=$(python3 -c "import vapoursynth, os; print(os.path.join(os.path.dirname(vapoursynth.__file__), 'plugins', 'liblsmashsource.so'))") |
| 199 | + # echo "Plugin located at: $PLUGIN_PATH" |
| 200 | + # |
| 201 | + # echo "--- Checking dynamic dependencies (otool) ---" |
| 202 | + # # This shows what the plugin THINKS it needs |
| 203 | + # otool -L "$PLUGIN_PATH" |
| 204 | + # |
| 205 | + # echo "--- Forcing macOS dyld to load the plugin (ctypes) ---" |
| 206 | + # # This will intentionally crash and print the EXACT missing library or architecture error |
| 207 | + # python3 -c "import ctypes; ctypes.CDLL('$PLUGIN_PATH')" |
| 208 | + |
| 209 | + - name: Test Linux Wheel |
| 210 | + if: runner.os == 'Linux' |
| 211 | + run: | |
| 212 | + python3 -m venv test_env |
| 213 | + source test_env/bin/activate |
| 214 | +
|
| 215 | + pip install --upgrade pip |
| 216 | + pip install vapoursynth |
| 217 | +
|
| 218 | + pip install dist/*manylinux*.whl |
| 219 | +
|
| 220 | + echo "Testing VapourSynth Autoloading..." |
| 221 | + python3 -c "import vapoursynth; core = vapoursynth.core; plugins = [p.name for p in core.plugins()]; print('Successfully loaded plugins:', plugins); assert any('lsmash' in p.lower() for p in plugins), 'Plugin failed to autoload!'; print('✅ SUCCESS: Plugin autoloaded correctly!')" |
| 222 | +
|
| 223 | + - uses: actions/upload-artifact@v7.0.1 |
| 224 | + with: |
| 225 | + name: lsmashsource-${{ matrix.arch }} |
| 226 | + path: dist |
| 227 | + |
| 228 | + build-windows-wheel: |
| 229 | + runs-on: windows-latest |
| 230 | + defaults: |
| 231 | + run: |
| 232 | + shell: msys2 {0} |
| 233 | + steps: |
| 234 | + - uses: actions/checkout@v7 |
| 235 | + with: |
| 236 | + fetch-depth: 0 |
| 237 | + submodules: true |
| 238 | + - uses: msys2/setup-msys2@v2.32.0 |
| 239 | + with: |
| 240 | + msystem: UCRT64 |
| 241 | + update: true |
| 242 | + install: >- |
| 243 | + mingw-w64-ucrt-x86_64-cmake |
| 244 | + mingw-w64-ucrt-x86_64-gcc |
| 245 | + mingw-w64-ucrt-x86_64-meson |
| 246 | + mingw-w64-ucrt-x86_64-ninja |
| 247 | + mingw-w64-ucrt-x86_64-nasm |
| 248 | + mingw-w64-ucrt-x86_64-pkgconf |
| 249 | + mingw-w64-ucrt-x86_64-zlib |
| 250 | + mingw-w64-ucrt-x86_64-vulkan-headers |
| 251 | + mingw-w64-ucrt-x86_64-vulkan-loader |
| 252 | + mingw-w64-ucrt-x86_64-glslang |
| 253 | + mingw-w64-ucrt-x86_64-autotools |
| 254 | + mingw-w64-ucrt-x86_64-python |
| 255 | + mingw-w64-ucrt-x86_64-python-pip |
| 256 | + mingw-w64-ucrt-x86_64-python-wheel |
| 257 | + git |
| 258 | + make |
| 259 | + wget |
| 260 | + diffutils |
| 261 | +
|
| 262 | + - name: Build Dependencies and Plugin |
| 263 | + run: | |
| 264 | + export PREFIX=/ucrt64 SUDO="" EXTRA_FFMPEG_FLAGS="--enable-cuvid --enable-nvdec --enable-libmfx --enable-w32threads --pkg-config-flags=-static" |
| 265 | + ${{ env.BUILD_COMMANDS }} |
| 266 | +
|
| 267 | + python -m pip install build scikit-build-core --break-system-packages |
| 268 | + export LDFLAGS="-static-libgcc -static-libstdc++ -static" |
| 269 | + python -m build --outdir dist |
| 270 | +
|
| 271 | + - name: Test Windows Wheel |
| 272 | + run: | |
| 273 | + echo "Creating isolated Python virtual environment..." |
| 274 | + python -m venv test_env |
| 275 | + source test_env/bin/activate |
| 276 | +
|
| 277 | + echo "Installing VapourSynth via pip..." |
| 278 | + pip install --upgrade pip |
| 279 | + pip install vapoursynth |
| 280 | +
|
| 281 | + echo "Installing the built wheel for testing..." |
| 282 | + pip install dist/*ucrt_gnu.whl |
| 283 | +
|
| 284 | + echo "Testing VapourSynth Autoloading on Windows..." |
| 285 | + python -c "import vapoursynth; core = vapoursynth.core; plugins = [p.name for p in core.plugins()]; print('Successfully loaded plugins:', plugins); assert any('lsmash' in p.lower() for p in plugins), 'Plugin failed to autoload!'; print('SUCCESS: Plugin autoloaded correctly!')" |
| 286 | +
|
| 287 | + - name: Retag Wheel for Distribution |
| 288 | + run: | |
| 289 | + echo "Test passed! Retagging wheel to win_amd64 for standard Windows users..." |
| 290 | + python -m wheel tags --platform-tag=win_amd64 --remove dist/*.whl |
| 291 | +
|
| 292 | + - uses: actions/upload-artifact@v7.0.1 |
| 293 | + with: |
| 294 | + name: lsmashsource-sdist |
| 295 | + path: dist/*.tar.gz |
| 296 | + |
| 297 | + - uses: actions/upload-artifact@v7.0.1 |
| 298 | + with: |
| 299 | + name: lsmashsource-win_amd64 |
| 300 | + path: dist/*.whl |
| 301 | + |
| 302 | + publish: |
| 303 | + permissions: |
| 304 | + id-token: write |
| 305 | + needs: [build-non-windows-wheel, build-windows-wheel] |
| 306 | + if: startsWith(github.ref, 'refs/tags/') |
| 307 | + runs-on: ubuntu-latest |
| 308 | + |
| 309 | + steps: |
| 310 | + - uses: actions/download-artifact@v8.0.1 |
| 311 | + with: |
| 312 | + path: dist |
| 313 | + merge-multiple: true |
| 314 | + |
| 315 | + - uses: pypa/gh-action-pypi-publish@release/v1 |
0 commit comments