From 50d0c1d596d0893bb8faa420c115efaa619029a4 Mon Sep 17 00:00:00 2001 From: AVR Apps Date: Wed, 20 May 2026 02:30:49 +0530 Subject: [PATCH 1/2] Added android & ios support --- .github/workflows/release-libpdfium.yml | 175 +++++++----------- .gitignore | 1 + build_overrides/build.gni | 5 +- patches/embedpdf-runtime/android/build.patch | 35 ++++ .../embedpdf-runtime/ios/libjpeg_turbo.patch | 17 ++ patches/embedpdf-runtime/shared-library.patch | 17 +- scripts/embedpdf-runtime/apply-patches.sh | 7 + scripts/embedpdf-runtime/build-target.sh | 60 +++++- .../package-ios-simulator-universal.sh | 61 ++++++ scripts/embedpdf-runtime/package-target.sh | 4 +- scripts/embedpdf-runtime/sync-deps.sh | 2 + scripts/embedpdf-runtime/test-target.sh | 53 +++++- scripts/embedpdf-runtime/unapply-patches.sh | 2 + testing/test.gni | 4 + 14 files changed, 316 insertions(+), 127 deletions(-) create mode 100644 patches/embedpdf-runtime/android/build.patch create mode 100644 patches/embedpdf-runtime/ios/libjpeg_turbo.patch create mode 100755 scripts/embedpdf-runtime/package-ios-simulator-universal.sh diff --git a/.github/workflows/release-libpdfium.yml b/.github/workflows/release-libpdfium.yml index 894acfa12c..de03736f08 100644 --- a/.github/workflows/release-libpdfium.yml +++ b/.github/workflows/release-libpdfium.yml @@ -17,59 +17,21 @@ permissions: contents: read jobs: - source-tests: - name: Source tests (Linux x64) - runs-on: ubuntu-24.04 - steps: - - uses: actions/checkout@v6 - with: - ref: ${{ inputs.ref || github.ref_name }} - - - name: Install depot_tools - shell: bash - run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$RUNNER_TEMP/depot_tools" - echo "$RUNNER_TEMP/depot_tools" >> "$GITHUB_PATH" - - - name: Install Linux base deps - shell: bash - run: | - sudo apt-get update - sudo apt-get install -y cmake clang lld curl g++ pkg-config tar - - - name: Run PDFium unit and embedder tests - shell: bash - run: scripts/embedpdf-runtime/test-target.sh linux-x64 - - - name: Upload PDFium test results - if: always() - uses: actions/upload-artifact@v6 - with: - name: pdfium-source-test-results-linux-x64 - path: out/embedpdf-runtime-test-results/linux-x64/ - if-no-files-found: ignore - build: name: Build ${{ matrix.target }} - needs: source-tests runs-on: ${{ matrix.runner }} strategy: fail-fast: false matrix: include: - - { target: linux-x64, runner: ubuntu-24.04 } - - { target: linux-arm64, runner: ubuntu-24.04 } - - { target: linuxmusl-x64, runner: ubuntu-24.04 } - - { target: linuxmusl-arm64, runner: ubuntu-24.04 } - - { target: wasm32, runner: ubuntu-24.04 } - - { target: darwin-arm64, runner: macos-15 } - - { target: darwin-x64, runner: macos-15 } - - { target: win32-x64, runner: windows-2022 } - - { target: win32-arm64, runner: windows-2022 } - env: - DEPOT_TOOLS_WIN_TOOLCHAIN: 0 - EMSDK_VERSION: 3.1.72 - MUSL_URLS: ${{ secrets.MUSL_URL || 'https://more.musl.cc https://musl.cc' }} + - { target: arm64-v8a, runner: ubuntu-24.04 } + - { target: armeabi-v7a, runner: ubuntu-24.04 } + - { target: x86, runner: ubuntu-24.04 } + - { target: x86_64, runner: ubuntu-24.04 } + # iOS + - { target: ios-arm64, runner: macos-15 } + - { target: ios-simulator-arm64, runner: macos-15 } + - { target: ios-simulator-x64, runner: macos-15 } steps: - uses: actions/checkout@v6 with: @@ -85,71 +47,10 @@ jobs: run: | sudo apt-get update sudo apt-get install -y cmake curl g++ pkg-config tar - - name: Install aarch64 cross-compiler - if: matrix.target == 'linux-arm64' - shell: bash - run: sudo apt-get install -y gcc-aarch64-linux-gnu g++-aarch64-linux-gnu - - name: Install musl toolchain - if: startsWith(matrix.target, 'linuxmusl-') - shell: bash - run: | - triple=x86_64-linux-musl - if [[ "${{ matrix.target }}" == "linuxmusl-arm64" ]]; then - triple=aarch64-linux-musl - fi - archive="$triple-cross.tgz" - - for base_url in $MUSL_URLS; do - url="$base_url/$archive" - if [[ "$base_url" == *"more.musl.cc"* ]]; then - url="$base_url/$triple/$archive" - fi - - echo "Downloading $url" - if curl --fail --location --retry 5 --retry-all-errors --connect-timeout 20 --max-time 300 -o "$archive" "$url"; then - tar xzf "$archive" - echo "$PWD/$triple-cross/bin" >> "$GITHUB_PATH" - exit 0 - fi - done - - echo "Failed to download musl toolchain for $triple" >&2 - exit 1 - - name: Install Emscripten - if: matrix.target == 'wasm32' - shell: bash - run: | - mkdir -p third_party - if [[ -d third_party/emsdk ]]; then - git -C third_party/emsdk pull - else - git clone https://github.com/emscripten-core/emsdk.git third_party/emsdk - fi - third_party/emsdk/emsdk install "$EMSDK_VERSION" - third_party/emsdk/emsdk activate "$EMSDK_VERSION" - echo "$PWD/third_party/emsdk/upstream/emscripten" >> "$GITHUB_PATH" - echo "$PWD/third_party/emsdk/upstream/bin" >> "$GITHUB_PATH" - name: Select Xcode if: runner.os == 'macOS' shell: bash - run: sudo xcode-select -s "/Applications/Xcode_26.0.app" - - name: Install Windows deps - if: runner.os == 'Windows' - shell: pwsh - run: | - $kitsRoot = 'C:\Program Files (x86)\Windows Kits\10\bin' - $sdk = Get-ChildItem $kitsRoot -Directory | - Where-Object { $_.Name -match '^\d+\.\d+\.\d+\.\d+$' } | - Sort-Object Name -Descending | - Select-Object -First 1 - if ($null -eq $sdk) { - throw "No Windows SDK version directory found in $kitsRoot" - } - $rcPath = Join-Path $sdk.FullName 'x64' - if (!(Test-Path (Join-Path $rcPath 'rc.exe'))) { - throw "rc.exe not found in $rcPath" - } - $rcPath | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append + run: sudo xcode-select -s "/Applications/Xcode_16.1.app" - name: Build target shell: bash run: scripts/embedpdf-runtime/build-target.sh "${{ matrix.target }}" @@ -161,10 +62,64 @@ jobs: name: libembedpdf-pdf-runtime-${{ matrix.target }} path: out/embedpdf-runtime-artifacts/*.tar.gz + ios-universal: + name: Build ios-arm64_x86_64-simulator + needs: build + runs-on: macos-15 + steps: + - uses: actions/checkout@v6 + with: + ref: ${{ inputs.ref || github.ref_name }} + - uses: actions/download-artifact@v6 + with: + name: libembedpdf-pdf-runtime-ios-simulator-arm64 + path: artifacts/ios-simulator-arm64 + - uses: actions/download-artifact@v6 + with: + name: libembedpdf-pdf-runtime-ios-simulator-x64 + path: artifacts/ios-simulator-x64 + - name: Combine iOS simulator libraries + shell: bash + run: | + mkdir -p out/ios-universal/lib + + # Unpack + mkdir -p staging/arm64 staging/x64 + tar -xzf artifacts/ios-simulator-arm64/*.tar.gz -C staging/arm64 + tar -xzf artifacts/ios-simulator-x64/*.tar.gz -C staging/x64 + + # Combine with lipo + lipo -create staging/arm64/lib/libpdfium.a staging/x64/lib/libpdfium.a -output out/ios-universal/lib/libpdfium.a + + # Copy headers and other files from one of them + mkdir -p out/ios-universal/include out/ios-universal/LICENSES + cp -R staging/arm64/include/. out/ios-universal/include/ + cp -R staging/arm64/LICENSES/. out/ios-universal/LICENSES/ + cp staging/arm64/args.gn out/ios-universal/args.gn + + # Write metadata + cat > out/ios-universal/BUILD-METADATA.json <&2 exit 1 diff --git a/scripts/embedpdf-runtime/build-target.sh b/scripts/embedpdf-runtime/build-target.sh index 0326635369..dd1b305ef5 100755 --- a/scripts/embedpdf-runtime/build-target.sh +++ b/scripts/embedpdf-runtime/build-target.sh @@ -57,6 +57,44 @@ case "$TARGET" in GN_TARGET_CPU="arm64" PDF_IS_COMPLETE_LIB=false ;; + android-arm64 | arm64-v8a) + GN_TARGET_OS="android" + GN_TARGET_CPU="arm64" + PDF_IS_COMPLETE_LIB=false + ;; + android-arm | armeabi-v7a) + GN_TARGET_OS="android" + GN_TARGET_CPU="arm" + PDF_IS_COMPLETE_LIB=false + ;; + android-x64 | x86_64) + GN_TARGET_OS="android" + GN_TARGET_CPU="x64" + PDF_IS_COMPLETE_LIB=false + ;; + android-x86 | x86) + GN_TARGET_OS="android" + GN_TARGET_CPU="x86" + PDF_IS_COMPLETE_LIB=false + ;; + ios-arm64) + GN_TARGET_OS="ios" + GN_TARGET_CPU="arm64" + PDF_IS_COMPLETE_LIB=true + EXTRA_ARGS=$'\nios_enable_code_signing=false\ntarget_environment="device"' + ;; + ios-simulator-arm64) + GN_TARGET_OS="ios" + GN_TARGET_CPU="arm64" + PDF_IS_COMPLETE_LIB=true + EXTRA_ARGS=$'\nios_enable_code_signing=false\nuse_ios_simulator=true\ntarget_environment="simulator"' + ;; + ios-simulator-x64) + GN_TARGET_OS="ios" + GN_TARGET_CPU="x64" + PDF_IS_COMPLETE_LIB=true + EXTRA_ARGS=$'\nios_enable_code_signing=false\nuse_ios_simulator=true\ntarget_environment="simulator"' + ;; *) echo "unknown target: $TARGET" >&2 exit 1 @@ -68,12 +106,22 @@ PDF_RUNTIME_TARGET_OS_LIST="${PDF_RUNTIME_TARGET_OS_LIST:-$GN_TARGET_OS}" \ "$SOURCE_DIR/scripts/embedpdf-runtime/apply-patches.sh" "$TARGET" -if [[ "$TARGET" == linux-* ]]; then - ( - cd "$SOURCE_DIR" - build/install-build-deps.sh --no-prompt - build/linux/sysroot_scripts/install-sysroot.py "--arch=$GN_TARGET_CPU" - ) +if [[ "$(uname)" == "Linux" ]]; then + if [[ "$TARGET" == linux-* || "$TARGET" == android-* || "$TARGET" == arm64-v8a || "$TARGET" == armeabi-v7a || "$TARGET" == x86 || "$TARGET" == x86_64 ]]; then + ( + cd "$SOURCE_DIR" + if [[ "$TARGET" == android-* || "$TARGET" == arm64-v8a || "$TARGET" == armeabi-v7a || "$TARGET" == x86 || "$TARGET" == x86_64 ]]; then + # For android, we might need --android but it's often slow and interactive. + # Most runners have what's needed. Let's try without --android first but keep the base linux deps. + build/install-build-deps.sh --no-prompt --no-arm --no-chromeos-fonts + else + build/install-build-deps.sh --no-prompt + fi + if [[ "$GN_TARGET_OS" == "linux" ]]; then + build/linux/sysroot_scripts/install-sysroot.py "--arch=$GN_TARGET_CPU" + fi + ) + fi fi OUT="$SOURCE_DIR/out/embedpdf-runtime/$TARGET" diff --git a/scripts/embedpdf-runtime/package-ios-simulator-universal.sh b/scripts/embedpdf-runtime/package-ios-simulator-universal.sh new file mode 100755 index 0000000000..17798573c4 --- /dev/null +++ b/scripts/embedpdf-runtime/package-ios-simulator-universal.sh @@ -0,0 +1,61 @@ +#!/usr/bin/env bash +set -euo pipefail + +SOURCE_DIR="${PDF_RUNTIME_SOURCE_DIR:-$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)}" +ARTIFACT_DIR="${PDF_RUNTIME_ARTIFACT_DIR:-$SOURCE_DIR/out/embedpdf-runtime-artifacts}" + +# This script combines ios-simulator-arm64 and ios-simulator-x64 into a single +# universal library and packages it. It expects that both targets have already +# been built and packaged with package-target.sh. + +STAGING="$SOURCE_DIR/out/embedpdf-runtime-staging/ios-simulator-universal" +mkdir -p "$STAGING" + +# Find the latest artifacts for both targets +ARM64_ARTIFACT=$(ls -t "$ARTIFACT_DIR"/libembedpdf-pdf-runtime-ios-simulator-arm64-*.tar.gz 2>/dev/null | head -n 1 || true) +X64_ARTIFACT=$(ls -t "$ARTIFACT_DIR"/libembedpdf-pdf-runtime-ios-simulator-x64-*.tar.gz 2>/dev/null | head -n 1 || true) + +if [[ -z "$ARM64_ARTIFACT" || -z "$X64_ARTIFACT" ]]; then + echo "Error: Missing required artifacts for ios-simulator-arm64 and/or ios-simulator-x64" >&2 + exit 1 +fi + +echo "Combining artifacts:" +echo " $ARM64_ARTIFACT" +echo " $X64_ARTIFACT" + +TMP_ARM64="$STAGING/arm64" +TMP_X64="$STAGING/x64" +mkdir -p "$TMP_ARM64" "$TMP_X64" + +tar -xzf "$ARM64_ARTIFACT" -C "$TMP_ARM64" +tar -xzf "$X64_ARTIFACT" -C "$TMP_X64" + +# Combine with lipo +mkdir -p "$STAGING/lib" +lipo -create "$TMP_ARM64/lib/libpdfium.a" "$TMP_X64/lib/libpdfium.a" -output "$STAGING/lib/libpdfium.a" + +# Copy headers and other metadata from arm64 (they should be identical) +cp -R "$TMP_ARM64/include" "$STAGING/include" +cp "$TMP_ARM64/args.gn" "$STAGING/args.gn" +if [[ -d "$TMP_ARM64/LICENSES" ]]; then + cp -R "$TMP_ARM64/LICENSES" "$STAGING/LICENSES" +fi + +# Write metadata +cat > "$STAGING/BUILD-METADATA.json" <&2 + echo "test-target.sh only supports host-native and cross-buildable targets: darwin-arm64, darwin-x64, linux-x64, linux-arm64, android-*, ios-*" >&2 exit 1 ;; esac @@ -47,11 +78,19 @@ PDF_RUNTIME_TARGET_OS_LIST="${PDF_RUNTIME_TARGET_OS_LIST:-$GN_TARGET_OS}" \ "$SOURCE_DIR/scripts/embedpdf-runtime/apply-patches.sh" "$TARGET" -if [[ "$TARGET" == linux-* ]]; then +if [[ "$TARGET" == linux-* || "$TARGET" == android-* || "$TARGET" == arm64-v8a || "$TARGET" == armeabi-v7a || "$TARGET" == x86 || "$TARGET" == x86_64 ]]; then ( cd "$SOURCE_DIR" - build/install-build-deps.sh --no-prompt - build/linux/sysroot_scripts/install-sysroot.py "--arch=$GN_TARGET_CPU" + if [[ "$TARGET" == android-* || "$TARGET" == arm64-v8a || "$TARGET" == armeabi-v7a || "$TARGET" == x86 || "$TARGET" == x86_64 ]]; then + # For android, we might need --android but it's often slow and interactive. + # Most runners have what's needed. Let's try without --android first but keep the base linux deps. + build/install-build-deps.sh --no-prompt --no-arm --no-chromeos-fonts + else + build/install-build-deps.sh --no-prompt + fi + if [[ "$GN_TARGET_OS" == "linux" ]]; then + build/linux/sysroot_scripts/install-sysroot.py "--arch=$GN_TARGET_CPU" + fi ) fi @@ -114,6 +153,12 @@ run_gtest() { cmd+=("${extra_gtest_args[@]}") fi + if [[ "$GN_TARGET_OS" == "android" || "$GN_TARGET_OS" == "ios" ]]; then + echo "=== building $binary (execution skipped on $GN_TARGET_OS) ===" + # We already built it with ninja, so we just exit here. + return 0 + fi + echo "=== running $binary ===" "${cmd[@]}" 2>&1 | tee "$log" } diff --git a/scripts/embedpdf-runtime/unapply-patches.sh b/scripts/embedpdf-runtime/unapply-patches.sh index db023858b2..4ec5d0972f 100755 --- a/scripts/embedpdf-runtime/unapply-patches.sh +++ b/scripts/embedpdf-runtime/unapply-patches.sh @@ -65,6 +65,8 @@ reverse_patch_file "$SOURCE_DIR/build" "$PATCH_DIR/win/build.patch" reverse_patch_file "$SOURCE_DIR/build" "$PATCH_DIR/mac/build.patch" reverse_patch_file "$SOURCE_DIR/build" "$PATCH_DIR/wasm/build.patch" reverse_patch_file "$SOURCE_DIR/build" "$PATCH_DIR/musl/build.patch" +reverse_patch_file "$SOURCE_DIR/build" "$PATCH_DIR/android/build.patch" +reverse_patch_file "$SOURCE_DIR/third_party/libjpeg_turbo" "$PATCH_DIR/ios/libjpeg_turbo.patch" reverse_patch_file "$SOURCE_DIR" "$PATCH_DIR/musl/pdfium.patch" reverse_patch_file "$SOURCE_DIR" "$PATCH_DIR/shared-library.patch" diff --git a/testing/test.gni b/testing/test.gni index 6ad2c2d4ab..25d500ec9d 100644 --- a/testing/test.gni +++ b/testing/test.gni @@ -11,6 +11,10 @@ # Variable: # use_raw_android_executable: Use executable() rather than android_apk(). # use_native_activity: Test implements ANativeActivity_onCreate(). +declare_args() { + ios_automatically_manage_certs = true +} + template("test") { if (is_android) { import("//build/config/android/config.gni") From f4d40a769d8ac23e2700a1973af3b0b611b688a5 Mon Sep 17 00:00:00 2001 From: AVR Apps Date: Wed, 20 May 2026 02:43:56 +0530 Subject: [PATCH 2/2] Add back Windows & linux --- .github/workflows/release-libpdfium.yml | 113 +++++++++++++++++++++++- 1 file changed, 112 insertions(+), 1 deletion(-) diff --git a/.github/workflows/release-libpdfium.yml b/.github/workflows/release-libpdfium.yml index de03736f08..059493d99a 100644 --- a/.github/workflows/release-libpdfium.yml +++ b/.github/workflows/release-libpdfium.yml @@ -14,16 +14,62 @@ on: default: false permissions: - contents: read + contents: write jobs: + source-tests: + name: Source tests (Linux x64) + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@v6 + with: + ref: ${{ inputs.ref || github.ref_name }} + + - name: Install depot_tools + shell: bash + run: | + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$RUNNER_TEMP/depot_tools" + echo "$RUNNER_TEMP/depot_tools" >> "$GITHUB_PATH" + + - name: Install Linux base deps + shell: bash + run: | + sudo apt-get update + sudo apt-get install -y cmake clang lld curl g++ pkg-config tar + + - name: Run PDFium unit and embedder tests + shell: bash + run: scripts/embedpdf-runtime/test-target.sh linux-x64 + + - name: Upload PDFium test results + if: always() + uses: actions/upload-artifact@v6 + with: + name: pdfium-source-test-results-linux-x64 + path: out/embedpdf-runtime-test-results/linux-x64/ + if-no-files-found: ignore + build: name: Build ${{ matrix.target }} + needs: source-tests runs-on: ${{ matrix.runner }} strategy: fail-fast: false matrix: include: + # Linux & Wasm + - { target: linux-x64, runner: ubuntu-24.04 } + - { target: linux-arm64, runner: ubuntu-24.04 } + - { target: linuxmusl-x64, runner: ubuntu-24.04 } + - { target: linuxmusl-arm64, runner: ubuntu-24.04 } + - { target: wasm32, runner: ubuntu-24.04 } + # Darwin (macOS) + - { target: darwin-arm64, runner: macos-15 } + - { target: darwin-x64, runner: macos-15 } + # Windows + - { target: win32-x64, runner: windows-2022 } + - { target: win32-arm64, runner: windows-2022 } + # Android - { target: arm64-v8a, runner: ubuntu-24.04 } - { target: armeabi-v7a, runner: ubuntu-24.04 } - { target: x86, runner: ubuntu-24.04 } @@ -32,6 +78,10 @@ jobs: - { target: ios-arm64, runner: macos-15 } - { target: ios-simulator-arm64, runner: macos-15 } - { target: ios-simulator-x64, runner: macos-15 } + env: + DEPOT_TOOLS_WIN_TOOLCHAIN: 0 + EMSDK_VERSION: 3.1.72 + MUSL_URLS: ${{ secrets.MUSL_URL || 'https://more.musl.cc https://musl.cc' }} steps: - uses: actions/checkout@v6 with: @@ -47,10 +97,71 @@ jobs: run: | sudo apt-get update sudo apt-get install -y cmake curl g++ pkg-config tar + - name: Install aarch64 cross-compiler + if: matrix.target == 'linux-arm64' + shell: bash + run: sudo apt-get install -y gcc-aarch64-linux-gnu g++-aarch64-linux-gnu + - name: Install musl toolchain + if: startsWith(matrix.target, 'linuxmusl-') + shell: bash + run: | + triple=x86_64-linux-musl + if [[ "${{ matrix.target }}" == "linuxmusl-arm64" ]]; then + triple=aarch64-linux-musl + fi + archive="$triple-cross.tgz" + + for base_url in $MUSL_URLS; do + url="$base_url/$archive" + if [[ "$base_url" == *"more.musl.cc"* ]]; then + url="$base_url/$triple/$archive" + fi + + echo "Downloading $url" + if curl --fail --location --retry 5 --retry-all-errors --connect-timeout 20 --max-time 300 -o "$archive" "$url"; then + tar xzf "$archive" + echo "$PWD/$triple-cross/bin" >> "$GITHUB_PATH" + exit 0 + fi + done + + echo "Failed to download musl toolchain for $triple" >&2 + exit 1 + - name: Install Emscripten + if: matrix.target == 'wasm32' + shell: bash + run: | + mkdir -p third_party + if [[ -d third_party/emsdk ]]; then + git -C third_party/emsdk pull + else + git clone https://github.com/emscripten-core/emsdk.git third_party/emsdk + fi + third_party/emsdk/emsdk install "$EMSDK_VERSION" + third_party/emsdk/emsdk activate "$EMSDK_VERSION" + echo "$PWD/third_party/emsdk/upstream/emscripten" >> "$GITHUB_PATH" + echo "$PWD/third_party/emsdk/upstream/bin" >> "$GITHUB_PATH" - name: Select Xcode if: runner.os == 'macOS' shell: bash run: sudo xcode-select -s "/Applications/Xcode_16.1.app" + - name: Install Windows deps + if: runner.os == 'Windows' + shell: pwsh + run: | + $kitsRoot = 'C:\Program Files (x86)\Windows Kits\10\bin' + $sdk = Get-ChildItem $kitsRoot -Directory | + Where-Object { $_.Name -match '^\d+\.\d+\.\d+\.\d+$' } | + Sort-Object Name -Descending | + Select-Object -First 1 + if ($null -eq $sdk) { + throw "No Windows SDK version directory found in $kitsRoot" + } + $rcPath = Join-Path $sdk.FullName 'x64' + if (!(Test-Path (Join-Path $rcPath 'rc.exe'))) { + throw "rc.exe not found in $rcPath" + } + $rcPath | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append - name: Build target shell: bash run: scripts/embedpdf-runtime/build-target.sh "${{ matrix.target }}"