| name: Build & Distribute (WebAssembly) | |
| on: | |
| workflow_call: | |
| inputs: | |
| tag: | |
| description: "Type a release tag or 'nightly' for a nightly build" | |
| required: true | |
| type: string | |
| jobs: | |
| build: | |
| strategy: | |
| matrix: | |
| variant: | |
| - config: "full" | |
| threaded: true | |
| - config: "full" | |
| threaded: false | |
| - config: "lite" | |
| threaded: false | |
| name: Build for WebAssembly (${{ matrix.variant.config }}, ${{ matrix.variant.threaded && 'threaded' || 'single-threaded' }}) | |
| runs-on: "ubuntu-latest" | |
| env: | |
| DEBIAN_FRONTEND: noninteractive | |
| EMSDK_VERSION: 4.0.12 | |
| steps: | |
| - name: Print environment | |
| run: | | |
| echo "Building ${{ inputs.tag }}" | |
| echo "Running for WebAssembly with variant: ${{ matrix.variant.config }}, threaded: ${{ matrix.variant.threaded }}" | |
| echo "CCACHE_DIR: $CCACHE_DIR" | |
| - name: Update package list | |
| run: sudo apt update | |
| - name: Install build tools | |
| run: | | |
| sudo apt install -y --no-install-recommends \ | |
| build-essential pkg-config g++ git cmake yasm python3 autotools-dev automake autoconf libtool | |
| - name: Install GPAC build dependencies | |
| run: | | |
| sudo apt install -y --no-install-recommends \ | |
| zlib1g-dev libfreetype6-dev libpng-dev libmad0-dev libfaad-dev libogg-dev libvorbis-dev libtheora-dev \ | |
| liba52-0.7.4-dev libavcodec-dev libavformat-dev libavutil-dev libswscale-dev libavdevice-dev libnghttp2-dev \ | |
| libopenjp2-7-dev libcaca-dev libxv-dev x11proto-video-dev libgl1-mesa-dev libglu1-mesa-dev x11proto-gl-dev \ | |
| libxvidcore-dev libssl-dev libjack-jackd2-dev libasound2-dev libpulse-dev libsdl2-dev dvb-apps mesa-utils \ | |
| libcurl4-openssl-dev libjpeg62-dev | |
| - name: Get Emscripten source | |
| uses: actions/checkout@v4 | |
| with: | |
| repository: emscripten-core/emsdk | |
| fetch-depth: 1 | |
| path: emsdk | |
| - name: Set up Emscripten | |
| working-directory: emsdk | |
| run: | | |
| ./emsdk install ${{ env.EMSDK_VERSION }} | |
| ./emsdk activate ${{ env.EMSDK_VERSION }} | |
| # Update environment variables | |
| echo "PATH=$PWD:$PWD/upstream/emscripten:$PATH" >> $GITHUB_ENV | |
| echo "EMSDK=$PWD" >> $GITHUB_ENV | |
| - name: Get GPAC source | |
| uses: actions/checkout@v4 | |
| with: | |
| repository: gpac/gpac | |
| fetch-depth: 0 | |
| path: gpac_public | |
| ref: ${{ inputs.tag == 'nightly' && 'master' || inputs.tag }} | |
| - name: Get manual dependencies | |
| uses: actions/checkout@v4 | |
| if: ${{ matrix.variant.config != 'lite' }} | |
| with: | |
| repository: gpac/deps_wasm | |
| fetch-depth: 1 | |
| path: deps_wasm | |
| submodules: true | |
| - name: Get latest commit hash for manual dependencies | |
| id: get-commit | |
| if: ${{ matrix.variant.config != 'lite' }} | |
| working-directory: deps_wasm | |
| run: echo "hash=$(git rev-parse HEAD)" >> $GITHUB_OUTPUT | |
| - name: Cache dependencies | |
| id: cache-deps | |
| if: ${{ matrix.variant.config != 'lite' }} | |
| uses: actions/cache@v4 | |
| with: | |
| path: deps_wasm/wasm${{ matrix.variant.threaded && '_thread' || '' }} | |
| key: wasm-deps-${{ matrix.variant.threaded && 'threaded' || 'single' }}-${{ steps.get-commit.outputs.hash }} | |
| - name: Cache Emscripten Build | |
| uses: actions/cache@v4 | |
| with: | |
| path: ${{ github.workspace }}/emsdk/upstream/emscripten/cache | |
| key: emscripten-${{ env.EMSDK_VERSION }}-${{ matrix.variant.config }}-${{ matrix.variant.threaded && 'threaded' || 'single' }}-${{ steps.get-commit.outputs.hash }} | |
| - name: Build manual dependencies | |
| if: ${{ matrix.variant.config != 'lite' && !steps.cache-deps.outputs.cache-hit }} | |
| working-directory: deps_wasm | |
| run: ./wasm_extra_libs.sh ${{ matrix.variant.threaded && '--enable-threading' || '' }} | |
| - name: Set PKG_CONFIG_PATH | |
| if: ${{ matrix.variant.config != 'lite' }} | |
| working-directory: deps_wasm | |
| run: | | |
| # Update PKG_CONFIG_PATH | |
| if [ "${{ matrix.variant.threaded }}" = "true" ]; then | |
| echo "PKG_CONFIG_PATH=$PWD/wasm_thread/lib/pkgconfig" >> $GITHUB_ENV | |
| else | |
| echo "PKG_CONFIG_PATH=$PWD/wasm/lib/pkgconfig" >> $GITHUB_ENV | |
| fi | |
| - name: Build GPAC | |
| working-directory: gpac_public | |
| run: | | |
| if [ "${{ matrix.variant.config }}" = "lite" ]; then | |
| ./configure --emscripten --extra-cflags="-Wno-pointer-sign -Wno-implicit-const-int-float-conversion" --em-opt=z \ | |
| --isomedia-only --disable-threads --disable-isom-dump \ | |
| --enable-reframer --enable-mp4mx --enable-mp4dmx --enable-fout --enable-webcodec | |
| else | |
| if [ "${{ matrix.variant.threaded }}" = "true" ]; then | |
| ./configure --emscripten --extra-cflags="-Wno-pointer-sign -Wno-implicit-const-int-float-conversion" | |
| else | |
| ./configure --emscripten --disable-threads --extra-cflags="-Wno-pointer-sign -Wno-implicit-const-int-float-conversion" | |
| fi | |
| fi | |
| make -j$(nproc) | |
| - name: Prepare output directory | |
| working-directory: gpac_public/bin/gcc | |
| run: | | |
| out="${{ github.workspace }}/output" | |
| mkdir -p $out | |
| if [ "${{ matrix.variant.config }}" = "full" ]; then | |
| if [ "${{ matrix.variant.threaded }}" = "true" ]; then | |
| cp gpac.js gpac.wasm $out | |
| else | |
| mv gpac.js gpac.st.js | |
| mv gpac.wasm gpac.st.wasm | |
| sed -i 's/gpac\.wasm/gpac.st.wasm/g' gpac.st.js | |
| cp gpac.st.js gpac.st.wasm $out | |
| fi | |
| elif [ "${{ matrix.variant.config }}" = "lite" ]; then | |
| mv gpac.js gpac.lite.js | |
| mv gpac.wasm gpac.lite.wasm | |
| sed -i 's/gpac\.wasm/gpac.lite.wasm/g' gpac.lite.js | |
| cp gpac.lite.js gpac.lite.wasm $out | |
| fi | |
| - name: Upload artifacts | |
| uses: actions/upload-artifact@v4 | |
| env: | |
| DIST_TYPE: ${{ inputs.tag == 'nightly' && 'nightly-latest' || format('main-{0}', inputs.tag) }} | |
| with: | |
| name: wasm-${{ env.DIST_TYPE }}@${{ matrix.variant.config }}-${{ matrix.variant.threaded && 'threaded' || 'single' }} | |
| path: output/* | |
| retention-days: 1 | |
| publish: | |
| needs: build | |
| runs-on: ubuntu-latest | |
| env: | |
| AWS_ACCESS_KEY_ID: ${{ secrets.DIST_ACCESS_KEY_ID }} | |
| AWS_SECRET_ACCESS_KEY: ${{ secrets.DIST_SECRET_ACCESS_KEY }} | |
| steps: | |
| - name: Download artifacts | |
| uses: actions/download-artifact@v4 | |
| with: | |
| pattern: wasm-${{ inputs.tag == 'nightly' && 'nightly-latest' || format('main-{0}', inputs.tag) }}@*-* | |
| path: artifacts | |
| - name: Publish to S3 (bash) | |
| shell: bash | |
| run: | | |
| set -euxo pipefail | |
| shopt -s nullglob | |
| root="artifacts" | |
| bucket="${{ secrets.DIST_S3_BUCKET }}" | |
| extras="--endpoint-url ${{ secrets.DIST_S3_ENDPOINT }}" | |
| echo "Uploading artifacts from $root to bucket $bucket" | |
| for dir in "$root"/wasm-*; do | |
| [ -d "$dir" ] || continue | |
| slug="$(basename "$dir")" | |
| component_part="${slug#wasm-}" | |
| component_part="${component_part%%@*}" | |
| if [ "$component_part" = "nightly-latest" ]; then | |
| tag="$(date -u +%Y%m%d)" | |
| prefix="wasm/nightly/$tag" | |
| elif [[ "$component_part" =~ ^main-(.+)$ ]]; then | |
| tag="${BASH_REMATCH[1]}" | |
| prefix="wasm/main/$tag" | |
| else | |
| echo "Skipping unrecognized component part: $component_part" >&2 | |
| continue | |
| fi | |
| echo "Processing $slug -> prefix $prefix" | |
| for f in "$dir"/*; do | |
| [ -f "$f" ] || continue | |
| dest="s3://$bucket/$prefix/$(basename "$f")" | |
| echo "Uploading $f -> $dest" | |
| aws s3 cp "$f" "$dest" $extras | |
| done | |
| done | |
| if [ "${{ inputs.tag }}" = "nightly" ]; then | |
| echo "Updating 'latest' pointers" | |
| for dir in "$root"/wasm-nightly-latest@*-*; do | |
| [ -d "$dir" ] || continue | |
| prefix="wasm" | |
| slug="$(basename "$dir")" | |
| for f in "$dir"/*; do | |
| [ -f "$f" ] || continue | |
| dest="s3://$bucket/$prefix/$(basename "$f")" | |
| echo "Uploading $f -> $dest" | |
| aws s3 cp "$f" "$dest" $extras | |
| done | |
| done | |
| fi |