diff --git a/.github/workflows/windows-build.yml b/.github/workflows/windows-build.yml index 278d2b7..25e9354 100644 --- a/.github/workflows/windows-build.yml +++ b/.github/workflows/windows-build.yml @@ -1,5 +1,11 @@ name: Windows Build +# This workflow builds the project on Windows with multiple compilers: +# - build-vs2022: Uses Visual Studio 2022 (stable) +# - build-vs2026: Uses Visual Studio 2026 (when available on GitHub runners, skips gracefully if not) +# - build-mingw: Uses MinGW-w64 (latest version) +# All jobs test Debug/Release builds with static/shared library configurations. + on: push: branches: [ main, ci_test ] @@ -8,8 +14,8 @@ on: workflow_dispatch: jobs: - build: - name: Windows Build (${{ matrix.config }}-${{ matrix.library_type }}) + build-vs2022: + name: Windows Build VS2022 (${{ matrix.config }}-${{ matrix.library_type }}) runs-on: windows-latest strategy: @@ -19,7 +25,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Setup Visual Studio environment uses: microsoft/setup-msbuild@v1.1 @@ -187,7 +193,7 @@ jobs: - name: Upload artifacts uses: actions/upload-artifact@v4 with: - name: ccap-windows-${{ matrix.config }}-${{ matrix.library_type }} + name: ccap-windows-vs2022-${{ matrix.config }}-${{ matrix.library_type }} path: | build/${{ matrix.config }}-${{ matrix.library_type }}/${{ matrix.config }}/ccap*.* build/${{ matrix.config }}-${{ matrix.library_type }}/${{ matrix.config }}/0-print_camera.exe @@ -195,4 +201,386 @@ jobs: build/${{ matrix.config }}-${{ matrix.library_type }}/${{ matrix.config }}/2-capture_grab.exe build/${{ matrix.config }}-${{ matrix.library_type }}/${{ matrix.config }}/3-capture_callback.exe build/${{ matrix.config }}-${{ matrix.library_type }}/*_results.xml - if-no-files-found: error \ No newline at end of file + if-no-files-found: error + + build-vs2026: + name: Windows Build VS2026 (${{ matrix.config }}-${{ matrix.library_type }}) + runs-on: windows-latest + + strategy: + matrix: + config: [Debug, Release] + library_type: [static, shared] + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Check for Visual Studio 2026 + id: check-vs2026 + shell: pwsh + run: | + Write-Host "Checking for Visual Studio 2026 on this runner..." + + # Check if VS 2026 is available (stable or preview) + $vs2026Path = "C:\Program Files\Microsoft Visual Studio\2026" + $vs2026PreviewPath = "C:\Program Files\Microsoft Visual Studio\2026\Preview" + $vs2026EnterprisePath = "C:\Program Files\Microsoft Visual Studio\2026\Enterprise" + $vs2026ProfessionalPath = "C:\Program Files\Microsoft Visual Studio\2026\Professional" + $vs2026CommunityPath = "C:\Program Files\Microsoft Visual Studio\2026\Community" + + $found = $false + if (Test-Path $vs2026PreviewPath) { + Write-Host "✓ Visual Studio 2026 Preview found at: $vs2026PreviewPath" + $found = $true + } elseif (Test-Path $vs2026EnterprisePath) { + Write-Host "✓ Visual Studio 2026 Enterprise found at: $vs2026EnterprisePath" + $found = $true + } elseif (Test-Path $vs2026ProfessionalPath) { + Write-Host "✓ Visual Studio 2026 Professional found at: $vs2026ProfessionalPath" + $found = $true + } elseif (Test-Path $vs2026CommunityPath) { + Write-Host "✓ Visual Studio 2026 Community found at: $vs2026CommunityPath" + $found = $true + } elseif (Test-Path $vs2026Path) { + Write-Host "✓ Visual Studio 2026 found at: $vs2026Path" + $found = $true + } + + if ($found) { + echo "VS_2026_AVAILABLE=true" >> $env:GITHUB_ENV + } else { + Write-Host "ℹ Visual Studio 2026 is not available on this GitHub runner yet." + Write-Host "Available Visual Studio installations:" + Get-ChildItem "C:\Program Files\Microsoft Visual Studio" -Directory -ErrorAction SilentlyContinue | ForEach-Object { Write-Host " - $($_.FullName)" } + Write-Host "" + Write-Host "⏭ Skipping VS2026 build - this job will complete successfully without running the build." + Write-Host "Once GitHub adds VS2026 to their runners, this job will automatically start building." + echo "VS_2026_AVAILABLE=false" >> $env:GITHUB_ENV + } + + - name: Setup latest CMake + if: env.VS_2026_AVAILABLE == 'true' + # Use @latest to ensure CMake 3.31+ is available, which is required for VS 2026 support + uses: lukka/get-cmake@latest + + - name: Configure CMake with VS2026 + if: env.VS_2026_AVAILABLE == 'true' + run: | + $SHARED_FLAG = "" + if ("${{ matrix.library_type }}" -eq "shared") { + $SHARED_FLAG = "-DCCAP_BUILD_SHARED=ON" + Write-Host "Configuring Windows build ${{ matrix.config }} with VS2026 - SHARED LIBRARY (DLL)" + } else { + Write-Host "Configuring Windows build ${{ matrix.config }} with VS2026 - STATIC LIBRARY" + } + + # Check CMake version + cmake --version + + mkdir -p "build/${{ matrix.config }}-${{ matrix.library_type }}" + cd "build/${{ matrix.config }}-${{ matrix.library_type }}" + + # Try Visual Studio 18 2026 generator + try { + Write-Host "Attempting to use Visual Studio 18 2026 generator..." + cmake ../.. -G "Visual Studio 18 2026" -A x64 -DCCAP_BUILD_TESTS=ON $SHARED_FLAG + } catch { + Write-Host "Visual Studio 18 2026 generator not available, trying alternative detection..." + cmake ../.. -A x64 -DCCAP_BUILD_TESTS=ON $SHARED_FLAG + } + + - name: Build + if: env.VS_2026_AVAILABLE == 'true' + run: | + cd "build/${{ matrix.config }}-${{ matrix.library_type }}" + cmake --build . --config ${{ matrix.config }} --parallel + + - name: Verify library type + if: env.VS_2026_AVAILABLE == 'true' + shell: bash + working-directory: build/${{ matrix.config }}-${{ matrix.library_type }}/${{ matrix.config }} + run: | + echo "Checking built libraries:" + ls -la | grep -E "ccap" || echo "No ccap libraries found" + + # Verify library type + # Debug versions have 'd' suffix, Release versions don't + if [ "${{ matrix.config }}" = "Debug" ]; then + LIB_BASENAME="ccapd" + DLL_NAME="ccapd.dll" + else + LIB_BASENAME="ccap" + DLL_NAME="ccap.dll" + fi + + if [ "${{ matrix.library_type }}" = "shared" ]; then + if [ -f "$DLL_NAME" ]; then + echo "✓ Windows shared library $DLL_NAME successfully built with VS2026" + # Check if import library exists + if [ -f "${LIB_BASENAME}.lib" ]; then + echo "✓ Windows import library ${LIB_BASENAME}.lib also created" + fi + else + echo "✗ Windows shared library $DLL_NAME not found" + exit 1 + fi + else + if [ -f "${LIB_BASENAME}.lib" ]; then + echo "✓ Windows static library ${LIB_BASENAME}.lib successfully built with VS2026" + else + echo "✗ Windows static library ${LIB_BASENAME}.lib not found" + exit 1 + fi + fi + + - name: Test shared library linking (Windows VS2026) + if: env.VS_2026_AVAILABLE == 'true' && matrix.library_type == 'shared' + shell: bash + working-directory: build/${{ matrix.config }}-${{ matrix.library_type }}/${{ matrix.config }} + run: | + echo "Testing Windows shared library linking with VS2026..." + + # Create a simple test program + cat > test_shared.cpp << 'EOF' + #include "ccap_c.h" + #include + int main() { + const char* version = ccap_get_version(); + printf("Library version: %s\n", version ? version : "unknown"); + CcapProvider* provider = ccap_provider_create(); + if (provider) { + printf("Provider created successfully\n"); + ccap_provider_destroy(provider); + return 0; + } + return 1; + } + EOF + + # Find Visual Studio 2026 compiler + VCVARS_PATH=$(find "/c/Program Files/Microsoft Visual Studio/2026" -name "vcvars64.bat" 2>/dev/null | head -n1) + + if [ -n "$VCVARS_PATH" ]; then + echo "Using Visual Studio 2026 environment from: $VCVARS_PATH" + # Convert path for cmd + VCVARS_WIN_PATH=$(echo "$VCVARS_PATH" | sed 's|/c/|C:/|g' | sed 's|/|\\|g') + + # Determine library names based on config + if [ "${{ matrix.config }}" = "Debug" ]; then + LIB_NAME="ccapd.lib" + DLL_NAME="ccapd.dll" + else + LIB_NAME="ccap.lib" + DLL_NAME="ccap.dll" + fi + + # Create a temporary batch file to avoid quote escaping issues + cat > compile_test.bat << EOF + @echo off + call "$VCVARS_WIN_PATH" + set "INCLUDE_DIR=%GITHUB_WORKSPACE%\\include" + if not exist "%INCLUDE_DIR%" ( + echo Include directory not found: %INCLUDE_DIR% + exit /b 1 + ) + cl /I"%INCLUDE_DIR%" test_shared.cpp $LIB_NAME /Fe:test_shared.exe + EOF + + # Execute the batch file + cmd //c compile_test.bat + + # Ensure DLL is available beside the test executable + if [ ! -f "./$DLL_NAME" ]; then + DLL_PATH=$(find .. -name "$DLL_NAME" -print -quit) + if [ -z "$DLL_PATH" ]; then + echo "✗ Windows shared library $DLL_NAME not found for runtime" + exit 1 + fi + cp "$DLL_PATH" . + fi + ./test_shared.exe + echo "✓ Windows shared library linking test with VS2026 passed" + else + echo "⚠ Visual Studio 2026 compiler not found, skipping link test" + fi + + - name: Run Unit Tests + if: env.VS_2026_AVAILABLE == 'true' + shell: bash + run: | + # Create symbolic links to make test script work with new build directory structure + mkdir -p build/tests + + # Create symbolic link for the config directory + if [ ! -L "build/${{ matrix.config }}" ]; then + ln -sf "${{ matrix.config }}-${{ matrix.library_type }}" "build/${{ matrix.config }}" + fi + + # Create symbolic link for the tests directory to match expected path structure + if [ ! -L "build/tests/${{ matrix.config }}" ]; then + ln -sf "../${{ matrix.config }}-${{ matrix.library_type }}/tests/${{ matrix.config }}" "build/tests/${{ matrix.config }}" + fi + + cd scripts + if [ "${{ matrix.config }}" == "Debug" ]; then + # Set library path for shared library tests + if [ "${{ matrix.library_type }}" = "shared" ]; then + export PATH="$PWD/../build/${{ matrix.config }}-${{ matrix.library_type }}/${{ matrix.config }}:$PATH" + fi + ./run_tests.sh --functional --skip-build + else + # Set library path for shared library tests + if [ "${{ matrix.library_type }}" = "shared" ]; then + export PATH="$PWD/../build/${{ matrix.config }}-${{ matrix.library_type }}/${{ matrix.config }}:$PATH" + fi + ./run_tests.sh --performance --skip-build + fi + + - name: Upload artifacts + if: env.VS_2026_AVAILABLE == 'true' + uses: actions/upload-artifact@v4 + with: + name: ccap-windows-vs2026-${{ matrix.config }}-${{ matrix.library_type }} + path: | + build/${{ matrix.config }}-${{ matrix.library_type }}/${{ matrix.config }}/ccap*.* + build/${{ matrix.config }}-${{ matrix.library_type }}/${{ matrix.config }}/0-print_camera.exe + build/${{ matrix.config }}-${{ matrix.library_type }}/${{ matrix.config }}/1-minimal_example.exe + build/${{ matrix.config }}-${{ matrix.library_type }}/${{ matrix.config }}/2-capture_grab.exe + build/${{ matrix.config }}-${{ matrix.library_type }}/${{ matrix.config }}/3-capture_callback.exe + build/${{ matrix.config }}-${{ matrix.library_type }}/*_results.xml + # Use 'warn' instead of 'error' since VS 2026 build is optional (may not be available on all runners) + if-no-files-found: warn + + build-mingw: + name: Windows Build MinGW (${{ matrix.config }}-${{ matrix.library_type }}) + runs-on: windows-latest + + strategy: + matrix: + config: [Debug, Release] + library_type: [static, shared] + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Setup MinGW-w64 + uses: msys2/setup-msys2@v2 + with: + msystem: MINGW64 + update: true + install: >- + mingw-w64-x86_64-toolchain + mingw-w64-x86_64-cmake + mingw-w64-x86_64-ninja + make + + - name: Configure CMake with MinGW + shell: msys2 {0} + run: | + SHARED_FLAG="" + if [ "${{ matrix.library_type }}" = "shared" ]; then + SHARED_FLAG="-DCCAP_BUILD_SHARED=ON" + echo "Configuring Windows build ${{ matrix.config }} with MinGW - SHARED LIBRARY (DLL)" + else + echo "Configuring Windows build ${{ matrix.config }} with MinGW - STATIC LIBRARY" + fi + + # Check compiler version + gcc --version + cmake --version + + mkdir -p "build/${{ matrix.config }}-${{ matrix.library_type }}" + cd "build/${{ matrix.config }}-${{ matrix.library_type }}" + cmake ../.. -G "Ninja" -DCMAKE_BUILD_TYPE=${{ matrix.config }} -DCCAP_BUILD_TESTS=ON $SHARED_FLAG + + - name: Build + shell: msys2 {0} + run: | + cd "build/${{ matrix.config }}-${{ matrix.library_type }}" + cmake --build . --parallel + + - name: Verify library type + shell: msys2 {0} + working-directory: build/${{ matrix.config }}-${{ matrix.library_type }} + run: | + echo "Checking built libraries:" + ls -la | grep -E "ccap" || echo "No ccap libraries found" + + if [ "${{ matrix.library_type }}" = "shared" ]; then + # MinGW shared libraries use .dll extension + if [ -f "libccap.dll" ]; then + echo "✓ Windows shared library libccap.dll successfully built with MinGW" + else + echo "✗ Windows shared library libccap.dll not found" + exit 1 + fi + else + # MinGW static libraries use .a extension + if [ -f "libccap.a" ]; then + echo "✓ Windows static library libccap.a successfully built with MinGW" + else + echo "✗ Windows static library libccap.a not found" + exit 1 + fi + fi + + - name: Test shared library linking (Windows MinGW) + if: matrix.library_type == 'shared' + shell: msys2 {0} + working-directory: build/${{ matrix.config }}-${{ matrix.library_type }} + run: | + echo "Testing Windows shared library linking with MinGW..." + + # Create a simple test program + cat > test_shared.cpp << 'EOF' + #include "ccap_c.h" + #include + int main() { + const char* version = ccap_get_version(); + printf("Library version: %s\n", version ? version : "unknown"); + CcapProvider* provider = ccap_provider_create(); + if (provider) { + printf("Provider created successfully\n"); + ccap_provider_destroy(provider); + return 0; + } + return 1; + } + EOF + + # Compile and run with shared library + g++ -I../../include test_shared.cpp -L. -lccap -o test_shared.exe + ./test_shared.exe + echo "✓ Windows shared library linking test with MinGW passed" + + - name: Run Unit Tests + if: matrix.config == 'Release' + shell: msys2 {0} + run: | + # Create symbolic links to make test script work with new build directory structure + mkdir -p build + if [ ! -L "build/${{ matrix.config }}" ]; then + ln -sf "${{ matrix.config }}-${{ matrix.library_type }}" "build/${{ matrix.config }}" + fi + + cd scripts + # Set library path for shared library tests + if [ "${{ matrix.library_type }}" = "shared" ]; then + export PATH="$PWD/../build/${{ matrix.config }}-${{ matrix.library_type }}:$PATH" + fi + ./run_tests.sh --functional --skip-build + + - name: Upload artifacts + uses: actions/upload-artifact@v4 + with: + name: ccap-windows-mingw-${{ matrix.config }}-${{ matrix.library_type }} + path: | + build/${{ matrix.config }}-${{ matrix.library_type }}/libccap.* + build/${{ matrix.config }}-${{ matrix.library_type }}/0-print_camera.exe + build/${{ matrix.config }}-${{ matrix.library_type }}/1-minimal_example.exe + build/${{ matrix.config }}-${{ matrix.library_type }}/2-capture_grab.exe + build/${{ matrix.config }}-${{ matrix.library_type }}/3-capture_callback.exe + build/${{ matrix.config }}-${{ matrix.library_type }}/*_results.xml + if-no-files-found: warn \ No newline at end of file diff --git a/BUILD_AND_INSTALL.md b/BUILD_AND_INSTALL.md index 7340812..5b513ba 100644 --- a/BUILD_AND_INSTALL.md +++ b/BUILD_AND_INSTALL.md @@ -5,8 +5,8 @@ This document describes how to build, install, and use the ccap library. ## Prerequisites - **macOS**: Xcode Command Line Tools or full Xcode -- **Windows**: Visual Studio 2019+ or Build Tools for Visual Studio -- **Common**: CMake 3.14+ +- **Windows**: Visual Studio 2019+ or Build Tools for Visual Studio (including VS 2026), or MinGW-w64 +- **Common**: CMake 3.14+ (CMake 3.31+ recommended for MSVC 2026 support) ## Quick Start diff --git a/README.md b/README.md index 7e05852..8234194 100644 --- a/README.md +++ b/README.md @@ -206,12 +206,12 @@ int main() { | Platform | Compiler | System Requirements | |----------|----------|---------------------| -| **Windows** | MSVC 2019+ | DirectShow | +| **Windows** | MSVC 2019+ (including 2026) / MinGW-w64 | DirectShow | | **macOS** | Xcode 11+ | macOS 10.13+ | | **iOS** | Xcode 11+ | iOS 13.0+ | | **Linux** | GCC 7+ / Clang 6+ | V4L2 (Linux 2.6+) | -**Build Requirements**: CMake 3.14+, C++17 (C++ interface), C99 (C interface) +**Build Requirements**: CMake 3.14+ (3.31+ recommended for MSVC 2026), C++17 (C++ interface), C99 (C interface) ### Supported Linux Distributions diff --git a/README.zh-CN.md b/README.zh-CN.md index 993102a..f066a78 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -167,12 +167,12 @@ int main() { | 平台 | 编译器 | 系统要求 | |------|--------|----------| -| **Windows** | MSVC 2019+ | DirectShow | +| **Windows** | MSVC 2019+(包括 2026)/ MinGW-w64 | DirectShow | | **macOS** | Xcode 11+ | macOS 10.13+ | | **iOS** | Xcode 11+ | iOS 13.0+ | | **Linux** | GCC 7+ / Clang 6+ | V4L2 (Linux 2.6+) | -**构建要求**:CMake 3.14+,C++17(C++ 接口),C99(C 接口) +**构建要求**:CMake 3.14+(推荐使用 3.31+ 以支持 MSVC 2026),C++17(C++ 接口),C99(C 接口) ### 支持的 Linux 发行版