This is an automated email from the ASF dual-hosted git repository.

chaokunyang pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/fory.git


The following commit(s) were added to refs/heads/main by this push:
     new 16c18be9d fix: x86 architecture missing from universal2 macOS wheel 
(#3114)
16c18be9d is described below

commit 16c18be9dec4b20fbb3acd11a54324bd4278c89f
Author: Madhava Jay <[email protected]>
AuthorDate: Thu Jan 8 17:04:36 2026 +1000

    fix: x86 architecture missing from universal2 macOS wheel (#3114)
    
    ## Why?
    
    macOS wheels produced by the native release workflow are tagged as
    universal2
    but contain single‑arch binaries, and artifacts from arm64/x86_64 builds
    collide. This makes the published mac wheels incorrect.
    
    You can check by doing this:
    ```
     cd pyfory-0.14.1-cp313-cp313-macosx_15_0_universal2.whl     ✔
     ~/Dow/pyfory-0.14.1-cp313-cp313-macosx_15_0_universal2.whl  find ./ -name 
"mmh3.so"
    ./pyfory/lib/mmh3/mmh3.so
     ~/Dow/pyfory-0.14.1-cp313-cp313-macosx_15_0_universal2.whl  lipo -archs 
./pyfory/lib/mmh3/mmh3.so
    arm64
    ```
    
    This causes it to crash on intel mac.
    
    I tested this in github CI here:
    
    https://github.com/madhavajay/fory/actions/runs/20806248646/job/59761528285
    
    ```
    Unpacking to: verify/pyfory-0.14.1.dev0...OK
    pyfory/_util.so: x86_64 arm64
    pyfory/serialization.so: x86_64 arm64
    pyfory/format/_format.so: x86_64 arm64
    pyfory/lib/mmh3/mmh3.so: x86_64 arm64
    ```
    
    ## What does this PR do?
    
    - Builds macOS wheels separately on arm64 and x86_64 runners, with
    explicit
      macosx_11_0_<arch> tags.
    - Merges the two wheels into a real universal2 wheel using lipo.
    - Verifies the merged binaries contain both architectures and that the
    wheel
      tag is macosx_11_0_universal2.
    - Adds PYFORY_WHEEL_PLAT support in ci/deploy.sh to force mac wheel
    tags.
    
    ## Related issues
    
    N/A
    
    ## Does this PR introduce any user-facing change?
    
    No
    
    ## Benchmark
    
    N/A (CI/workflow-only change; no runtime impact)
---
 .github/workflows/build-native-pr.yml      | 146 ++++++++++++++++++++++--
 .github/workflows/build-native-release.yml | 173 +++++++++++++++++++++++++++--
 ci/deploy.sh                               |  17 ++-
 3 files changed, 313 insertions(+), 23 deletions(-)

diff --git a/.github/workflows/build-native-pr.yml 
b/.github/workflows/build-native-pr.yml
index 044c8f077..bdb2fef7b 100644
--- a/.github/workflows/build-native-pr.yml
+++ b/.github/workflows/build-native-pr.yml
@@ -24,11 +24,10 @@ on:
     paths: [ci/**, python/**, .github/workflows/**]
 
 jobs:
-  build:
-    runs-on: ${{ matrix.os }}
+  build-windows:
+    runs-on: windows-latest
     strategy:
       matrix:
-        os: [macos-latest, windows-latest]
         python-version: ['3.13']
     steps:
       - uses: actions/checkout@v5
@@ -44,11 +43,7 @@ jobs:
             ~/.local/bin/bazel
             C:\bazel\bazel.exe
           key: bazel-binary-${{ runner.os }}-${{ runner.arch }}-${{ 
hashFiles('.bazelversion') }}
-      - name: Install bazel
-        if: runner.os != 'Windows'
-        run: ./ci/run_ci.sh install_bazel
       - name: Install bazel (Windows)
-        if: runner.os == 'Windows'
         run: ./ci/run_ci.sh install_bazel_windows
         shell: bash
       - name: Build wheel
@@ -63,5 +58,140 @@ jobs:
       - name: Upload wheels as artifacts
         uses: actions/upload-artifact@v4
         with:
-          name: pyfory-wheels-native-${{ matrix.os }}-${{ 
matrix.python-version }}
+          name: pyfory-wheels-native-windows-${{ matrix.python-version }}
+          path: dist/*.whl
+
+  build-macos-arm64:
+    runs-on: macos-15
+    strategy:
+      matrix:
+        python-version: ['3.13']
+    steps:
+      - uses: actions/checkout@v5
+      - uses: actions/setup-python@v5
+        with:
+          python-version: ${{ matrix.python-version }}
+          cache: 'pip'
+      - name: Cache Bazel binary
+        uses: actions/cache@v4
+        with:
+          path: |
+            ~/bin/bazel
+            ~/.local/bin/bazel
+          key: bazel-binary-${{ runner.os }}-${{ runner.arch }}-${{ 
hashFiles('.bazelversion') }}
+      - name: Install bazel
+        run: ./ci/run_ci.sh install_bazel
+      - name: Build wheel
+        run: ./ci/deploy.sh build_pyfory
+        shell: bash
+        env:
+          MACOSX_DEPLOYMENT_TARGET: "11.0"
+          PYFORY_WHEEL_PLAT: macosx_11_0_arm64
+      - name: Install and verify wheel
+        shell: bash
+        run: |
+          python -m pip install --upgrade pip
+          pip install dist/*.whl
+          python -c "import pyfory; print(pyfory.__version__)"
+      - name: Upload wheel artifact
+        uses: actions/upload-artifact@v4
+        with:
+          name: pyfory-macos-arm64-wheel-${{ matrix.python-version }}
+          path: dist/*.whl
+
+  build-macos-x86_64:
+    runs-on: macos-15-intel
+    strategy:
+      matrix:
+        python-version: ['3.13']
+    steps:
+      - uses: actions/checkout@v5
+      - uses: actions/setup-python@v5
+        with:
+          python-version: ${{ matrix.python-version }}
+          cache: 'pip'
+      - name: Cache Bazel binary
+        uses: actions/cache@v4
+        with:
+          path: |
+            ~/bin/bazel
+            ~/.local/bin/bazel
+          key: bazel-binary-${{ runner.os }}-${{ runner.arch }}-${{ 
hashFiles('.bazelversion') }}
+      - name: Install bazel
+        run: ./ci/run_ci.sh install_bazel
+      - name: Build wheel
+        run: ./ci/deploy.sh build_pyfory
+        shell: bash
+        env:
+          MACOSX_DEPLOYMENT_TARGET: "11.0"
+          PYFORY_WHEEL_PLAT: macosx_11_0_x86_64
+      - name: Install and verify wheel
+        shell: bash
+        run: |
+          python -m pip install --upgrade pip
+          pip install dist/*.whl
+          python -c "import pyfory; print(pyfory.__version__)"
+      - name: Upload wheel artifact
+        uses: actions/upload-artifact@v4
+        with:
+          name: pyfory-macos-x86_64-wheel-${{ matrix.python-version }}
+          path: dist/*.whl
+
+  merge-macos-universal2:
+    runs-on: macos-15
+    needs: [build-macos-arm64, build-macos-x86_64]
+    strategy:
+      matrix:
+        python-version: ['3.13']
+    steps:
+      - uses: actions/setup-python@v5
+        with:
+          python-version: ${{ matrix.python-version }}
+      - name: Install wheel tooling
+        run: python -m pip install --upgrade pip wheel
+      - name: Download arch wheels
+        uses: actions/download-artifact@v5
+        with:
+          pattern: pyfory-macos-*-wheel-${{ matrix.python-version }}
+          path: artifacts
+          merge-multiple: true
+      - name: Build universal2 wheel
+        shell: bash
+        run: |
+          set -euo pipefail
+          mkdir -p unpacked dist
+          ARM_WHL=$(ls artifacts/*arm64*.whl | head -n1)
+          X86_WHL=$(ls artifacts/*x86_64*.whl | head -n1)
+          python -m wheel unpack "$ARM_WHL" -d unpacked/arm64
+          python -m wheel unpack "$X86_WHL" -d unpacked/x86_64
+          ARM_DIR=$(ls -d unpacked/arm64/pyfory-*)
+          X86_DIR=$(ls -d unpacked/x86_64/pyfory-*)
+          UNIVERSAL_DIR="unpacked/pyfory-universal2"
+          cp -R "$ARM_DIR" "$UNIVERSAL_DIR"
+          for so in pyfory/_util.so pyfory/serialization.so 
pyfory/format/_format.so pyfory/lib/mmh3/mmh3.so; do
+            lipo -create "$ARM_DIR/$so" "$X86_DIR/$so" -output 
"$UNIVERSAL_DIR/$so"
+          done
+          WHEEL_FILE=$(ls "$UNIVERSAL_DIR"/pyfory-*.dist-info/WHEEL)
+          sed -i '' -e 's/macosx_11_0_arm64/macosx_11_0_universal2/g' \
+            -e 's/macosx_11_0_x86_64/macosx_11_0_universal2/g' \
+            "$WHEEL_FILE"
+          python -m wheel pack "$UNIVERSAL_DIR" -d dist
+      - name: Verify universal2 binaries
+        shell: bash
+        run: |
+          set -euo pipefail
+          mkdir -p verify
+          for whl in dist/*.whl; do
+            python -m wheel unpack "$whl" -d verify
+          done
+          VERIFY_DIR=$(ls -d verify/pyfory-*)
+          WHEEL_FILE=$(ls "$VERIFY_DIR"/pyfory-*.dist-info/WHEEL)
+          grep -q "macosx_11_0_universal2" "$WHEEL_FILE"
+          for so in pyfory/_util.so pyfory/serialization.so 
pyfory/format/_format.so pyfory/lib/mmh3/mmh3.so; do
+            echo "$so: $(lipo -archs "$VERIFY_DIR/$so")"
+          done
+      - name: Upload universal2 wheel
+        uses: actions/upload-artifact@v4
+        with:
+          name: pyfory-wheels-native-macos-universal2-${{ 
matrix.python-version }}
           path: dist/*.whl
diff --git a/.github/workflows/build-native-release.yml 
b/.github/workflows/build-native-release.yml
index 88af14b94..a531f766c 100644
--- a/.github/workflows/build-native-release.yml
+++ b/.github/workflows/build-native-release.yml
@@ -21,11 +21,10 @@ on:
     tags: ['v*']  # NO PATH FILTER - critical for releases
 
 jobs:
-  build:
-    runs-on: ${{ matrix.os }}
+  build-windows:
+    runs-on: windows-latest
     strategy:
       matrix:
-        os: [macos-15-large, macos-latest, windows-latest]
         python-version: ['3.8', '3.9', '3.10', '3.11', '3.12', '3.13']
     steps:
       - uses: actions/checkout@v5
@@ -45,11 +44,7 @@ jobs:
             ~/.local/bin/bazel
             C:\bazel\bazel.exe
           key: bazel-binary-${{ runner.os }}-${{ runner.arch }}-${{ 
hashFiles('.bazelversion') }}
-      - name: Install bazel
-        if: runner.os != 'Windows'
-        run: ./ci/run_ci.sh install_bazel
       - name: Install bazel (Windows)
-        if: runner.os == 'Windows'
         run: ./ci/run_ci.sh install_bazel_windows
         shell: bash
       - name: Build wheel
@@ -64,7 +59,6 @@ jobs:
           pip install dist/*.whl
           INSTALLED_VERSION=$(python -c "import pyfory; 
print(pyfory.__version__)")
           echo "Installed version: $INSTALLED_VERSION"
-          # Verify version matches the tag
           EXPECTED_VERSION="${{ github.ref_name }}"
           EXPECTED_VERSION=$(DEPLOY_QUIET=1 ci/deploy.sh parse_py_version 
$EXPECTED_VERSION | tail -n1)
           echo "Expected version: $EXPECTED_VERSION"
@@ -76,5 +70,166 @@ jobs:
       - name: Upload wheels as artifacts
         uses: actions/upload-artifact@v4
         with:
-          name: pyfory-wheels-${{ matrix.os }}-${{ matrix.python-version 
}}-${{ github.ref_name }}
+          name: pyfory-wheels-windows-${{ matrix.python-version }}-${{ 
github.ref_name }}
+          path: dist/*.whl
+
+  build-macos-arm64:
+    runs-on: macos-15
+    strategy:
+      matrix:
+        python-version: ['3.8', '3.9', '3.10', '3.11', '3.12', '3.13']
+    steps:
+      - uses: actions/checkout@v5
+      - name: Bump version
+        run: ./ci/deploy.sh bump_py_version "${{ github.ref_name }}"
+        shell: bash
+      - uses: actions/setup-python@v5
+        with:
+          python-version: ${{ matrix.python-version }}
+          cache: 'pip'
+      - name: Cache Bazel binary
+        uses: actions/cache@v4
+        with:
+          path: |
+            ~/bin/bazel
+            ~/.local/bin/bazel
+          key: bazel-binary-${{ runner.os }}-${{ runner.arch }}-${{ 
hashFiles('.bazelversion') }}
+      - name: Install bazel
+        run: ./ci/run_ci.sh install_bazel
+      - name: Build wheel
+        shell: bash
+        run: ./ci/deploy.sh build_pyfory
+        env:
+          GITHUB_REF_NAME: ${{ github.ref_name }}
+          MACOSX_DEPLOYMENT_TARGET: "11.0"
+          PYFORY_WHEEL_PLAT: macosx_11_0_arm64
+      - name: Install and verify wheel
+        shell: bash
+        run: |
+          python -m pip install --upgrade pip
+          pip install dist/*.whl
+          INSTALLED_VERSION=$(python -c "import pyfory; 
print(pyfory.__version__)")
+          echo "Installed version: $INSTALLED_VERSION"
+          EXPECTED_VERSION="${{ github.ref_name }}"
+          EXPECTED_VERSION=$(DEPLOY_QUIET=1 ci/deploy.sh parse_py_version 
$EXPECTED_VERSION | tail -n1)
+          echo "Expected version: $EXPECTED_VERSION"
+          if [ "$INSTALLED_VERSION" != "$EXPECTED_VERSION" ]; then
+            echo "Version mismatch: Expected $EXPECTED_VERSION but got 
$INSTALLED_VERSION"
+            exit 1
+          fi
+          echo "Version verification successful"
+      - name: Upload wheel artifact
+        uses: actions/upload-artifact@v4
+        with:
+          name: pyfory-macos-arm64-wheel-${{ matrix.python-version }}-${{ 
github.ref_name }}
+          path: dist/*.whl
+
+  build-macos-x86_64:
+    runs-on: macos-15-intel
+    strategy:
+      matrix:
+        python-version: ['3.8', '3.9', '3.10', '3.11', '3.12', '3.13']
+    steps:
+      - uses: actions/checkout@v5
+      - name: Bump version
+        run: ./ci/deploy.sh bump_py_version "${{ github.ref_name }}"
+        shell: bash
+      - uses: actions/setup-python@v5
+        with:
+          python-version: ${{ matrix.python-version }}
+          cache: 'pip'
+      - name: Cache Bazel binary
+        uses: actions/cache@v4
+        with:
+          path: |
+            ~/bin/bazel
+            ~/.local/bin/bazel
+          key: bazel-binary-${{ runner.os }}-${{ runner.arch }}-${{ 
hashFiles('.bazelversion') }}
+      - name: Install bazel
+        run: ./ci/run_ci.sh install_bazel
+      - name: Build wheel
+        shell: bash
+        run: ./ci/deploy.sh build_pyfory
+        env:
+          GITHUB_REF_NAME: ${{ github.ref_name }}
+          MACOSX_DEPLOYMENT_TARGET: "11.0"
+          PYFORY_WHEEL_PLAT: macosx_11_0_x86_64
+      - name: Install and verify wheel
+        shell: bash
+        run: |
+          python -m pip install --upgrade pip
+          pip install dist/*.whl
+          INSTALLED_VERSION=$(python -c "import pyfory; 
print(pyfory.__version__)")
+          echo "Installed version: $INSTALLED_VERSION"
+          EXPECTED_VERSION="${{ github.ref_name }}"
+          EXPECTED_VERSION=$(DEPLOY_QUIET=1 ci/deploy.sh parse_py_version 
$EXPECTED_VERSION | tail -n1)
+          echo "Expected version: $EXPECTED_VERSION"
+          if [ "$INSTALLED_VERSION" != "$EXPECTED_VERSION" ]; then
+            echo "Version mismatch: Expected $EXPECTED_VERSION but got 
$INSTALLED_VERSION"
+            exit 1
+          fi
+          echo "Version verification successful"
+      - name: Upload wheel artifact
+        uses: actions/upload-artifact@v4
+        with:
+          name: pyfory-macos-x86_64-wheel-${{ matrix.python-version }}-${{ 
github.ref_name }}
+          path: dist/*.whl
+
+  merge-macos-universal2:
+    runs-on: macos-15
+    needs: [build-macos-arm64, build-macos-x86_64]
+    strategy:
+      matrix:
+        python-version: ['3.8', '3.9', '3.10', '3.11', '3.12', '3.13']
+    steps:
+      - uses: actions/setup-python@v5
+        with:
+          python-version: ${{ matrix.python-version }}
+      - name: Install wheel tooling
+        run: python -m pip install --upgrade pip wheel
+      - name: Download arch wheels
+        uses: actions/download-artifact@v5
+        with:
+          pattern: pyfory-macos-*-wheel-${{ matrix.python-version }}-${{ 
github.ref_name }}
+          path: artifacts
+          merge-multiple: true
+      - name: Build universal2 wheel
+        shell: bash
+        run: |
+          set -euo pipefail
+          mkdir -p unpacked dist
+          ARM_WHL=$(ls artifacts/*arm64*.whl | head -n1)
+          X86_WHL=$(ls artifacts/*x86_64*.whl | head -n1)
+          python -m wheel unpack "$ARM_WHL" -d unpacked/arm64
+          python -m wheel unpack "$X86_WHL" -d unpacked/x86_64
+          ARM_DIR=$(ls -d unpacked/arm64/pyfory-*)
+          X86_DIR=$(ls -d unpacked/x86_64/pyfory-*)
+          UNIVERSAL_DIR="unpacked/pyfory-universal2"
+          cp -R "$ARM_DIR" "$UNIVERSAL_DIR"
+          for so in pyfory/_util.so pyfory/serialization.so 
pyfory/format/_format.so pyfory/lib/mmh3/mmh3.so; do
+            lipo -create "$ARM_DIR/$so" "$X86_DIR/$so" -output 
"$UNIVERSAL_DIR/$so"
+          done
+          WHEEL_FILE=$(ls "$UNIVERSAL_DIR"/pyfory-*.dist-info/WHEEL)
+          sed -i '' -e 's/macosx_11_0_arm64/macosx_11_0_universal2/g' \
+            -e 's/macosx_11_0_x86_64/macosx_11_0_universal2/g' \
+            "$WHEEL_FILE"
+          python -m wheel pack "$UNIVERSAL_DIR" -d dist
+      - name: Verify universal2 binaries
+        shell: bash
+        run: |
+          set -euo pipefail
+          mkdir -p verify
+          for whl in dist/*.whl; do
+            python -m wheel unpack "$whl" -d verify
+          done
+          VERIFY_DIR=$(ls -d verify/pyfory-*)
+          WHEEL_FILE=$(ls "$VERIFY_DIR"/pyfory-*.dist-info/WHEEL)
+          grep -q "macosx_11_0_universal2" "$WHEEL_FILE"
+          for so in pyfory/_util.so pyfory/serialization.so 
pyfory/format/_format.so pyfory/lib/mmh3/mmh3.so; do
+            echo "$so: $(lipo -archs "$VERIFY_DIR/$so")"
+          done
+      - name: Upload universal2 wheel
+        uses: actions/upload-artifact@v4
+        with:
+          name: pyfory-wheels-macos-universal2-${{ matrix.python-version 
}}-${{ github.ref_name }}
           path: dist/*.whl
diff --git a/ci/deploy.sh b/ci/deploy.sh
index be0c38595..fb0123eb1 100755
--- a/ci/deploy.sh
+++ b/ci/deploy.sh
@@ -90,13 +90,18 @@ build_pyfory() {
   $PIP_CMD install setuptools -U
 
   if [[ "$OSTYPE" == "darwin"* ]]; then
-    MACOS_VERSION=$(sw_vers -productVersion | cut -d. -f1-2)
-    echo "MACOS_VERSION: $MACOS_VERSION"
-    if [[ "$MACOS_VERSION" == "13"* ]]; then
-      export MACOSX_DEPLOYMENT_TARGET=10.13
-      $PYTHON_CMD setup.py bdist_wheel --plat-name macosx_10_13_x86_64 
--dist-dir="$ROOT/dist"
+    if [ -n "${PYFORY_WHEEL_PLAT:-}" ]; then
+      echo "PYFORY_WHEEL_PLAT: $PYFORY_WHEEL_PLAT"
+      $PYTHON_CMD setup.py bdist_wheel --plat-name "$PYFORY_WHEEL_PLAT" 
--dist-dir="$ROOT/dist"
     else
-      $PYTHON_CMD setup.py bdist_wheel --dist-dir="$ROOT/dist"
+      MACOS_VERSION=$(sw_vers -productVersion | cut -d. -f1-2)
+      echo "MACOS_VERSION: $MACOS_VERSION"
+      if [[ "$MACOS_VERSION" == "13"* ]]; then
+        export MACOSX_DEPLOYMENT_TARGET=10.13
+        $PYTHON_CMD setup.py bdist_wheel --plat-name macosx_10_13_x86_64 
--dist-dir="$ROOT/dist"
+      else
+        $PYTHON_CMD setup.py bdist_wheel --dist-dir="$ROOT/dist"
+      fi
     fi
   elif [[ "$OSTYPE" == "msys" || "$OSTYPE" == "win32" ]]; then
 


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to