diff --git a/.github/workflows/build-wheel.yml b/.github/workflows/build-wheel.yml index 78f53b34..33352fb8 100644 --- a/.github/workflows/build-wheel.yml +++ b/.github/workflows/build-wheel.yml @@ -88,7 +88,17 @@ jobs: echo "Verifying wheels using twine check" twine check dist/* - - name: Build Windows wheel (x64) + - name: Install ARM64 OpenSSL via vcpkg (Windows ARM64) + if: runner.os == 'Windows' && inputs.architecture == 'arm64' + shell: pwsh + run: | + # Static linking avoids runtime DLL load issues. + & "$env:VCPKG_INSTALLATION_ROOT\vcpkg.exe" install openssl:arm64-windows-static-md + $vcpkgRoot = "$env:VCPKG_INSTALLATION_ROOT\installed\arm64-windows-static-md" + echo "OPENSSL_DIR=$vcpkgRoot" >> $env:GITHUB_ENV + echo "OPENSSL_STATIC=1" >> $env:GITHUB_ENV + + - name: Build Windows wheel if: runner.os == 'Windows' shell: pwsh run: | @@ -107,6 +117,7 @@ jobs: # Download native artifacts Write-Host "Starting artifact download process..." Write-Host "C2PA_VERSION: $env:C2PA_VERSION" + Write-Host "Architecture: ${{ inputs.architecture }}" python scripts/download_artifacts.py "$env:C2PA_VERSION" @@ -115,8 +126,15 @@ jobs: Write-Host "src/c2pa/libs directory contents:" Get-ChildItem -Recurse -Path src/c2pa/libs + # Set platform tag based on architecture + if ("${{ inputs.architecture }}" -eq "arm64") { + $PLATFORM_TAG = "win_arm64" + } else { + $PLATFORM_TAG = "win_amd64" + } + # Build wheel - python setup.py bdist_wheel --plat-name win_amd64 + python setup.py bdist_wheel --plat-name $PLATFORM_TAG # Verify wheel structure twine check dist/* @@ -188,4 +206,4 @@ jobs: with: name: ${{ inputs.artifact-name }} path: dist - if-no-files-found: error \ No newline at end of file + if-no-files-found: error diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 6cab3c53..e970c93a 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -128,7 +128,16 @@ jobs: github.event.pull_request.user.login == 'dependabot[bot]' || contains(github.event.pull_request.labels.*.name, 'safe to test') - runs-on: windows-latest + runs-on: ${{ matrix.runs-on }} + + strategy: + fail-fast: false + matrix: + include: + - runs-on: windows-latest + python-version: "3.10" + - runs-on: windows-11-arm + python-version: "3.11" # win-arm runner needs 3.11 atleast steps: - name: Checkout repository @@ -137,9 +146,20 @@ jobs: - name: Set up Python uses: actions/setup-python@v5 with: - python-version: "3.10" + python-version: ${{ matrix.python-version }} cache: "pip" + - name: Install ARM64 OpenSSL via vcpkg (Windows ARM64) + if: matrix.runs-on == 'windows-11-arm' + shell: pwsh + run: | + # Pre-installed OpenSSL on runner fails build. + # Static OpenSSL to avoid runtime DLL load complexities. + & "$env:VCPKG_INSTALLATION_ROOT\vcpkg.exe" install openssl:arm64-windows-static-md + $vcpkgRoot = "$env:VCPKG_INSTALLATION_ROOT\installed\arm64-windows-static-md" + echo "OPENSSL_DIR=$vcpkgRoot" >> $env:GITHUB_ENV + echo "OPENSSL_STATIC=1" >> $env:GITHUB_ENV + - name: Install project dependencies run: python -m pip install -r requirements.txt @@ -277,13 +297,17 @@ jobs: python-version: "3.10" architecture: ${{ matrix.target }} artifact-name: wheels-windows-${{ matrix.target }} - runs-on: windows-latest + runs-on: ${{ matrix.runs-on }} c2pa-version: ${{ needs.read-version.outputs.c2pa-native-version }} secrets: github-token: ${{ secrets.GITHUB_TOKEN }} strategy: matrix: - target: [x64] + include: + - target: x64 + runs-on: windows-latest + - target: arm64 + runs-on: windows-11-arm if: | github.event_name != 'pull_request' || github.event.pull_request.author_association == 'COLLABORATOR' || @@ -294,10 +318,17 @@ jobs: test-built-windows-wheel: name: Test Windows built wheel needs: build-windows-wheel - runs-on: windows-latest + runs-on: ${{ matrix.runs-on }} strategy: + fail-fast: false matrix: - target: [x64] + include: + - target: x64 + runs-on: windows-latest + python-version: "3.10" + - target: arm64 + runs-on: windows-11-arm + python-version: "3.11" # win-arm runner needs 3.11 atleast if: | github.event_name != 'pull_request' || github.event.pull_request.author_association == 'COLLABORATOR' || @@ -312,7 +343,7 @@ jobs: - name: Set up Python uses: actions/setup-python@v5 with: - python-version: "3.10" + python-version: ${{ matrix.python-version }} cache: "pip" - name: Download wheel artifacts @@ -321,6 +352,16 @@ jobs: name: wheels-windows-${{ matrix.target }} path: dist + - name: Install ARM64 OpenSSL via vcpkg (Windows ARM64) + if: matrix.runs-on == 'windows-11-arm' + shell: pwsh + run: | + # Static linking avoids runtime DLL load issues. + & "$env:VCPKG_INSTALLATION_ROOT\vcpkg.exe" install openssl:arm64-windows-static-md + $vcpkgRoot = "$env:VCPKG_INSTALLATION_ROOT\installed\arm64-windows-static-md" + echo "OPENSSL_DIR=$vcpkgRoot" >> $env:GITHUB_ENV + echo "OPENSSL_STATIC=1" >> $env:GITHUB_ENV + - name: Create and activate virtual environment run: | python -m venv venv @@ -332,15 +373,7 @@ jobs: $wheel = Get-ChildItem -Path dist -Filter "c2pa_python-*.whl" | Select-Object -First 1 if (-not $wheel) { Write-Error "No wheel file found in dist directory"; exit 1 } pip install $wheel.FullName - - - name: Run unittest tests on installed wheel - run: | - .\venv\Scripts\activate - python .\tests\test_unit_tests.py - - - name: Install pytest (in venv) - run: | - .\venv\Scripts\activate + pip install -r requirements.txt pip install pytest - name: Run tests with pytest (venv) diff --git a/requirements-dev.txt b/requirements-dev.txt index ab7ae804..1077f810 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -17,7 +17,7 @@ flake8==7.3.0 # Test dependencies (for callback signers) cryptography==47.0.0 - + # Documentation Sphinx>=7.3.0 sphinx-autoapi>=3.0.0 diff --git a/scripts/download_artifacts.py b/scripts/download_artifacts.py index c3394494..b0cd33f4 100644 --- a/scripts/download_artifacts.py +++ b/scripts/download_artifacts.py @@ -91,7 +91,7 @@ def get_platform_identifier(target_arch=None): else: return "universal-apple-darwin" elif system == "windows": - if target_arch == "arm64": + if target_arch == "arm64" or machine in ["arm64", "aarch64"]: return "aarch64-pc-windows-msvc" else: return "x86_64-pc-windows-msvc" diff --git a/setup.py b/setup.py index 489472c1..ddf6e985 100644 --- a/setup.py +++ b/setup.py @@ -41,6 +41,7 @@ def get_version(): 'aarch64-apple-darwin': 'dylib', 'x86_64-apple-darwin': 'dylib', 'x86_64-pc-windows-msvc': 'dll', + 'aarch64-pc-windows-msvc': 'dll', 'x86_64-unknown-linux-gnu': 'so', 'aarch64-unknown-linux-gnu': 'so', } @@ -78,7 +79,7 @@ def get_platform_identifier(target_arch=None) -> str: else: return "universal-apple-darwin" elif system == "windows": - if target_arch == "arm64": + if target_arch == "arm64" or platform.machine().lower() in ["arm64", "aarch64"]: return "aarch64-pc-windows-msvc" else: return "x86_64-pc-windows-msvc" diff --git a/src/c2pa/lib.py b/src/c2pa/lib.py index e14f3d6b..b1caa104 100644 --- a/src/c2pa/lib.py +++ b/src/c2pa/lib.py @@ -37,7 +37,8 @@ def get_platform_identifier() -> str: - universal-apple-darwin (for Mac universal) - aarch64-apple-darwin (for Mac ARM64) - x86_64-apple-darwin (for Mac x86_64) - - x86_64-pc-windows-msvc (for Windows 64-bit) + - x86_64-pc-windows-msvc (for Windows x64) + - aarch64-pc-windows-msvc (for Windows ARM64) - x86_64-unknown-linux-gnu (for Linux 64-bit) - aarch64-unknown-linux-gnu (for Linux ARM) """ @@ -54,6 +55,8 @@ def get_platform_identifier() -> str: else: return "universal-apple-darwin" elif system == "windows": + if _get_architecture() in [CPUArchitecture.ARM64.value, CPUArchitecture.AARCH64.value]: + return "aarch64-pc-windows-msvc" return "x86_64-pc-windows-msvc" elif system == "linux": if _get_architecture() in [CPUArchitecture.ARM64.value, CPUArchitecture.AARCH64.value]: @@ -81,7 +84,7 @@ def _get_architecture() -> str: elif sys.platform == "win32": # win32 will cover all Windows versions # (the 32 is a historical quirk) - return platform.machine() + return platform.machine().lower() else: raise RuntimeError(f"Unsupported platform: {sys.platform}")