Linux: portable manylinux build, vcpkg for Linux, slim profile expansion #7
Workflow file for this run
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: manylinux | |
| on: | |
| pull_request: | |
| types: [synchronize, opened] | |
| push: | |
| branches: | |
| - main | |
| env: | |
| DEBIAN_FRONTEND: noninteractive | |
| OPENCV_VERSION: 4.13.0 | |
| # Bump DEPS_VERSION to invalidate the static-deps cache when build_static_deps.sh changes | |
| # in ways that are not reflected by its file hash (e.g. upstream tarball updates). | |
| DEPS_VERSION: "1" | |
| jobs: | |
| # --------------------------------------------------------------------------- | |
| # Build full libOpenCvSharpExtern.so inside manylinux_2_28. | |
| # Static deps (FFmpeg, Tesseract, Leptonica, libjpeg, libpng, libtiff, libwebp) | |
| # are built by build_static_deps.sh and cached in /opt/deps. | |
| # The resulting .so depends only on glibc / libstdc++ system libraries. | |
| # --------------------------------------------------------------------------- | |
| build_full: | |
| runs-on: ubuntu-24.04 | |
| container: | |
| image: quay.io/pypa/manylinux_2_28_x86_64 | |
| options: --user root | |
| steps: | |
| - uses: actions/checkout@v6 | |
| with: | |
| submodules: true | |
| # -- System tools -------------------------------------------------------- | |
| - name: Install system tools | |
| run: dnf install -y git zip unzip nasm yasm pkg-config ninja-build kernel-headers perl-IPC-Cmd perl-Time-Piece | |
| # -- vcpkg (image libs + Tesseract + Leptonica) -------------------------- | |
| - name: Bootstrap vcpkg | |
| run: | | |
| git clone --filter=blob:none --depth=1 https://github.com/microsoft/vcpkg.git /opt/vcpkg | |
| /opt/vcpkg/bootstrap-vcpkg.sh -disableMetrics | |
| - name: Restore vcpkg package cache | |
| id: vcpkg-cache | |
| uses: actions/cache/restore@v5 | |
| with: | |
| path: /opt/vcpkg/installed | |
| key: vcpkg-x64-linux-static-${{ hashFiles('vcpkg.json') }}-${{ hashFiles('cmake/triplets/x64-linux-static.cmake') }} | |
| - name: Install packages via vcpkg | |
| if: steps.vcpkg-cache.outputs.cache-hit != 'true' | |
| run: | | |
| /opt/vcpkg/vcpkg install \ | |
| --triplet x64-linux-static \ | |
| --overlay-triplets=${GITHUB_WORKSPACE}/cmake/triplets | |
| - name: Save vcpkg package cache | |
| if: steps.vcpkg-cache.outputs.cache-hit != 'true' && github.event_name == 'push' && github.ref == 'refs/heads/main' | |
| uses: actions/cache/save@v5 | |
| with: | |
| path: /opt/vcpkg/installed | |
| key: vcpkg-x64-linux-static-${{ hashFiles('vcpkg.json') }}-${{ hashFiles('cmake/triplets/x64-linux-static.cmake') }} | |
| # -- FFmpeg cache -------------------------------------------------------- | |
| - name: Restore FFmpeg cache | |
| id: ffmpeg-cache | |
| uses: actions/cache/restore@v5 | |
| with: | |
| path: /opt/ffmpeg | |
| key: manylinux2_28-ffmpeg-v${{ env.DEPS_VERSION }}-${{ hashFiles('docker/manylinux/build_static_deps.sh') }} | |
| - name: Build FFmpeg | |
| if: steps.ffmpeg-cache.outputs.cache-hit != 'true' | |
| run: bash docker/manylinux/build_static_deps.sh | |
| - name: Save FFmpeg cache | |
| if: steps.ffmpeg-cache.outputs.cache-hit != 'true' && github.event_name == 'push' && github.ref == 'refs/heads/main' | |
| uses: actions/cache/save@v5 | |
| with: | |
| path: /opt/ffmpeg | |
| key: manylinux2_28-ffmpeg-v${{ env.DEPS_VERSION }}-${{ hashFiles('docker/manylinux/build_static_deps.sh') }} | |
| # -- OpenCV cache -------------------------------------------------------- | |
| - name: Restore OpenCV cache (full) | |
| id: opencv-cache | |
| uses: actions/cache/restore@v5 | |
| with: | |
| path: | | |
| ${{ github.workspace }}/opencv_artifacts/include | |
| ${{ github.workspace }}/opencv_artifacts/lib | |
| key: opencv-${{ env.OPENCV_VERSION }}-manylinux2_28-full-v${{ env.DEPS_VERSION }}-${{ hashFiles('vcpkg.json') }}-${{ hashFiles('docker/manylinux/build_static_deps.sh') }} | |
| - name: Build OpenCV (full) | |
| if: steps.opencv-cache.outputs.cache-hit != 'true' | |
| run: | | |
| cmake \ | |
| -C cmake/opencv_build_options.cmake \ | |
| -S opencv \ | |
| -B opencv/build \ | |
| -D OPENCV_EXTRA_MODULES_PATH=${GITHUB_WORKSPACE}/opencv_contrib/modules \ | |
| -D CMAKE_INSTALL_PREFIX=${GITHUB_WORKSPACE}/opencv_artifacts \ | |
| -D CMAKE_TOOLCHAIN_FILE=/opt/vcpkg/scripts/buildsystems/vcpkg.cmake \ | |
| -D VCPKG_TARGET_TRIPLET=x64-linux-static \ | |
| -D CMAKE_PREFIX_PATH=/opt/ffmpeg \ | |
| -D BUILD_JPEG=OFF \ | |
| -D BUILD_PNG=OFF \ | |
| -D BUILD_TIFF=OFF \ | |
| -D BUILD_WEBP=OFF \ | |
| -D BUILD_ZLIB=OFF \ | |
| -D WITH_TBB=OFF \ | |
| -D WITH_OPENEXR=OFF \ | |
| -D WITH_JASPER=OFF \ | |
| -D WITH_GTK=OFF | |
| cmake --build opencv/build -j 3 | |
| cmake --install opencv/build | |
| - name: Save OpenCV cache (full) | |
| if: steps.opencv-cache.outputs.cache-hit != 'true' && github.event_name == 'push' && github.ref == 'refs/heads/main' | |
| uses: actions/cache/save@v5 | |
| with: | |
| path: | | |
| ${{ github.workspace }}/opencv_artifacts/include | |
| ${{ github.workspace }}/opencv_artifacts/lib | |
| key: opencv-${{ env.OPENCV_VERSION }}-manylinux2_28-full-v${{ env.DEPS_VERSION }}-${{ hashFiles('vcpkg.json') }}-${{ hashFiles('docker/manylinux/build_static_deps.sh') }} | |
| # -- OpenCvSharpExtern --------------------------------------------------- | |
| - name: Build OpenCvSharpExtern (full) | |
| run: | | |
| cmake \ | |
| -S src \ | |
| -B src/build \ | |
| -D CMAKE_BUILD_TYPE=Release \ | |
| -D CMAKE_TOOLCHAIN_FILE=/opt/vcpkg/scripts/buildsystems/vcpkg.cmake \ | |
| -D VCPKG_TARGET_TRIPLET=x64-linux-static \ | |
| -D CMAKE_PREFIX_PATH="${GITHUB_WORKSPACE}/opencv_artifacts;/opt/ffmpeg" | |
| cmake --build src/build -j | |
| cp src/build/OpenCvSharpExtern/libOpenCvSharpExtern.so ${GITHUB_WORKSPACE}/libOpenCvSharpExtern.so | |
| - name: Verify no unresolved dependencies (full) | |
| run: | | |
| echo "=== ldd output ===" | |
| ldd ${GITHUB_WORKSPACE}/libOpenCvSharpExtern.so | |
| echo "=== Checking for 'not found' ===" | |
| if ldd ${GITHUB_WORKSPACE}/libOpenCvSharpExtern.so | grep -q "not found"; then | |
| echo "ERROR: unresolved dependencies found" | |
| ldd ${GITHUB_WORKSPACE}/libOpenCvSharpExtern.so | grep "not found" | |
| exit 1 | |
| fi | |
| echo "OK: all dependencies resolved" | |
| - uses: actions/upload-artifact@v6 | |
| with: | |
| name: libOpenCvSharpExtern-full | |
| path: libOpenCvSharpExtern.so | |
| # --------------------------------------------------------------------------- | |
| # Build slim libOpenCvSharpExtern.so inside manylinux_2_28. | |
| # No external deps needed: OpenCV bundled 3rdparty provides static .a for | |
| # jpeg/png/tiff/webp/zlib internally. | |
| # --------------------------------------------------------------------------- | |
| build_slim: | |
| runs-on: ubuntu-24.04 | |
| container: | |
| image: quay.io/pypa/manylinux_2_28_x86_64 | |
| options: --user root | |
| steps: | |
| - uses: actions/checkout@v6 | |
| with: | |
| submodules: true | |
| - name: Restore OpenCV cache (slim) | |
| id: opencv-cache | |
| uses: actions/cache/restore@v5 | |
| with: | |
| path: | | |
| ${{ github.workspace }}/opencv_artifacts_slim/include | |
| ${{ github.workspace }}/opencv_artifacts_slim/lib | |
| key: opencv-${{ env.OPENCV_VERSION }}-manylinux2_28-slim | |
| - name: Build OpenCV (slim) | |
| if: steps.opencv-cache.outputs.cache-hit != 'true' | |
| run: | | |
| cmake \ | |
| -C cmake/opencv_build_options_slim.cmake \ | |
| -S opencv \ | |
| -B opencv/build \ | |
| -D CMAKE_INSTALL_PREFIX=${GITHUB_WORKSPACE}/opencv_artifacts_slim \ | |
| -D WITH_TBB=OFF | |
| cmake --build opencv/build -j 3 | |
| cmake --install opencv/build | |
| - name: Save OpenCV cache (slim) | |
| if: steps.opencv-cache.outputs.cache-hit != 'true' && github.event_name == 'push' && github.ref == 'refs/heads/main' | |
| uses: actions/cache/save@v5 | |
| with: | |
| path: | | |
| ${{ github.workspace }}/opencv_artifacts_slim/include | |
| ${{ github.workspace }}/opencv_artifacts_slim/lib | |
| key: opencv-${{ env.OPENCV_VERSION }}-manylinux2_28-slim | |
| - name: Build OpenCvSharpExtern (slim) | |
| run: | | |
| cmake \ | |
| -S src \ | |
| -B src/build-slim \ | |
| -D CMAKE_BUILD_TYPE=Release \ | |
| -D CMAKE_PREFIX_PATH=${GITHUB_WORKSPACE}/opencv_artifacts_slim \ | |
| -D NO_CONTRIB=ON \ | |
| -D NO_VIDEOIO=ON \ | |
| -D NO_HIGHGUI=ON \ | |
| -D NO_DNN=ON | |
| cmake --build src/build-slim -j | |
| cp src/build-slim/OpenCvSharpExtern/libOpenCvSharpExtern.so ${GITHUB_WORKSPACE}/libOpenCvSharpExtern-slim.so | |
| - name: Verify no unresolved dependencies (slim) | |
| run: | | |
| echo "=== ldd output ===" | |
| ldd ${GITHUB_WORKSPACE}/libOpenCvSharpExtern-slim.so | |
| echo "=== Checking for 'not found' ===" | |
| if ldd ${GITHUB_WORKSPACE}/libOpenCvSharpExtern-slim.so | grep -q "not found"; then | |
| echo "ERROR: unresolved dependencies found" | |
| ldd ${GITHUB_WORKSPACE}/libOpenCvSharpExtern-slim.so | grep "not found" | |
| exit 1 | |
| fi | |
| echo "OK: all dependencies resolved" | |
| - uses: actions/upload-artifact@v6 | |
| with: | |
| name: libOpenCvSharpExtern-slim | |
| path: libOpenCvSharpExtern-slim.so | |
| # --------------------------------------------------------------------------- | |
| # Integration test: run the manylinux-built .so on bare Ubuntu 24.04 (no container). | |
| # This validates that a glibc 2.28-built binary works on a newer distro. | |
| # --------------------------------------------------------------------------- | |
| test: | |
| needs: [build_full, build_slim] | |
| runs-on: ubuntu-24.04 | |
| steps: | |
| - uses: actions/checkout@v6 | |
| with: | |
| submodules: false | |
| - name: Download full artifact | |
| uses: actions/download-artifact@v6 | |
| with: | |
| name: libOpenCvSharpExtern-full | |
| path: nuget/ | |
| - name: Download slim artifact | |
| uses: actions/download-artifact@v6 | |
| with: | |
| name: libOpenCvSharpExtern-slim | |
| path: nuget-slim/ | |
| - name: Install .NET | |
| uses: actions/setup-dotnet@v5 | |
| with: | |
| dotnet-version: '8.0.x' | |
| - name: Test (full) | |
| run: | | |
| cd ${GITHUB_WORKSPACE}/test/OpenCvSharp.Tests | |
| dotnet build -c Release -f net8.0 | |
| cp ${GITHUB_WORKSPACE}/nuget/libOpenCvSharpExtern.so bin/Release/net8.0/ | |
| cp ${GITHUB_WORKSPACE}/nuget/libOpenCvSharpExtern.so ./ | |
| sudo cp ${GITHUB_WORKSPACE}/nuget/libOpenCvSharpExtern.so /usr/lib/ | |
| LD_LIBRARY_PATH=. dotnet test OpenCvSharp.Tests.csproj -c Release -f net8.0 --runtime linux-x64 --logger "trx;LogFileName=test-results.trx" < /dev/null | |
| - name: Smoke test (slim) | |
| run: | | |
| cd ${GITHUB_WORKSPACE}/nuget-slim/ | |
| mv libOpenCvSharpExtern-slim.so libOpenCvSharpExtern.so | |
| echo -ne "#include <stdio.h>\nint core_Mat_sizeof(); int main(){ int i = core_Mat_sizeof(); printf(\"sizeof(Mat) = %d\", i); return 0; }" > test.c | |
| gcc -I./ -L./ test.c -o test -lOpenCvSharpExtern | |
| LD_LIBRARY_PATH=. ./test | |
| - uses: actions/upload-artifact@v6 | |
| with: | |
| name: test-results-manylinux | |
| path: test/OpenCvSharp.Tests/bin/Release/net8.0/test-results.trx | |
| # --------------------------------------------------------------------------- | |
| # Create NuGet packages from the manylinux-built binaries. | |
| # Only runs on push to main. | |
| # --------------------------------------------------------------------------- | |
| nuget: | |
| needs: test | |
| if: github.event_name == 'push' && github.ref == 'refs/heads/main' | |
| runs-on: ubuntu-24.04 | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - name: Download full artifact | |
| uses: actions/download-artifact@v6 | |
| with: | |
| name: libOpenCvSharpExtern-full | |
| path: /tmp/so-full/ | |
| - name: Download slim artifact | |
| uses: actions/download-artifact@v6 | |
| with: | |
| name: libOpenCvSharpExtern-slim | |
| path: /tmp/so-slim/ | |
| - name: Install .NET | |
| uses: actions/setup-dotnet@v5 | |
| with: | |
| dotnet-version: '8.0.x' | |
| - name: Create NuGet packages | |
| env: | |
| BETA: "-beta" | |
| run: | | |
| yyyymmdd=$(date '+%Y%m%d') | |
| version="${OPENCV_VERSION}.${yyyymmdd}${BETA}" | |
| echo "Package version: $version" | |
| # Full package | |
| cp /tmp/so-full/libOpenCvSharpExtern.so nuget/libOpenCvSharpExtern.so | |
| dotnet pack nuget/OpenCvSharp4.official.runtime.linux-x64.csproj \ | |
| -o ${GITHUB_WORKSPACE}/artifacts -p:Version=$version | |
| # Slim package (overwrite .so in nuget/ with slim binary) | |
| cp /tmp/so-slim/libOpenCvSharpExtern-slim.so nuget/libOpenCvSharpExtern.so | |
| dotnet pack nuget/OpenCvSharp4.official.runtime.linux-x64.slim.csproj \ | |
| -o ${GITHUB_WORKSPACE}/artifacts -p:Version=$version | |
| ls ${GITHUB_WORKSPACE}/artifacts | |
| - uses: actions/upload-artifact@v6 | |
| with: | |
| name: nuget-packages-manylinux | |
| path: artifacts |