-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Build Windows ARM64 #1795
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Build Windows ARM64 #1795
Conversation
This workflow builds OpenCVSharp for ARM64 on Windows, including setup for dependencies, caching, and artifact uploading.
…in build workflow
…fore copying files
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR adds a GitHub Actions workflow to build OpenCVSharp native libraries for Windows ARM64 architecture. The workflow automates the compilation of both OpenCV 4.11.0 and OpenCVSharp's native components targeting ARM64, with caching for efficiency.
Key changes:
- Adds complete CI/CD pipeline for Windows ARM64 builds
- Implements OpenCV 4.11.0 compilation with ARM64-specific optimizations (NEON, static linking)
- Includes workarounds for missing dependencies and path issues through runtime modifications
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| workflow_dispatch: | ||
| jobs: | ||
| build-opencv-arm64: | ||
| runs-on: windows-11-arm |
Copilot
AI
Dec 5, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The runner label windows-11-arm may not be available in GitHub-hosted runners. As of January 2025, GitHub does not provide public ARM64 Windows runners. This workflow will only work if you have self-hosted runners with this label configured. Consider adding a comment in the workflow or documentation to clarify this requirement.
| - name: Clone OpenCVSharp source code | ||
| shell: powershell | ||
| run: | | ||
| Write-Host "Cloning OpenCVSharp repository..." | ||
| git clone --depth 1 https://github.com/shimat/opencvsharp.git opencvsharp-source | ||
|
|
||
| # Remove existing src directory completely and recreate it | ||
| Write-Host "Removing existing src directory..." | ||
| if (Test-Path "src") { | ||
| Remove-Item -Path "src" -Recurse -Force | ||
| } | ||
|
|
||
| # Copy the entire src directory from cloned repo | ||
| Write-Host "Copying source files..." | ||
| Copy-Item -Path "opencvsharp-source\src" -Destination "." -Recurse -Force | ||
|
|
||
| Write-Host "Source files copied successfully" | ||
|
|
Copilot
AI
Dec 5, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This step clones the OpenCVSharp repository after already checking it out in the previous step. This duplicates the repository unnecessarily and then replaces the checked-out src directory with the cloned one. This is redundant - if you need the latest source, you should just use the checked-out repository directly. If you need a specific version, specify it in the checkout action instead.
| - name: Clone OpenCVSharp source code | |
| shell: powershell | |
| run: | | |
| Write-Host "Cloning OpenCVSharp repository..." | |
| git clone --depth 1 https://github.com/shimat/opencvsharp.git opencvsharp-source | |
| # Remove existing src directory completely and recreate it | |
| Write-Host "Removing existing src directory..." | |
| if (Test-Path "src") { | |
| Remove-Item -Path "src" -Recurse -Force | |
| } | |
| # Copy the entire src directory from cloned repo | |
| Write-Host "Copying source files..." | |
| Copy-Item -Path "opencvsharp-source\src" -Destination "." -Recurse -Force | |
| Write-Host "Source files copied successfully" | |
| & $env:VCPKG_ROOT\vcpkg install libjpeg-turbo:arm64-windows-static | ||
| & $env:VCPKG_ROOT\vcpkg integrate install |
Copilot
AI
Dec 5, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The variable $env:VCPKG_ROOT is used here, but later in line 138 the code checks for $env:VCPKG_INSTALLATION_ROOT as the standard variable on GitHub runners. This inconsistency could cause issues. Consider using the same logic as lines 138-139 to handle both possible environment variables.
| & $env:VCPKG_ROOT\vcpkg install libjpeg-turbo:arm64-windows-static | |
| & $env:VCPKG_ROOT\vcpkg integrate install | |
| # Determine vcpkg root directory | |
| if ($env:VCPKG_INSTALLATION_ROOT) { | |
| $vcpkgRoot = $env:VCPKG_INSTALLATION_ROOT | |
| } else { | |
| $vcpkgRoot = $env:VCPKG_ROOT | |
| } | |
| & "$vcpkgRoot\vcpkg" install libjpeg-turbo:arm64-windows-static | |
| & "$vcpkgRoot\vcpkg" integrate install |
| # Create stubs for missing libraries that are referenced but not used (DNN/GAPI disabled) | ||
| $stubLibs = @("libprotobuf.lib", "ade.lib") | ||
| foreach ($lib in $stubLibs) { | ||
| $stubPath = "C:\opencv-build\install\ARM64\vc17\staticlib\$lib" | ||
| if (-not (Test-Path $stubPath)) { | ||
| New-Item -ItemType File -Path $stubPath -Force | Out-Null | ||
| Write-Host "Created stub $lib (not used)" | ||
| } | ||
| } |
Copilot
AI
Dec 5, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Creating stub/empty library files is a workaround that could lead to linker errors or undefined behavior at runtime if these libraries are actually referenced. While the comment states these are "not used", this approach is fragile. A better solution would be to fix the build configuration to not reference these libraries at all when DNN/GAPI are disabled.
| # Create stubs for missing libraries that are referenced but not used (DNN/GAPI disabled) | |
| $stubLibs = @("libprotobuf.lib", "ade.lib") | |
| foreach ($lib in $stubLibs) { | |
| $stubPath = "C:\opencv-build\install\ARM64\vc17\staticlib\$lib" | |
| if (-not (Test-Path $stubPath)) { | |
| New-Item -ItemType File -Path $stubPath -Force | Out-Null | |
| Write-Host "Created stub $lib (not used)" | |
| } | |
| } | |
| # (Removed) Stub library creation for missing libraries. Instead, ensure build configuration does not reference these when DNN/GAPI are disabled. |
| shell: powershell | ||
| run: | | ||
| # Define paths at the beginning for better maintainability | ||
| $oldJpegPath = 'C:\\a\\opencvsharp\.win\.arm64\\opencvsharp\.win\.arm64\\vcpkg\\installed\\arm64-windows-static\\lib\\jpeg\.lib' |
Copilot
AI
Dec 5, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The hardcoded path C:\\a\\opencvsharp\.win\.arm64\\opencvsharp\.win\.arm64\\vcpkg\\installed\\arm64-windows-static\\lib\\jpeg\.lib appears to be specific to a particular CI environment or local setup. This path is unlikely to exist in the GitHub Actions runner and the replacement logic may not work as intended. Consider using a more generic pattern or removing this path replacement if it's not necessary.
| $oldJpegPath = 'C:\\a\\opencvsharp\.win\.arm64\\opencvsharp\.win\.arm64\\vcpkg\\installed\\arm64-windows-static\\lib\\jpeg\.lib' | |
| $oldJpegPath = "$vcpkgRoot\installed\arm64-windows-static\lib\jpeg.lib" |
| # Comment out the problematic iconv calls | ||
| $content = $content -replace 'ocv_target_link_libraries\(OpenCvSharpExtern Iconv::Iconv\)', '# ocv_target_link_libraries(OpenCvSharpExtern Iconv::Iconv)' | ||
| $content = $content -replace 'ocv_target_compile_definitions\(OpenCvSharpExtern PRIVATE "NO_ICONV=1"\)', '# ocv_target_compile_definitions(OpenCvSharpExtern PRIVATE "NO_ICONV=1")' | ||
|
|
||
| Set-Content $cmakeFile -Value $content | ||
|
|
||
| # Fix include_opencv.h to comment out missing headers | ||
| $includeFile = "src\OpenCvSharpExtern\include_opencv.h" | ||
| $includeContent = Get-Content $includeFile -Raw | ||
| $includeContent = $includeContent -replace '#include <opencv2/wechat_qrcode\.hpp>', '// #include <opencv2/wechat_qrcode.hpp> // Disabled' | ||
| $includeContent = $includeContent -replace '#include <opencv2/dnn\.hpp>', '// #include <opencv2/dnn.hpp> // Disabled' | ||
| $includeContent = $includeContent -replace '#include <opencv2/dnn_superres\.hpp>', '// #include <opencv2/dnn_superres.hpp> // Disabled' | ||
| $includeContent = $includeContent -replace '#include <opencv2/text\.hpp>', '// #include <opencv2/text.hpp> // Disabled' | ||
| Set-Content $includeFile -Value $includeContent | ||
|
|
Copilot
AI
Dec 5, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Modifying source files directly in the build step (CMakeLists.txt and include_opencv.h) is a fragile anti-pattern. These modifications are not version-controlled and could break with updates to the source code. Consider either: 1) Maintaining patch files that can be applied, 2) Forking and modifying the source repository, or 3) Using CMake's command-line options to control build settings instead of text replacement.
| # Comment out the problematic iconv calls | |
| $content = $content -replace 'ocv_target_link_libraries\(OpenCvSharpExtern Iconv::Iconv\)', '# ocv_target_link_libraries(OpenCvSharpExtern Iconv::Iconv)' | |
| $content = $content -replace 'ocv_target_compile_definitions\(OpenCvSharpExtern PRIVATE "NO_ICONV=1"\)', '# ocv_target_compile_definitions(OpenCvSharpExtern PRIVATE "NO_ICONV=1")' | |
| Set-Content $cmakeFile -Value $content | |
| # Fix include_opencv.h to comment out missing headers | |
| $includeFile = "src\OpenCvSharpExtern\include_opencv.h" | |
| $includeContent = Get-Content $includeFile -Raw | |
| $includeContent = $includeContent -replace '#include <opencv2/wechat_qrcode\.hpp>', '// #include <opencv2/wechat_qrcode.hpp> // Disabled' | |
| $includeContent = $includeContent -replace '#include <opencv2/dnn\.hpp>', '// #include <opencv2/dnn.hpp> // Disabled' | |
| $includeContent = $includeContent -replace '#include <opencv2/dnn_superres\.hpp>', '// #include <opencv2/dnn_superres.hpp> // Disabled' | |
| $includeContent = $includeContent -replace '#include <opencv2/text\.hpp>', '// #include <opencv2/text.hpp> // Disabled' | |
| Set-Content $includeFile -Value $includeContent | |
| # Apply patch files to CMakeLists.txt and include_opencv.h | |
| # Ensure patch.exe is available (install via Chocolatey if needed) | |
| if (-not (Get-Command patch.exe -ErrorAction SilentlyContinue)) { | |
| choco install patch | |
| } | |
| # Apply CMakeLists.txt patch | |
| patch -p1 < ..\patches\cmakelists-iconv.patch | |
| # Apply include_opencv.h patch | |
| patch -p1 < ..\patches\include_opencv_headers.patch | |
| # Fix hardcoded jpeg.lib path in generated .vcxproj files | ||
| Write-Host "Fixing jpeg.lib path in OpenCvSharpExtern.vcxproj files..." | ||
| $vcxprojFile = "OpenCvSharpExtern.dir\Release\OpenCvSharpExtern.vcxproj" | ||
| if (Test-Path $vcxprojFile) { | ||
| $vcxprojContent = Get-Content $vcxprojFile -Raw | ||
| $vcxprojContent = $vcxprojContent -replace $oldJpegPath, $newJpegPath | ||
| Set-Content $vcxprojFile -Value $vcxprojContent | ||
| Write-Host "Fixed jpeg.lib path in release vcxproj" | ||
| } | ||
|
|
||
| # Also fix in the main vcxproj if it exists | ||
| $mainVcxproj = "OpenCvSharpExtern.vcxproj" | ||
| if (Test-Path $mainVcxproj) { | ||
| $mainContent = Get-Content $mainVcxproj -Raw | ||
| $mainContent = $mainContent -replace $oldJpegPath, $newJpegPath | ||
| Set-Content $mainVcxproj -Value $mainContent | ||
| Write-Host "Fixed jpeg.lib path in main vcxproj" | ||
| } | ||
|
|
Copilot
AI
Dec 5, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Modifying generated .vcxproj files after CMake configuration is an anti-pattern. These files can be regenerated by CMake at any time, losing your changes. The path issue should be fixed at the CMake configuration level by setting appropriate CMAKE variables (like CMAKE_PREFIX_PATH or CMAKE_LIBRARY_PATH) or by fixing the vcpkg integration, rather than post-processing generated files.
| # Fix hardcoded jpeg.lib path in generated .vcxproj files | |
| Write-Host "Fixing jpeg.lib path in OpenCvSharpExtern.vcxproj files..." | |
| $vcxprojFile = "OpenCvSharpExtern.dir\Release\OpenCvSharpExtern.vcxproj" | |
| if (Test-Path $vcxprojFile) { | |
| $vcxprojContent = Get-Content $vcxprojFile -Raw | |
| $vcxprojContent = $vcxprojContent -replace $oldJpegPath, $newJpegPath | |
| Set-Content $vcxprojFile -Value $vcxprojContent | |
| Write-Host "Fixed jpeg.lib path in release vcxproj" | |
| } | |
| # Also fix in the main vcxproj if it exists | |
| $mainVcxproj = "OpenCvSharpExtern.vcxproj" | |
| if (Test-Path $mainVcxproj) { | |
| $mainContent = Get-Content $mainVcxproj -Raw | |
| $mainContent = $mainContent -replace $oldJpegPath, $newJpegPath | |
| Set-Content $mainVcxproj -Value $mainContent | |
| Write-Host "Fixed jpeg.lib path in main vcxproj" | |
| } | |
| # [REMOVED] Post-processing of .vcxproj files to fix jpeg.lib path. | |
| # Ensure correct library paths are set in CMake configuration above. | |
Co-authored-by: Copilot <[email protected]>
No description provided.