diff --git a/.github/workflows/build-wheel.yml b/.github/workflows/build-wheel.yml index 819b4d0b..d7b5fcaf 100644 --- a/.github/workflows/build-wheel.yml +++ b/.github/workflows/build-wheel.yml @@ -63,7 +63,7 @@ jobs: cd /io && /opt/python/cp310-cp310/bin/pip install -r requirements.txt -r requirements-dev.txt && /opt/python/cp310-cp310/bin/pip install toml && - C2PA_LIBS_PLATFORM=\"${{ inputs.architecture == 'aarch64' && 'aarch64-unknown-linux-gnu' || 'x86_64-unknown-linux-gnu' }}\" /opt/python/cp310-cp310/bin/python scripts/download_artifacts.py $C2PA_VERSION && + C2PA_LIBS_PLATFORM=\"${{ format('{0}', inputs.architecture == 'aarch64' && 'aarch64-unknown-linux-gnu' || 'x86_64-unknown-linux-gnu') }}\" /opt/python/cp310-cp310/bin/python scripts/download_artifacts.py $C2PA_VERSION && for PYBIN in /opt/python/cp3{10,11}-*/bin; do \${PYBIN}/pip install --upgrade pip wheel && \${PYBIN}/pip install toml && diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 8740a0f1..4ac6a324 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -51,7 +51,7 @@ jobs: strategy: fail-fast: false matrix: - os: [ macos-latest, ubuntu-latest ] + os: [ macos-latest, ubuntu-latest, ubuntu-24.04-arm ] steps: - name: Checkout repository @@ -178,6 +178,8 @@ jobs: include: - target: x86_64 runs-on: ubuntu-24.04 + - target: aarch64 + runs-on: ubuntu-24.04-arm if: | github.event_name != 'pull_request' || github.event.pull_request.author_association == 'COLLABORATOR' || @@ -194,6 +196,8 @@ jobs: include: - target: x86_64 runs-on: ubuntu-24.04 + - target: aarch64 + runs-on: ubuntu-24.04-arm if: | github.event_name != 'pull_request' || github.event.pull_request.author_association == 'COLLABORATOR' || @@ -444,6 +448,10 @@ jobs: pattern: wheels-* path: dist merge-multiple: true + - name: List downloaded artifacts + run: | + echo "Downloaded Artifacts" + ls -la dist/ - name: Publish to TestPyPI uses: pypa/gh-action-pypi-publish@release/v1 with: @@ -453,4 +461,3 @@ jobs: verbose: true # Uncomment below for test runs, otherwise fails on existing packages being reuploaded skip-existing: true - diff --git a/pyproject.toml b/pyproject.toml index 3ef2f737..e2149481 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "c2pa-python" -version = "0.10.0" +version = "0.11.0" requires-python = ">=3.10" description = "Python bindings for the C2PA Content Authenticity Initiative (CAI) library" readme = { file = "README.md", content-type = "text/markdown" } diff --git a/scripts/download_artifacts.py b/scripts/download_artifacts.py index d8399618..3da65246 100644 --- a/scripts/download_artifacts.py +++ b/scripts/download_artifacts.py @@ -46,16 +46,21 @@ def get_platform_identifier(): Returns one of: - universal-apple-darwin (for Mac) - x86_64-pc-windows-msvc (for Windows 64-bit) - - x86_64-unknown-linux-gnu (for Linux 64-bit) + - x86_64-unknown-linux-gnu (for Linux x86_64) + - aarch64-unknown-linux-gnu (for Linux ARM64) """ system = platform.system().lower() + machine = platform.machine().lower() if system == "darwin": return "universal-apple-darwin" elif system == "windows": return "x86_64-pc-windows-msvc" elif system == "linux": - return "x86_64-unknown-linux-gnu" + if machine in ["arm64", "aarch64"]: + return "aarch64-unknown-linux-gnu" + else: + return "x86_64-unknown-linux-gnu" else: raise ValueError(f"Unsupported operating system: {system}") @@ -105,8 +110,12 @@ def copy_artifacts_to_root(): print("Copying artifacts from scripts/artifacts to root...") if ROOT_ARTIFACTS_DIR.exists(): shutil.rmtree(ROOT_ARTIFACTS_DIR) + print(f"Copying from {SCRIPTS_ARTIFACTS_DIR} to {ROOT_ARTIFACTS_DIR}") shutil.copytree(SCRIPTS_ARTIFACTS_DIR, ROOT_ARTIFACTS_DIR) print("Done copying artifacts") + print("\nFolder content of artifacts directory:") + for item in sorted(ROOT_ARTIFACTS_DIR.iterdir()): + print(f" {item.name}") def main(): if len(sys.argv) < 2: @@ -126,6 +135,8 @@ def main(): if env_platform: print(f"Using platform from environment variable C2PA_LIBS_PLATFORM: {env_platform}") platform_id = env_platform or get_platform_identifier() + print("Looking up releases for platform id: ", platform_id) + print("Environment variable set for lookup: ", env_platform) platform_source = "environment variable" if env_platform else "auto-detection" print(f"Target platform: {platform_id} (set through{platform_source})") diff --git a/setup.py b/setup.py index 2d866857..1216abdc 100644 --- a/setup.py +++ b/setup.py @@ -30,6 +30,7 @@ def get_version(): 'x86_64-apple-darwin': 'dylib', 'x86_64-pc-windows-msvc': 'dll', 'x86_64-unknown-linux-gnu': 'so', + 'aarch64-unknown-linux-gnu': 'so', # Add ARM Linux support } # Directory structure @@ -51,6 +52,7 @@ def get_platform_identifier(cpu_arch = None) -> str: - x86_64-apple-darwin (for Mac x86_64) - x86_64-pc-windows-msvc (for Windows 64-bit) - x86_64-unknown-linux-gnu (for Linux 64-bit) + - aarch64-unknown-linux-gnu (for Linux ARM64) """ system = platform.system().lower() @@ -66,6 +68,8 @@ def get_platform_identifier(cpu_arch = None) -> str: elif system == "windows": return "x86_64-pc-windows-msvc" elif system == "linux": + if platform.machine() == "aarch64": + return "aarch64-unknown-linux-gnu" return "x86_64-unknown-linux-gnu" else: raise ValueError(f"Unsupported operating system: {system}") diff --git a/src/c2pa/lib.py b/src/c2pa/lib.py index fb38645c..f0382874 100644 --- a/src/c2pa/lib.py +++ b/src/c2pa/lib.py @@ -62,6 +62,8 @@ def get_platform_identifier(cpu_arch: Optional[CPUArchitecture] = None) -> str: elif system == "windows": return "x86_64-pc-windows-msvc" elif system == "linux": + if _get_architecture() in ['arm64', 'aarch64']: + return "aarch64-unknown-linux-gnu" return "x86_64-unknown-linux-gnu" else: raise ValueError(f"Unsupported operating system: {system}") @@ -245,8 +247,11 @@ def dynamically_load_library( # If specific library name is provided, only load that one lib = _load_single_library(lib_name, possible_paths) if not lib: + platform_id = get_platform_identifier() + current_arch = _get_architecture() logger.error(f"Could not find {lib_name} in any of the search paths: {[str(p) for p in possible_paths]}") - raise RuntimeError(f"Could not find {lib_name} in any of the search paths") + logger.error(f"Platform: {platform_id}, Architecture: {current_arch}") + raise RuntimeError(f"Could not find {lib_name} in any of the search paths (Platform: {platform_id}, Architecture: {current_arch})") return lib # Default path (no library name provided in the environment)