Merge pull request #2129 from shimat/renovate/skiasharp #1381
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Wasm | |
| on: | |
| pull_request: | |
| types: [synchronize, opened] | |
| push: | |
| branches: | |
| - main | |
| env: | |
| DEBIAN_FRONTEND: noninteractive | |
| OPENCV_VERSION: 5.0.0 | |
| # Must match the Emscripten version bundled with the .NET wasm SDK below (currently | |
| # Microsoft.NET.Runtime.Emscripten.3.1.56.Sdk), since OpenCvSharpExtern.a built here gets | |
| # statically linked by that SDK's own emcc/wasm-ld later - mixing Emscripten versions across | |
| # that link boundary is unsupported and has already caused one silent bug (#2039, a wasm-opt | |
| # feature-flag mismatch) plus a suspected second one (a setjmp/longjmp hang; see #2043). | |
| EM_VERSION: 3.1.56 | |
| EM_CACHE_FOLDER: 'emsdk-cache' | |
| # Bump this whenever the OpenCV cmake flags below change, to bust the OpenCV build cache. | |
| OPENCV_CACHE_VERSION: 3 | |
| jobs: | |
| build: | |
| name: Wasm | |
| runs-on: ubuntu-24.04 | |
| steps: | |
| - uses: actions/checkout@v7 | |
| with: | |
| fetch-depth: 1 | |
| persist-credentials: false | |
| submodules: recursive | |
| - name: Resolve OpenCV revisions | |
| id: opencv-revisions | |
| run: | | |
| echo "opencv=$(git rev-parse HEAD:opencv)" >> "${GITHUB_OUTPUT}" | |
| echo "opencv_contrib=$(git rev-parse HEAD:opencv_contrib)" >> "${GITHUB_OUTPUT}" | |
| - name: Install dependencies | |
| run: | | |
| current_path=$(pwd) | |
| sudo apt-get update -y | |
| sudo apt-get install -y --no-install-recommends \ | |
| apt-transport-https \ | |
| software-properties-common \ | |
| wget \ | |
| unzip \ | |
| ca-certificates \ | |
| g++ \ | |
| make \ | |
| cmake \ | |
| libtbb-dev \ | |
| libatlas-base-dev \ | |
| libgtk-3-dev \ | |
| libavcodec-dev \ | |
| libavformat-dev \ | |
| libswscale-dev \ | |
| libdc1394-dev \ | |
| libxine2-dev \ | |
| libv4l-dev \ | |
| libtheora-dev \ | |
| libvorbis-dev \ | |
| libxvidcore-dev \ | |
| libopencore-amrnb-dev \ | |
| libopencore-amrwb-dev \ | |
| x264 \ | |
| libtesseract-dev | |
| - name: Restore OpenCV cache | |
| id: opencv-cache | |
| uses: actions/cache/restore@v6 | |
| with: | |
| path: | | |
| ${{ github.workspace }}/opencv_wasm/include | |
| ${{ github.workspace }}/opencv_wasm/lib | |
| ${{ github.workspace }}/opencv_wasm/libopencv.o | |
| key: opencv-${{ steps.opencv-revisions.outputs.opencv }}-${{ steps.opencv-revisions.outputs.opencv_contrib }}-wasm-${{ env.EM_VERSION }}-v${{ env.OPENCV_CACHE_VERSION }} | |
| - name: Setup Emscripten cache | |
| id: cache-system-libraries | |
| uses: actions/cache@v6 | |
| with: | |
| path: ${{env.EM_CACHE_FOLDER}} | |
| key: ${{env.EM_VERSION}}-${{ runner.os }} | |
| - uses: mymindstorm/setup-emsdk@v16 | |
| with: | |
| version: ${{env.EM_VERSION}} | |
| actions-cache-folder: ${{env.EM_CACHE_FOLDER}} | |
| - name: Build OpenCV | |
| if: steps.opencv-cache.outputs.cache-hit != 'true' | |
| run: | | |
| emcmake cmake \ | |
| -S opencv \ | |
| -B opencv/build \ | |
| -DCMAKE_BUILD_TYPE=Release \ | |
| -DOPENCV_EXTRA_MODULES_PATH=${GITHUB_WORKSPACE}/opencv_contrib/modules \ | |
| -DBUILD_SHARED_LIBS=OFF \ | |
| -DENABLE_CXX11=ON -DBUILD_TESTS=OFF \ | |
| -DBUILD_PERF_TESTS=OFF \ | |
| -DBUILD_DOCS=OFF \ | |
| -DBUILD_EXAMPLES=OFF \ | |
| -DBUILD_JAVA=OFF \ | |
| -DBUILD_opencv_java_bindings_generator=OFF \ | |
| -DBUILD_opencv_python_bindings_generator=OFF \ | |
| -DBUILD_opencv_python_tests=OFF \ | |
| -DBUILD_opencv_ts=OFF \ | |
| -DBUILD_opencv_js=OFF \ | |
| -DBUILD_opencv_js_bindings_generator=OFF \ | |
| -DBUILD_opencv_apps=OFF \ | |
| -DBUILD_opencv_barcode=OFF \ | |
| -DBUILD_opencv_bioinspired=OFF \ | |
| -DBUILD_opencv_ccalib=OFF \ | |
| -DBUILD_opencv_datasets=OFF \ | |
| -DBUILD_opencv_dnn_objdetect=OFF \ | |
| -DBUILD_opencv_dpm=OFF \ | |
| -DBUILD_opencv_fuzzy=OFF \ | |
| -DBUILD_opencv_gapi=OFF \ | |
| -DBUILD_opencv_intensity_transform=OFF \ | |
| -DBUILD_opencv_mcc=OFF \ | |
| -DBUILD_opencv_objc_bindings_generator=OFF \ | |
| -DBUILD_opencv_rapid=OFF \ | |
| -DBUILD_opencv_reg=OFF \ | |
| -DBUILD_opencv_stereo=ON \ | |
| -DBUILD_opencv_structured_light=OFF \ | |
| -DBUILD_opencv_surface_matching=OFF \ | |
| -DBUILD_opencv_wechat_qrcode=ON \ | |
| -DBUILD_opencv_videostab=OFF \ | |
| -DWITH_GSTREAMER=OFF \ | |
| -DWITH_EIGEN=OFF \ | |
| -DWITH_ADE=OFF \ | |
| -DOPENCV_ENABLE_NONFREE=ON \ | |
| -DCMAKE_INSTALL_PREFIX=${GITHUB_WORKSPACE}/opencv_wasm \ | |
| -DCMAKE_C_FLAGS='-s WASM=1' -DCMAKE_CXX_FLAGS='-s WASM=1' \ | |
| -DWITH_ITT=OFF \ | |
| -DWITH_JPEG=ON \ | |
| -DWITH_TIFF=ON \ | |
| -DWITH_PNG=ON \ | |
| -DWITH_IPP=OFF \ | |
| -DWITH_LAPACK=OFF \ | |
| -DWITH_OPENCL=OFF \ | |
| -DWITH_PTHREADS_PF=OFF \ | |
| -DCV_ENABLE_INTRINSICS=OFF \ | |
| -DBUILD_opencv_dnn=ON | |
| cmake --build opencv/build --parallel $(nproc) | |
| cmake --install opencv/build | |
| em++ -r -o ${GITHUB_WORKSPACE}/opencv_wasm/libopencv.o \ | |
| -Wl,--whole-archive ${GITHUB_WORKSPACE}/opencv_wasm/lib/*.a \ | |
| ${GITHUB_WORKSPACE}/opencv_wasm/lib/opencv5/3rdparty/*.a | |
| ls | |
| - name: Save OpenCV cache | |
| if: steps.opencv-cache.outputs.cache-hit != 'true' && github.event_name == 'push' && github.ref == 'refs/heads/main' | |
| uses: actions/cache/save@v6 | |
| with: | |
| path: | | |
| ${{ github.workspace }}/opencv_wasm/include | |
| ${{ github.workspace }}/opencv_wasm/lib | |
| ${{ github.workspace }}/opencv_wasm/libopencv.o | |
| key: opencv-${{ steps.opencv-revisions.outputs.opencv }}-${{ steps.opencv-revisions.outputs.opencv_contrib }}-wasm-${{ env.EM_VERSION }}-v${{ env.OPENCV_CACHE_VERSION }} | |
| - name: Build OpenCvSharpExtern | |
| run: | | |
| ls ${GITHUB_WORKSPACE}/opencv_wasm | |
| echo "-----" | |
| emcmake cmake -S src -B src/build -DCMAKE_BUILD_TYPE=Release -DOpenCV_DIR=${GITHUB_WORKSPACE}/opencv_wasm/lib/cmake/opencv5 -DWASM_LIB=${GITHUB_WORKSPACE}/opencv_wasm/libopencv.o | |
| cmake --build src/build --parallel $(nproc) | |
| ls src/build/OpenCvSharpExtern | |
| cp src/build/OpenCvSharpExtern/libOpenCvSharpExtern.a ${GITHUB_WORKSPACE}/packaging/nuget/OpenCvSharpExtern.a | |
| # Also stage it where OpenCvSharp5.runtime.wasm.props expects it (relative to the props | |
| # file's own location), so test/OpenCvSharp.Tests.Wasm can import that same .props and | |
| # link against this build directly, without a NuGet pack/restore round-trip. | |
| mkdir -p ${GITHUB_WORKSPACE}/runtimes/browser-wasm/4.0.23 | |
| cp src/build/OpenCvSharpExtern/libOpenCvSharpExtern.a ${GITHUB_WORKSPACE}/runtimes/browser-wasm/4.0.23/OpenCvSharpExtern.a | |
| - name: Install .NET | |
| uses: actions/setup-dotnet@v6 | |
| with: | |
| dotnet-version: '10.0.x' | |
| - name: Install wasm-tools workload | |
| run: dotnet workload install wasm-tools | |
| - name: Verify EM_VERSION matches the .NET wasm SDK's bundled Emscripten | |
| run: | | |
| pack_dir=$(ls -d /usr/share/dotnet/packs/Microsoft.NET.Runtime.Emscripten.*.Sdk.* 2>/dev/null | head -1) | |
| if [ -z "$pack_dir" ]; then | |
| echo "::error::Could not find an installed Microsoft.NET.Runtime.Emscripten.*.Sdk pack under /usr/share/dotnet/packs - can't verify EM_VERSION." | |
| exit 1 | |
| fi | |
| installed=$(basename "$pack_dir" | sed -E 's/Microsoft\.NET\.Runtime\.Emscripten\.([0-9]+\.[0-9]+\.[0-9]+)\.Sdk.*/\1/') | |
| echo "wasm.yml EM_VERSION: ${EM_VERSION}" | |
| echo ".NET wasm SDK's bundled Emscripten: ${installed}" | |
| if [ "$installed" != "$EM_VERSION" ]; then | |
| echo "::error::EM_VERSION (${EM_VERSION}) no longer matches the .NET wasm SDK's bundled Emscripten (${installed})."\ | |
| "OpenCvSharpExtern.a was built with the wrong toolchain version relative to the one that will"\ | |
| "statically link it later - update EM_VERSION in wasm.yml to ${installed}. See #2043 for what"\ | |
| "this class of mismatch already broke once (a setjmp/longjmp hang)." | |
| exit 1 | |
| fi | |
| - name: Create NuGet package | |
| env: | |
| BETA: "-beta" | |
| run: | | |
| yyyymmdd=`date '+%Y%m%d'` | |
| echo $yyyymmdd | |
| version="${OPENCV_VERSION}.${yyyymmdd}${BETA}" | |
| echo "Package version: $version" | |
| dotnet pack ${GITHUB_WORKSPACE}/packaging/nuget/OpenCvSharp5.runtime.wasm.csproj -o ${GITHUB_WORKSPACE}/artifacts_wasm -p:Version=$version | |
| ls ${GITHUB_WORKSPACE}/artifacts_wasm | |
| - uses: actions/upload-artifact@v7 | |
| with: | |
| name: artifacts_wasm | |
| path: artifacts_wasm | |
| - name: Check OpenCvSharpExtern package contents | |
| run: | | |
| nupkg=$(ls ${GITHUB_WORKSPACE}/artifacts_wasm/*.nupkg) | |
| echo "Inspecting $nupkg" | |
| unzip -l "$nupkg" | |
| # #2039 regression guard: the native lib must ship WITHOUT the "lib" prefix, since | |
| # NativeFileReference derives the P/Invoke module name from the file's %(Filename). | |
| unzip -p "$nupkg" runtimes/browser-wasm/4.0.23/OpenCvSharpExtern.a > /dev/null | |
| unzip -p "$nupkg" build/net8.0/OpenCvSharp5.runtime.wasm.props > /dev/null | |
| - name: Publish wasm E2E consumer test | |
| run: | | |
| dotnet publish ${GITHUB_WORKSPACE}/test/OpenCvSharp.Tests.Wasm/OpenCvSharp.Tests.Wasm.csproj -c Release -o ${GITHUB_WORKSPACE}/artifacts_wasm_e2e | |
| - name: Run wasm E2E consumer test | |
| run: | | |
| set -e | |
| npx --yes http-server ${GITHUB_WORKSPACE}/artifacts_wasm_e2e/wwwroot -p 8080 --silent & | |
| SERVER_PID=$! | |
| for i in $(seq 1 30); do | |
| if curl -sf http://127.0.0.1:8080/index.html -o /dev/null; then | |
| break | |
| fi | |
| sleep 1 | |
| done | |
| if ! curl -sf http://127.0.0.1:8080/index.html -o /dev/null; then | |
| echo "ERROR: http-server did not become ready on port 8080 within 30s" | |
| kill $SERVER_PID || true | |
| exit 1 | |
| fi | |
| mkdir -p ${RUNNER_TEMP}/wasm-e2e | |
| cp ${GITHUB_WORKSPACE}/test/OpenCvSharp.Tests.Wasm/run-e2e.mjs ${RUNNER_TEMP}/wasm-e2e/run-e2e.mjs | |
| cd ${RUNNER_TEMP}/wasm-e2e | |
| npm init -y > /dev/null 2>&1 | |
| npm install playwright > /dev/null 2>&1 | |
| npx playwright install --with-deps chromium | |
| node run-e2e.mjs http://127.0.0.1:8080 | |
| kill $SERVER_PID || true |