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

yihua pushed a commit to branch release/0.5.x
in repository https://gitbox.apache.org/repos/asf/hudi-rs.git

commit c402f065c4d1b495eecee7192d0de87ad6964d24
Author: Y Ethan Guo <[email protected]>
AuthorDate: Fri Sep 4 23:00:37 2026 -0700

    fix(ci): install a modern protoc for the manylinux wheel build (#751)
    
    (cherry picked from commit 7d130d812850cf34348df9440d0e038a8f4f2f92)
---
 .github/scripts/manylinux-build-deps.sh | 111 ++++++++++++++++++++++++++++++++
 .github/workflows/ci.yml                |  43 +++++++++++++
 .github/workflows/release.yml           |  42 ++++++------
 3 files changed, 175 insertions(+), 21 deletions(-)

diff --git a/.github/scripts/manylinux-build-deps.sh 
b/.github/scripts/manylinux-build-deps.sh
new file mode 100755
index 00000000..3b313efb
--- /dev/null
+++ b/.github/scripts/manylinux-build-deps.sh
@@ -0,0 +1,111 @@
+#!/usr/bin/env bash
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+# Install the system build dependencies for a manylinux wheel.
+#
+# Both release steps and the CI job that guards them run this one script, so a
+# change cannot land in some of them and not others.
+#
+# protoc: the distro package is 2.5.0 on the CentOS 7 base, which predates the
+# --experimental_allow_proto3_optional flag prost-build passes when it compiles
+# lance-encoding/lance-file's .proto files.
+#
+# libclang: librocksdb-sys generates its bindings with bindgen, which needs a
+# libclang the base image does not carry; the distro clang is 3.4, older than
+# bindgen supports. bindgen also needs clang's builtin headers (stdbool.h and
+# friends), which libclang cannot locate on its own when loaded from the SCL
+# prefix, so both are handed over explicitly. The exports only reach the build
+# if this script is SOURCED from before-script-linux, not executed: a 
step-level
+# `env:` never enters the container (maturin-action forwards only its own
+# variables), while the before-script runs in the same shell as the build - the
+# long-standing CFLAGS_aarch64 export below relies on the same behavior.
+#
+# perl-IPC-Cmd: needed by openssl.
+
+# This script is sourced, not executed, so that the exports below land in the
+# same shell the build runs in. Keep the caller's shell options: the strictness
+# is for this script, and leaking `set -u` in particular would turn any unset
+# variable in a future maturin-action release into a release-time failure.
+_deps_saved_opts=$(set +o)
+set -euo pipefail
+
+PROTOC_VERSION=36.1
+
+case "$(uname -m)" in
+  x86_64)
+    protoc_arch=x86_64
+    
protoc_sha256=c4bc672d9d49214dc8cafdceadf4df92182d6ca8e3ec65a56b2d7de5602669b4
+    ;;
+  aarch64)
+    protoc_arch=aarch_64
+    
protoc_sha256=237a68856edf1bd28b6204bddd0596c1cf46d298bc29c620012540b2e44c73e7
+    ;;
+  *)
+    echo "unsupported architecture: $(uname -m)" >&2
+    exit 1
+    ;;
+esac
+
+curl -fsSL -o /tmp/protoc.zip \
+  
"https://github.com/protocolbuffers/protobuf/releases/download/v${PROTOC_VERSION}/protoc-${PROTOC_VERSION}-linux-${protoc_arch}.zip";
+
+# The wheels this produces are published and signed, so verify the archive
+# rather than trusting whatever the download returned.
+echo "${protoc_sha256}  /tmp/protoc.zip" | sha256sum -c -
+
+unzip -qo /tmp/protoc.zip -d /usr/local bin/protoc 'include/*'
+chmod +x /usr/local/bin/protoc
+protoc --version
+
+yum install -y llvm-toolset-7.0-clang llvm-toolset-7.0-clang-libs perl-IPC-Cmd
+
+# libclang.so links against the LLVM runtime in the same prefix, so make the
+# loader aware of it rather than relying on a symlink out of the prefix.
+libclang_dir=/opt/rh/llvm-toolset-7.0/root/usr/lib64
+if [ ! -e "$libclang_dir/libclang.so" ]; then
+  echo "libclang.so not found under $libclang_dir" >&2
+  return 1 2>/dev/null || exit 1
+fi
+
+# Register the prefix so the LLVM runtime libclang links against resolves.
+echo "$libclang_dir" >/etc/ld.so.conf.d/llvm-toolset-7.0.conf
+ldconfig
+
+# Assign in a condition context: a bare `var=$(...)` takes the substitution's
+# status, so a non-matching glob would trip errexit before the check below.
+clang_include=""
+for candidate in "$libclang_dir"/clang/*/include; do
+  if [ -e "$candidate/stdbool.h" ]; then
+    clang_include=$candidate
+    break
+  fi
+done
+if [ -z "$clang_include" ]; then
+  echo "clang builtin headers not found under $libclang_dir/clang" >&2
+  return 1 2>/dev/null || exit 1
+fi
+
+export LIBCLANG_PATH="$libclang_dir"
+export BINDGEN_EXTRA_CLANG_ARGS="-I$clang_include"
+echo "libclang: $LIBCLANG_PATH"
+echo "clang builtin headers: $clang_include"
+
+# Restore the caller's shell options; the exports above survive.
+eval "$_deps_saved_opts"
+unset _deps_saved_opts
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 25f11af2..9ce83fd0 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -307,6 +307,49 @@ jobs:
         run: |
           sudo chown -R $(id -u):$(id -g) $GITHUB_WORKSPACE/.cargo 
$GITHUB_WORKSPACE/target $GITHUB_WORKSPACE/python/target 
$GITHUB_WORKSPACE/.uv-cache || true
 
+  manylinux-wheel-build:
+    name: Build the manylinux wheel
+    strategy:
+      fail-fast: false
+      matrix:
+        include:
+          - runner: ubuntu-latest
+            target: x86_64-unknown-linux-gnu
+          - runner: ubuntu-22.04-arm
+            target: aarch64-unknown-linux-gnu
+    runs-on: ${{ matrix.runner }}
+    steps:
+      - uses: actions/checkout@v7
+      - uses: actions/setup-python@v6
+        with:
+          python-version: '3.13'
+      # Builds the wheel in the same container, running the same dependency
+      # script, that the release workflow publishes from. Regular CI runs on 
the
+      # host, whose apt protoc is new enough for lance-encoding's prost-build 
and
+      # which carries libclang for librocksdb-sys, so a container-only break 
(see
+      # #750) stays invisible until a release tag is pushed - by which point 
the
+      # version is burnt on crates.io and cannot be reused.
+      - name: Build wheel
+        uses: PyO3/maturin-action@v1
+        with:
+          target: ${{ matrix.target }}
+          command: build
+          args: --release -m python/Cargo.toml --out dist
+          # Pin the image rather than relying on the default, so this job and 
the
+          # release steps are provably the same environment.
+          manylinux: '2014'
+          before-script-linux: |
+            source .github/scripts/manylinux-build-deps.sh
+      # A wheel that compiles is not necessarily a wheel that loads: the
+      # bindings rocksdb generates come from the container's older libclang, 
and
+      # bad bindings tend to surface on import or first use rather than at
+      # compile time. Each runner installs the wheel it just built.
+      - name: Import the built wheel
+        run: |
+          python -m pip install --upgrade pip
+          python -m pip install dist/*.whl
+          python -c "import hudi; print(hudi.__file__)"
+
   publish-coverage:
     name: Publish coverage reports to codecov.io
     runs-on: ubuntu-latest
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 653ae04f..eeaf35d2 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -119,37 +119,37 @@ jobs:
   release-pypi-manylinux:
     name: PyPI release manylinux
     needs: validate-release-tag
-    runs-on: ubuntu-latest
+    # aarch64 builds on a native ARM runner so this job and the CI wheel-build
+    # job use the same image; cross-building it from x86_64 would exercise a
+    # container CI never touches. It also drops the ring workaround that the
+    # cross build needed (briansmith/ring#1728).
+    strategy:
+      fail-fast: false
+      matrix:
+        include:
+          - runner: ubuntu-latest
+            target: x86_64-unknown-linux-gnu
+            # the sdist rides along with exactly one leg
+            args: --skip-existing -m python/Cargo.toml
+          - runner: ubuntu-22.04-arm
+            target: aarch64-unknown-linux-gnu
+            args: --skip-existing -m python/Cargo.toml --no-sdist
+    runs-on: ${{ matrix.runner }}
     steps:
       - uses: actions/checkout@v7
       - uses: actions/setup-python@v6
         with:
           python-version: '3.13'
 
-      - name: Publish manylinux to pypi x86_64 (with sdist)
+      - name: Publish manylinux to pypi
         uses: PyO3/maturin-action@v1
         env:
           MATURIN_PYPI_TOKEN: ${{ secrets.PYPI_TOKEN }}
           MATURIN_REPOSITORY: pypi
         with:
-          target: x86_64-unknown-linux-gnu
-          command: publish
-          args: --skip-existing -m python/Cargo.toml
-          # protobuf-compiler is needed by lance-encoding/lance-file's 
prost-build;
-          # perl-IPC-Cmd is needed by openssl.
-          before-script-linux: yum install -y protobuf-compiler perl-IPC-Cmd
-
-      - name: Publish manylinux to pypi aarch64 (without sdist)
-        uses: PyO3/maturin-action@v1
-        env:
-          MATURIN_PYPI_TOKEN: ${{ secrets.PYPI_TOKEN }}
-          MATURIN_REPOSITORY: pypi
-        with:
-          target: aarch64-unknown-linux-gnu
+          target: ${{ matrix.target }}
           command: publish
-          args: --skip-existing -m python/Cargo.toml --no-sdist
+          args: ${{ matrix.args }}
+          manylinux: '2014'
           before-script-linux: |
-            yum install -y protobuf-compiler
-            # We can remove this once we upgrade to 2_28.
-            # https://github.com/briansmith/ring/issues/1728
-            export CFLAGS_aarch64_unknown_linux_gnu="-D__ARM_ARCH=8"
+            source .github/scripts/manylinux-build-deps.sh

Reply via email to