name: build-linux # Builds a single self-contained libmpv.so for Linux (x86_64) from mpv source # pinned to a release tag. Every video dependency is built static and linked # into the one .so; glibc/pthread/dl/m, the system zlib and the system audio # stack (PipeWire / PulseAudio / ALSA) stay external, mirroring CoreAudio # (macOS) and WASAPI (Windows), so the OS audio is left dynamic and # everything else is self contained. # # Linux is the easiest of the three platforms: a single native build on an # ubuntu runner, no cross-compile, no lipo. The only Linux-specific work is the # font stack: libass (a hard mpv dependency) needs fontconfig (-> expat) where # macOS/Windows use CoreText/DirectWrite. # # Pinned to the mpv tag in ci/versions.env - the version whose client API # (131077) the jlibmpv JNA bindings are validated against. Bump MPV_REF (and # the dependency pins) there for a libmpv update. The build recipe # (dependency versions, static flags) lives in ci/build-libmpv-linux.sh. # # Triggers: pull requests (all three build workflows act as the PR check), # manual workflow_dispatch, and workflow_call from release.yml on tag push. # A push to main builds nothing on its own. on: pull_request: workflow_dispatch: workflow_call: # A called (reusable) workflow only exposes top-level `workflow_call` # outputs to the caller - job outputs are not. release.yml needs the # mpv version to name the release assets, so expose it here. outputs: version: description: mpv version the built artifact was compiled from value: ${{ jobs.linux.outputs.version }} env: TARGET: x86_64-linux jobs: linux: runs-on: ubuntu-24.04 outputs: artifact-name: ${{ steps.artifact.outputs.name }} version: ${{ steps.artifact.outputs.version }} env: CCACHE_BASEDIR: ${{ github.workspace }} CCACHE_DIR: ${{ github.workspace }}/.ccache CCACHE_MAXSIZE: 500M steps: - name: Check out mpv-natives (build scripts) uses: actions/checkout@v4 with: fetch-depth: 1 - name: Load pinned versions id: versions run: | source ci/versions.env echo "mpv_ref=$MPV_REF" >> "$GITHUB_OUTPUT" - name: Check out mpv (pinned tag) uses: actions/checkout@v4 with: repository: mpv-player/mpv ref: ${{ steps.versions.outputs.mpv_ref }} path: mpv fetch-depth: 1 - name: Get time id: get_time run: echo "timestamp=$(date +%s%N)" >> $GITHUB_OUTPUT - name: Restore ccache uses: actions/cache/restore@v4 with: path: ${{ env.CCACHE_DIR }} key: ${{ env.TARGET }}-${{ steps.get_time.outputs.timestamp }} restore-keys: ${{ env.TARGET }}- - name: Install dependencies run: | sudo apt-get update sudo apt-get install --no-install-recommends -y \ ccache nasm ninja-build pkgconf cmake \ libasound2-dev libpulse-dev libpipewire-0.3-dev python3 -m pip install meson # Run the vendored build script from inside the mpv source tree, so the # native build writes linux_prefix/ and the meson build next to mpv's # meson.build and produces the self-contained .so in mpv/artifact/. - name: Build self-contained libmpv working-directory: mpv run: bash "${{ github.workspace }}/ci/build-libmpv-linux.sh" - name: Print meson log on failure if: failure() run: cat mpv/linux_build/meson-logs/meson-log.txt - name: Collect artifact run: | mkdir -p artifact-libmpv cp -pv mpv/artifact/libmpv.so artifact-libmpv/ echo "=== contents ===" ls -l artifact-libmpv # Verify the artifact is self-contained and portable: # (1) ldd shows only system libs - and among them libasound.so.2, # because audio is left to the OS stack (CoreAudio/WASAPI model), # (2) no .debug sections remain (strip worked, artifact stays small). # fontconfig bakes its build prefix into the binary, but that is benign: # with no config file at that path it falls back to a built-in config # that scans /usr/share/fonts, so we do NOT fail on those strings. - name: Verify artifact (ldd, size, alsa is a system lib) run: | cd artifact-libmpv echo "=== dynamic deps (system libs only) ===" ldd libmpv.so echo "=== debug sections (expect 0) ===" readelf -S libmpv.so | grep -c '\.debug' || true echo "=== size ===" du -h libmpv.so echo "=== system audio libs present (pipewire/pulse/alsa, not vendored) ===" if ldd libmpv.so | grep -Eq 'libpipewire-0\.3|libpulse\.so|libasound\.so'; then echo "OK: at least one system audio lib present, as intended" else echo "ERROR: libmpv.so links no audio backend (no sound?)" exit 1 fi - name: Checksums run: | cd artifact-libmpv sha256sum libmpv.so > checksums.txt cat checksums.txt - name: Artifact name id: artifact run: | VER=$(cat mpv/MPV_VERSION | tr -d '[:space:]') # Intermediate artifact is a per-platform directory (zipped by # upload-artifact) containing libmpv.so + checksums.txt. release.yml # downloads it and re-uploads the bare .so as the final release asset # named -.so. echo "name=mpv-natives-linux-x86_64" >> "$GITHUB_OUTPUT" echo "version=$VER" >> "$GITHUB_OUTPUT" - name: Upload artifact uses: actions/upload-artifact@v4 with: name: ${{ steps.artifact.outputs.name }} path: artifact-libmpv - name: Save ccache uses: actions/cache/save@v4 if: always() with: path: ${{ env.CCACHE_DIR }} key: ${{ env.TARGET }}-${{ steps.get_time.outputs.timestamp }}