Skip to content

Fix double InputArray multi-channel semantics #763

Fix double InputArray multi-channel semantics

Fix double InputArray multi-channel semantics #763

Workflow file for this run

name: manylinux
on:
pull_request:
types: [synchronize, opened]
push:
branches:
- main
permissions:
contents: read
packages: read
env:
DEBIAN_FRONTEND: noninteractive
OPENCV_VERSION: 5.0.0
MEDIAMTX_VERSION: 1.19.3
jobs:
# ---------------------------------------------------------------------------
# Build full libOpenCvSharpExtern.so inside manylinux_2_28.
# Static deps (FFmpeg via build_static_deps.sh cached in /opt/ffmpeg;
# image libs + Tesseract + Leptonica via vcpkg cached in vcpkg_installed/)
# The resulting .so depends only on glibc / libstdc++ system libraries.
# ---------------------------------------------------------------------------
build_full:
name: Linux (x64, full)
runs-on: ubuntu-24.04
container:
image: ghcr.io/shimat/opencvsharp-manylinux@sha256:fdb9a9c223b215604dc7b6f7e8fff4b39bfea5fbaa7777a2e5544a60dfa437f8
credentials:
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
options: --user root
steps:
- uses: actions/checkout@v7
with:
submodules: true
- uses: ./.github/actions/build-manylinux-variant
with:
opencv_version: ${{ env.OPENCV_VERSION }}
variant_label: full
install_gtk3_devel: 'true'
artifacts_dir: opencv_artifacts
opencv_build_dir: opencv/build
extern_build_dir: src/build
save_shared_caches: 'true'
output_so_name: libOpenCvSharpExtern.so
artifact_name: libOpenCvSharpExtern-full
# ---------------------------------------------------------------------------
# Build headless libOpenCvSharpExtern.so inside manylinux_2_28.
# Same module set as "full" (videoio, dnn, ml, contrib, stitching, barcode, ...)
# but highgui is disabled, so GTK3/X11/Mesa are never linked. Targets
# containerized/headless consumers that need more than the "slim" module set
# but don't want the GTK3 runtime dependency of "full". See issue #2065.
# ---------------------------------------------------------------------------
build_headless:
name: Linux (x64, headless)
runs-on: ubuntu-24.04
container:
image: ghcr.io/shimat/opencvsharp-manylinux@sha256:fdb9a9c223b215604dc7b6f7e8fff4b39bfea5fbaa7777a2e5544a60dfa437f8
credentials:
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
options: --user root
steps:
- uses: actions/checkout@v7
with:
submodules: true
persist-credentials: false
- uses: ./.github/actions/build-manylinux-variant
with:
opencv_version: ${{ env.OPENCV_VERSION }}
variant_label: headless
install_gtk3_devel: 'false'
artifacts_dir: opencv_artifacts_headless
opencv_build_dir: opencv/build-headless
extern_build_dir: src/build-headless
extra_opencv_cmake_args: -D WITH_GTK=OFF
extra_extern_cmake_args: -D NO_HIGHGUI=ON
verify_gtk_off: 'true'
verify_no_gui_deps: 'true'
save_shared_caches: 'false'
output_so_name: libOpenCvSharpExtern-headless.so
artifact_name: libOpenCvSharpExtern-headless
# ---------------------------------------------------------------------------
# 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:
name: Linux (x64, slim)
runs-on: ubuntu-24.04
container:
image: ghcr.io/shimat/opencvsharp-manylinux@sha256:fdb9a9c223b215604dc7b6f7e8fff4b39bfea5fbaa7777a2e5544a60dfa437f8
credentials:
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
options: --user root
steps:
- uses: actions/checkout@v7
with:
submodules: true
# -- System tools --------------------------------------------------------
- name: Install system tools
run: dnf install -y ninja-build
- name: Restore OpenCV cache (slim)
id: opencv-cache
uses: actions/cache/restore@v6
with:
path: ${{ github.workspace }}/opencv_artifacts_slim
key: opencv-${{ env.OPENCV_VERSION }}-manylinux2_28-slim-${{ hashFiles('cmake/opencv_build_options_slim.cmake') }}
- name: Configure OpenCV (slim)
if: steps.opencv-cache.outputs.cache-hit != 'true'
run: |
cmake \
-G Ninja \
-C cmake/opencv_build_options_slim.cmake \
-S opencv \
-B opencv/build \
-D OPENCV_EXTRA_MODULES_PATH=${GITHUB_WORKSPACE}/opencv_contrib/modules \
-D CMAKE_INSTALL_PREFIX=${GITHUB_WORKSPACE}/opencv_artifacts_slim \
-D WITH_TBB=OFF \
-D BUILD_ZLIB=ON
- name: Build OpenCV (slim)
if: steps.opencv-cache.outputs.cache-hit != 'true'
run: |
cmake --build opencv/build -j 3
cmake --install opencv/build
echo "=== opencv_artifacts_slim layout ==="
find ${GITHUB_WORKSPACE}/opencv_artifacts_slim -name 'OpenCVConfig.cmake' -o -name '*.pc' | head -20
du -sh ${GITHUB_WORKSPACE}/opencv_artifacts_slim/*/
- name: Save OpenCV cache (slim)
if: steps.opencv-cache.outputs.cache-hit != 'true' && github.event_name == 'push' && github.ref == 'refs/heads/main'
run: |
config=$(find ${GITHUB_WORKSPACE}/opencv_artifacts_slim -name 'OpenCVConfig.cmake' | head -1)
if [ -z "$config" ]; then
echo "ERROR: OpenCVConfig.cmake not found under opencv_artifacts_slim - install is incomplete."
exit 1
fi
echo "Found: $config"
shell: bash
- name: Save OpenCV cache (slim) - upload
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_artifacts_slim
key: opencv-${{ env.OPENCV_VERSION }}-manylinux2_28-slim-${{ hashFiles('cmake/opencv_build_options_slim.cmake') }}
- name: Build OpenCvSharpExtern (slim)
run: |
cmake \
-G Ninja \
-S src \
-B src/build-slim \
-D CMAKE_BUILD_TYPE=Release \
-D OpenCV_DIR=${GITHUB_WORKSPACE}/opencv_artifacts_slim/lib64/cmake/opencv5 \
-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 \
-D NO_STITCHING=ON
cmake --build src/build-slim -j
cp src/build-slim/OpenCvSharpExtern/libOpenCvSharpExtern.so ${GITHUB_WORKSPACE}/libOpenCvSharpExtern-slim.so
- uses: actions/upload-artifact@v7
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:
name: Linux (test)
needs: [build_full, build_headless, build_slim]
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v7
with:
submodules: false
- name: Download full artifact
uses: actions/download-artifact@v8
with:
name: libOpenCvSharpExtern-full
path: packaging/nuget/
- name: Download headless artifact
uses: actions/download-artifact@v8
with:
name: libOpenCvSharpExtern-headless
path: nuget-headless/
- name: Download slim artifact
uses: actions/download-artifact@v8
with:
name: libOpenCvSharpExtern-slim
path: nuget-slim/
- name: Install .NET
uses: actions/setup-dotnet@v6
with:
dotnet-version: '10.0.x'
- name: Start local RTSP test server
run: |
docker run --detach --rm \
--name opencvsharp-rtsp \
--publish 8554:8554 \
--volume "${GITHUB_WORKSPACE}/test/rtsp/mediamtx.yml:/mediamtx.yml:ro" \
bluenviron/mediamtx:${MEDIAMTX_VERSION}@sha256:7797ed3df88df21e8c04ecd0aff08ce49a5232d1db453e51f5480ef36bc80865
for attempt in $(seq 1 30); do
if docker logs opencvsharp-rtsp 2>&1 | grep -q "stream is available"; then
exit 0
fi
sleep 1
done
docker logs opencvsharp-rtsp
exit 1
- name: Test (full)
env:
OPENCVSHARP_TEST_RTSP_URL: rtsp://127.0.0.1:8554/test
run: |
cd ${GITHUB_WORKSPACE}/test/OpenCvSharp.Tests
dotnet build -c Release -f net10.0
cp ${GITHUB_WORKSPACE}/packaging/nuget/libOpenCvSharpExtern.so bin/Release/net10.0/
cp ${GITHUB_WORKSPACE}/packaging/nuget/libOpenCvSharpExtern.so ./
sudo cp ${GITHUB_WORKSPACE}/packaging/nuget/libOpenCvSharpExtern.so /usr/lib/
LD_LIBRARY_PATH=. dotnet test --project OpenCvSharp.Tests.csproj -c Release -f net10.0 --runtime linux-x64 \
--results-directory TestResults --report-xunit-trx --report-xunit-trx-filename test-results.trx < /dev/null
- name: Test Avalonia extensions
run: |
cd ${GITHUB_WORKSPACE}/test/OpenCvSharp.Tests.Avalonia
dotnet build -c Release -f net10.0
cp ${GITHUB_WORKSPACE}/packaging/nuget/libOpenCvSharpExtern.so bin/Release/net10.0/
LD_LIBRARY_PATH=. dotnet test --project OpenCvSharp.Tests.Avalonia.csproj -c Release -f net10.0 --runtime linux-x64 < /dev/null
# Headless has the same module set as full except highgui, so it runs the same xunit
# suite minus the one test class that calls into highgui (WaitKey/PollKey/...).
- name: Test (headless)
env:
OPENCVSHARP_TEST_RTSP_URL: rtsp://127.0.0.1:8554/test
run: |
cd ${GITHUB_WORKSPACE}/test/OpenCvSharp.Tests
cp ${GITHUB_WORKSPACE}/nuget-headless/libOpenCvSharpExtern-headless.so bin/Release/net10.0/libOpenCvSharpExtern.so
cp ${GITHUB_WORKSPACE}/nuget-headless/libOpenCvSharpExtern-headless.so ./libOpenCvSharpExtern.so
sudo cp ${GITHUB_WORKSPACE}/nuget-headless/libOpenCvSharpExtern-headless.so /usr/lib/libOpenCvSharpExtern.so
LD_LIBRARY_PATH=. dotnet test --project OpenCvSharp.Tests.csproj -c Release -f net10.0 --runtime linux-x64 --no-build \
--filter-not-class OpenCvSharp.Tests.HighGui.HighGuiTest \
--results-directory TestResults --report-xunit-trx --report-xunit-trx-filename test-results-headless.trx < /dev/null
- name: Stop local RTSP test server
if: always()
run: docker stop opencvsharp-rtsp >/dev/null 2>&1 || true
- 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@v7
with:
name: test-results-manylinux
path: test/OpenCvSharp.Tests/TestResults/test-results*.trx
# ---------------------------------------------------------------------------
# Create NuGet packages from the manylinux-built binaries.
# Only runs on push to main.
# ---------------------------------------------------------------------------
nuget:
name: Linux (nuget)
needs: test
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v7
- name: Download full artifact
uses: actions/download-artifact@v8
with:
name: libOpenCvSharpExtern-full
path: /tmp/so-full/
- name: Download headless artifact
uses: actions/download-artifact@v8
with:
name: libOpenCvSharpExtern-headless
path: /tmp/so-headless/
- name: Download slim artifact
uses: actions/download-artifact@v8
with:
name: libOpenCvSharpExtern-slim
path: /tmp/so-slim/
- name: Install .NET
uses: actions/setup-dotnet@v6
with:
dotnet-version: '10.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 packaging/nuget/libOpenCvSharpExtern.so
dotnet pack packaging/nuget/OpenCvSharp5.official.runtime.linux-x64.csproj \
-o ${GITHUB_WORKSPACE}/artifacts -p:Version=$version
# Headless package (overwrite .so in packaging/nuget/ with headless binary)
cp /tmp/so-headless/libOpenCvSharpExtern-headless.so packaging/nuget/libOpenCvSharpExtern.so
dotnet pack packaging/nuget/OpenCvSharp5.official.runtime.linux-x64.headless.csproj \
-o ${GITHUB_WORKSPACE}/artifacts -p:Version=$version
# Slim package (overwrite .so in packaging/nuget/ with slim binary)
cp /tmp/so-slim/libOpenCvSharpExtern-slim.so packaging/nuget/libOpenCvSharpExtern.so
dotnet pack packaging/nuget/OpenCvSharp5.official.runtime.linux-x64.slim.csproj \
-o ${GITHUB_WORKSPACE}/artifacts -p:Version=$version
ls ${GITHUB_WORKSPACE}/artifacts
- uses: actions/upload-artifact@v7
with:
name: nuget-packages-manylinux
path: artifacts