From bf539c1c7df446a828de4e72c731dd4ca9b6f60b Mon Sep 17 00:00:00 2001 From: shimat Date: Sat, 30 May 2026 20:36:51 +0900 Subject: [PATCH 1/6] Fix duplicate native DLLs in net4x output directory (#1765) When a net4x project references OpenCvSharp4.runtime.win via PackageReference, two separate mechanisms both copy the native DLLs to the build output: 1. The .props file (at build/netstandard/) copies them to dll/x64/, which is where WindowsLibraryLoader looks at runtime. 2. NuGet''s PackageReference pipeline also copies runtimes/win-x64/native/ assets to the output root, which are never loaded by OpenCvSharp. Add a .targets file for each runtime package (full and slim) that removes the package''s entries from RuntimeCopyLocalItems after ResolvePackageAssets runs, suppressing the redundant root copy for net4x targets. The dll/x64/ placement from the .props file is unaffected, so runtime behavior is unchanged. This fix applies only to SDK-style projects using PackageReference. Old-style packages.config projects do not process runtimes/ assets automatically, so there is no duplicate in that case and the target has no effect. Co-Authored-By: Claude Sonnet 4.5 --- docs/issue-backlog.md | 2 +- nuget/OpenCvSharp4.runtime.win.csproj | 3 +++ nuget/OpenCvSharp4.runtime.win.slim.csproj | 3 +++ nuget/OpenCvSharp4.runtime.win.slim.targets | 24 +++++++++++++++++++++ nuget/OpenCvSharp4.runtime.win.targets | 24 +++++++++++++++++++++ 5 files changed, 55 insertions(+), 1 deletion(-) create mode 100644 nuget/OpenCvSharp4.runtime.win.slim.targets create mode 100644 nuget/OpenCvSharp4.runtime.win.targets diff --git a/docs/issue-backlog.md b/docs/issue-backlog.md index 43f3c4fc27..9afd0a386e 100644 --- a/docs/issue-backlog.md +++ b/docs/issue-backlog.md @@ -19,7 +19,7 @@ Check off items as they are resolved. --- -### [ ] #1704 — Assembly version reported as `0.0.0.0` +### [x] #1704 — Assembly version reported as `0.0.0.0` - **State**: closed (stale) - **URL**: https://github.com/shimat/opencvsharp/issues/1704 diff --git a/nuget/OpenCvSharp4.runtime.win.csproj b/nuget/OpenCvSharp4.runtime.win.csproj index 92a6a3b965..b078fe8d02 100644 --- a/nuget/OpenCvSharp4.runtime.win.csproj +++ b/nuget/OpenCvSharp4.runtime.win.csproj @@ -27,6 +27,9 @@ + + + diff --git a/nuget/OpenCvSharp4.runtime.win.slim.csproj b/nuget/OpenCvSharp4.runtime.win.slim.csproj index eb58ed5bfd..dc7141cc34 100644 --- a/nuget/OpenCvSharp4.runtime.win.slim.csproj +++ b/nuget/OpenCvSharp4.runtime.win.slim.csproj @@ -25,6 +25,9 @@ + + + diff --git a/nuget/OpenCvSharp4.runtime.win.slim.targets b/nuget/OpenCvSharp4.runtime.win.slim.targets new file mode 100644 index 0000000000..c59c3259f3 --- /dev/null +++ b/nuget/OpenCvSharp4.runtime.win.slim.targets @@ -0,0 +1,24 @@ + + + + + + + + diff --git a/nuget/OpenCvSharp4.runtime.win.targets b/nuget/OpenCvSharp4.runtime.win.targets new file mode 100644 index 0000000000..0693e47a39 --- /dev/null +++ b/nuget/OpenCvSharp4.runtime.win.targets @@ -0,0 +1,24 @@ + + + + + + + + From d5ef5cd65bc84fa4a6228b2254fcf9f06cfd33c4 Mon Sep 17 00:00:00 2001 From: shimat Date: Sat, 30 May 2026 20:41:50 +0900 Subject: [PATCH 2/6] Add developer documentation and CLAUDE.md docs/release-process.md: document the release workflow and assembly versioning policy (when to bump AssemblyVersion, how the NuGet version flows through CI, steps for upgrading OpenCV). CLAUDE.md: AI-facing instructions covering repository structure, the versioning convention, WindowsLibraryLoader behavior, and NuGet runtime package layout. Co-Authored-By: Claude Sonnet 4.5 --- CLAUDE.md | 39 +++++++++++++++++++++++++++++++ docs/release-process.md | 51 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 90 insertions(+) create mode 100644 CLAUDE.md create mode 100644 docs/release-process.md diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000000..856e442c24 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,39 @@ +# OpenCvSharp — Claude Code Instructions + +This file provides context for AI-assisted development on this repository. + +## Repository overview + +OpenCvSharp is a .NET wrapper for OpenCV. The solution has three layers: + +- **`src/OpenCvSharp/`** — managed C# wrapper (P/Invoke, types, extension methods) +- **`src/OpenCvSharpExtern/`** — thin C++ bridge that the C# side calls via P/Invoke +- **`nuget/`** — NuGet packaging projects (runtime packages that bundle the native DLLs) + +Target frameworks for the managed library: `netstandard2.0`, `netstandard2.1`, `net8.0`. Always verify that any change is consistent across all three. + +## Key conventions + +### Versioning + +See `docs/release-process.md` for the full release process. + +**Short version:** `AssemblyVersion` and `FileVersion` are hardcoded to `4.0.0.0` in `src/Directory.Build.props` and must **not** be changed for routine OpenCV patch/minor upgrades. The NuGet package version is passed via `-p:Version=...` at pack time in CI; no source file needs editing for a version bump. `InformationalVersion` is set automatically by the SDK and tracks the full NuGet version string including the commit SHA. + +Only bump the major component of `AssemblyVersion` (e.g. `4.0.0.0` → `5.0.0.0`) when there is a breaking API change or an OpenCV major-version upgrade. This is a breaking change for .NET Framework consumers. + +### Native DLL loading (Windows) + +`WindowsLibraryLoader` in `src/OpenCvSharp/Internal/PInvoke/WindowsLibraryLoader.cs` handles native DLL loading on Windows for .NET Framework targets. Key points: + +- Uses `AppContext.BaseDirectory` (not `Assembly.Location`) to avoid IL3000 warnings in AoT/single-file apps. +- For .NET Framework (net4x), looks for DLLs under `dll/x64/` relative to the base directory. The NuGet `.props` file copies DLLs there at build time. +- For .NET 5+, returns early — the .NET runtime handles native loading via the `runtimes/` folder layout. + +### NuGet runtime packages + +`nuget/OpenCvSharp4.runtime.win.props` and its slim variant copy native DLLs to `dll/x64/` for net4x consumers. A companion `.targets` file suppresses the redundant copy that NuGet's PackageReference pipeline would otherwise make to the output root. + +## Issue backlog + +`docs/issue-backlog.md` tracks actionable issues identified from closed/stale GitHub issues. Update the checkboxes as items are resolved. diff --git a/docs/release-process.md b/docs/release-process.md new file mode 100644 index 0000000000..d3d66a9a80 --- /dev/null +++ b/docs/release-process.md @@ -0,0 +1,51 @@ +# Release Process + +This document describes the steps required to publish a new version of OpenCvSharp. + +--- + +## Version numbering + +NuGet package versions follow the pattern `{opencv_version}.{YYYYMMDD}`, e.g. `4.13.0.20260530`. The `-beta` suffix is stripped by `OpenCvSharp.NupkgBetaRemover` at publish time. + +The version is passed at pack time via `-p:Version=...` in CI. **No source file needs to be edited to change the version number.** + +### Assembly versioning policy + +Managed assembly attributes are set as follows (see `src/Directory.Build.props`): + +| Attribute | Value | Rationale | +|---|---|---| +| `AssemblyVersion` | `4.0.0.0` (major-pinned, hardcoded) | Changing this on every release is a breaking change for .NET Framework consumers of the strong-named assembly — they would need binding redirects in `app.config`. Only bump the major component when there is a breaking API change. | +| `FileVersion` | `4.0.0.0` (hardcoded) | The date-based 4th component (e.g. `20260530`) exceeds the 65535 per-component limit of the Windows FILEVERSION PE resource. | +| `InformationalVersion` | Set automatically by the .NET SDK to `$(Version)` | This is the human-readable version visible in Windows file properties ("Product version") and most tooling. It tracks the NuGet version correctly with no manual action needed. | + +### When to bump `AssemblyVersion` + +- **Patch / minor OpenCV update** (e.g. 4.13.0 → 4.13.1, or 4.13 → 4.14): **do nothing**. The assembly version stays at `4.0.0.0`. +- **OpenCV major version bump** (e.g. 4.x → 5.x): update `AssemblyVersion` and `FileVersion` in `src/Directory.Build.props` to `5.0.0.0`. Be aware this is a breaking change for .NET Framework consumers. +- **Breaking API change in the C# wrapper** (rare): same as above — bump the major component. + +--- + +## CI workflow + +Releases are produced by running the following workflows in order: + +1. **`windows.yml`** — builds `OpenCvSharpExtern.dll` (full and slim), runs tests, packs NuGet packages with a `-beta` version suffix. +2. **`linux-arm64.yml`** — builds the Linux ARM64 native library. +3. **`manylinux.yml`** — builds the Linux x64 native library. +4. **`wasm.yml`** — builds the WASM native library. +5. **`publish_nuget.yml`** — collects all artifacts, strips the `-beta` suffix via `OpenCvSharp.NupkgBetaRemover`, validates the package set, and pushes to NuGet.org. + +The `OPENCV_VERSION` environment variable in `windows.yml` controls the OpenCV version embedded in the package version string. Update it there when upgrading OpenCV. + +--- + +## Upgrading OpenCV + +1. Update the `opencv` and `opencv_contrib` submodules to the new tag. +2. Update `OPENCV_VERSION` in `.github/workflows/windows.yml`. +3. Update the ffmpeg DLL filename references in `nuget/OpenCvSharp4.runtime.win.props` and `nuget/OpenCvSharp4.runtime.win.csproj` if the ffmpeg DLL name changed (e.g. `opencv_videoio_ffmpeg4130_64.dll` → `opencv_videoio_ffmpeg4140_64.dll`). +4. Run the full CI pipeline and verify all tests pass. +5. `AssemblyVersion` does **not** need to be changed for a minor/patch OpenCV upgrade. From 50b228024e2e6b6ea709611243cac9f0b52c9506 Mon Sep 17 00:00:00 2001 From: shimat Date: Sat, 30 May 2026 20:43:54 +0900 Subject: [PATCH 3/6] Consolidate AI instructions into copilot-instructions.md Merge the repository overview, versioning policy, WindowsLibraryLoader notes, and issue backlog pointer from CLAUDE.md into the existing .github/copilot-instructions.md to avoid maintaining two parallel files. Remove CLAUDE.md. Co-Authored-By: Claude Sonnet 4.5 --- .github/copilot-instructions.md | 28 +++++++++++++++++++++++ CLAUDE.md | 39 --------------------------------- 2 files changed, 28 insertions(+), 39 deletions(-) delete mode 100644 CLAUDE.md diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index 57256d36b5..7b2fc7d86d 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -184,3 +184,31 @@ From `namespace OpenCvSharp.Internal`, types in `namespace OpenCvSharp` are dire See `src/OpenCvSharpExtern/ximgproc_EdgeDrawing.h`, `src/OpenCvSharp/Modules/ximgproc/EdgeDrawing.cs` for a complete example covering: factory, OutputArray methods, std::vector methods, nested Params struct with bool fields, and VectorOfVec6d. +## Repository structure + +OpenCvSharp has three layers: + +- **`src/OpenCvSharp/`** — managed C# wrapper (P/Invoke, types, extension methods). Target frameworks: `netstandard2.0`, `netstandard2.1`, `net8.0`. Always verify that any change is consistent across all three. +- **`src/OpenCvSharpExtern/`** — thin C++ bridge called by the C# side via P/Invoke. +- **`nuget/`** — NuGet packaging projects (runtime packages that bundle the native DLLs). + +## Versioning and release process + +See `docs/release-process.md` for the full release workflow. + +**Key rule: do not edit version numbers in source files for routine releases.** The NuGet package version is passed via `-p:Version=...` at pack time in CI. `AssemblyVersion` and `FileVersion` are hardcoded to `4.0.0.0` in `src/Directory.Build.props` and must not be changed for patch or minor OpenCV upgrades — only bump the major component on a breaking API change or OpenCV major-version upgrade. `InformationalVersion` is set automatically by the SDK to the full NuGet version string. + +## Native DLL loading (Windows) + +`WindowsLibraryLoader` (`src/OpenCvSharp/Internal/PInvoke/WindowsLibraryLoader.cs`) handles native DLL loading on Windows for .NET Framework targets: + +- Uses `AppContext.BaseDirectory` (not `Assembly.Location`) to avoid IL3000 warnings in AoT/single-file apps. +- For .NET Framework (net4x), looks for DLLs under `dll/x64/` relative to the base directory. The NuGet `.props` file copies DLLs there at build time. +- For .NET 5+, returns early — the .NET runtime handles native loading via the `runtimes/` folder layout. + +The NuGet runtime packages (`nuget/OpenCvSharp4.runtime.win.*`) include a `.targets` file that suppresses the redundant copy NuGet's PackageReference pipeline would otherwise make to the output root for net4x consumers. + +## Issue backlog + +`docs/issue-backlog.md` tracks actionable issues identified from closed/stale GitHub issues. Update the checkboxes as items are resolved. + diff --git a/CLAUDE.md b/CLAUDE.md deleted file mode 100644 index 856e442c24..0000000000 --- a/CLAUDE.md +++ /dev/null @@ -1,39 +0,0 @@ -# OpenCvSharp — Claude Code Instructions - -This file provides context for AI-assisted development on this repository. - -## Repository overview - -OpenCvSharp is a .NET wrapper for OpenCV. The solution has three layers: - -- **`src/OpenCvSharp/`** — managed C# wrapper (P/Invoke, types, extension methods) -- **`src/OpenCvSharpExtern/`** — thin C++ bridge that the C# side calls via P/Invoke -- **`nuget/`** — NuGet packaging projects (runtime packages that bundle the native DLLs) - -Target frameworks for the managed library: `netstandard2.0`, `netstandard2.1`, `net8.0`. Always verify that any change is consistent across all three. - -## Key conventions - -### Versioning - -See `docs/release-process.md` for the full release process. - -**Short version:** `AssemblyVersion` and `FileVersion` are hardcoded to `4.0.0.0` in `src/Directory.Build.props` and must **not** be changed for routine OpenCV patch/minor upgrades. The NuGet package version is passed via `-p:Version=...` at pack time in CI; no source file needs editing for a version bump. `InformationalVersion` is set automatically by the SDK and tracks the full NuGet version string including the commit SHA. - -Only bump the major component of `AssemblyVersion` (e.g. `4.0.0.0` → `5.0.0.0`) when there is a breaking API change or an OpenCV major-version upgrade. This is a breaking change for .NET Framework consumers. - -### Native DLL loading (Windows) - -`WindowsLibraryLoader` in `src/OpenCvSharp/Internal/PInvoke/WindowsLibraryLoader.cs` handles native DLL loading on Windows for .NET Framework targets. Key points: - -- Uses `AppContext.BaseDirectory` (not `Assembly.Location`) to avoid IL3000 warnings in AoT/single-file apps. -- For .NET Framework (net4x), looks for DLLs under `dll/x64/` relative to the base directory. The NuGet `.props` file copies DLLs there at build time. -- For .NET 5+, returns early — the .NET runtime handles native loading via the `runtimes/` folder layout. - -### NuGet runtime packages - -`nuget/OpenCvSharp4.runtime.win.props` and its slim variant copy native DLLs to `dll/x64/` for net4x consumers. A companion `.targets` file suppresses the redundant copy that NuGet's PackageReference pipeline would otherwise make to the output root. - -## Issue backlog - -`docs/issue-backlog.md` tracks actionable issues identified from closed/stale GitHub issues. Update the checkboxes as items are resolved. From dbed22bd2621321a33d61c3ea95639a1f78264e6 Mon Sep 17 00:00:00 2001 From: shimat Date: Sat, 30 May 2026 20:45:33 +0900 Subject: [PATCH 4/6] Add CLAUDE.md pointing to copilot-instructions.md Claude Code reads CLAUDE.md automatically at session start. A one-line pointer avoids duplicating content while keeping .github/copilot-instructions.md as the single source of truth. Co-Authored-By: Claude Sonnet 4.5 --- CLAUDE.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 CLAUDE.md diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000000..0d38ad1a1f --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1 @@ +See `.github/copilot-instructions.md` for development instructions. From b6b15c0c3fbf272a98dc358083f7746109494c0f Mon Sep 17 00:00:00 2001 From: shimat Date: Sat, 30 May 2026 20:55:07 +0900 Subject: [PATCH 5/6] Mark #1765 as resolved in issue backlog Co-Authored-By: Claude Sonnet 4.5 --- docs/issue-backlog.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/issue-backlog.md b/docs/issue-backlog.md index 9afd0a386e..d8c8162876 100644 --- a/docs/issue-backlog.md +++ b/docs/issue-backlog.md @@ -32,7 +32,7 @@ Check off items as they are resolved. ## 🔧 Medium effort -### [ ] #1765 — Native DLLs copied twice when targeting .NET Framework 4.8 +### [x] #1765 — Native DLLs copied twice when targeting .NET Framework 4.8 - **State**: closed (stale) - **URL**: https://github.com/shimat/opencvsharp/issues/1765 From 7301dfe71f96fc9d44439e1afe7e05ad33f2acde Mon Sep 17 00:00:00 2001 From: shimat Date: Sat, 30 May 2026 21:14:01 +0900 Subject: [PATCH 6/6] Fix UTF-8 BOM on CLAUDE.md Co-Authored-By: Claude Sonnet 4.6 --- CLAUDE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CLAUDE.md b/CLAUDE.md index 0d38ad1a1f..9e422a1ca9 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1 +1 @@ -See `.github/copilot-instructions.md` for development instructions. +See `.github/copilot-instructions.md` for development instructions.