This is an automated email from the ASF dual-hosted git repository.
Gabriel39 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/doris.git
The following commit(s) were added to refs/heads/master by this push:
new f88735f8f62 [chore](build) Add paimon-rust third-party build
integration (#68562)
f88735f8f62 is described below
commit f88735f8f62ce3375c4a6874419495622c070ca7
Author: Gabriel <[email protected]>
AuthorDate: Tue Sep 29 12:44:46 2026 +0800
[chore](build) Add paimon-rust third-party build integration (#68562)
### What problem does this PR solve?
Related PR: #66227
Prepare the third-party dependency for the Paimon Rust reader on master
independently of the reader implementation. This extracts all
dependency-related changes from #66227 after simplifying its Rust
archive installation.
- Download Apache paimon-rust v0.4.0-rc1 with a pinned checksum and
build `paimon-c` with HDFS support.
- Generate the C header with pinned cbindgen 0.29.4 and install the
header and archive using the existing third-party copy/strip
conventions.
- Use Rust 1.94.0 by default for both Lance and Paimon. When changing
the toolchain, rebuild both libraries with the same `RUSTUP_TOOLCHAIN`
to avoid conflicting Rust standard libraries.
- Register the dependency in CMake while preserving libm and glibc
compatibility link ordering.
The changes cover dependency registration, building, and installation
checks, plus build-script regression tests. Existing installations
missing either Rust archive or the generated Paimon header follow the
full dependency rebuild path so Lance and Paimon are rebuilt together.
Header generation inherits the selected Cargo executable and offline
mode. Reader code and its functional tests remain in #66227. The Rust
archive identity helper and its dedicated test file are not included.
### Validation
- Bash syntax and `git diff --check` passed.
- `python3 thirdparty/test/paimon-build-test.py`: all 10 tests passed on
both this branch and #66227. Eight tests fail before the fix. Coverage
includes old Linux/macOS installs, missing archives/header,
complete-install reuse, clean forwarding, custom Cargo, and offline
metadata settings. External compiler/header-generator commands are test
doubles; the tests execute the actual build-script logic.
- Six temporary mock-toolchain scenarios passed on this branch, covering
installation, strip behavior, offline flags, default toolchain
selection, explicitly newer toolchains, and rejection of older
toolchains. The same scenarios passed on #66227.
- CMake fragment checks passed with `GLIBC_COMPATIBILITY` enabled and
disabled; compatibility-library ordering was also checked.
- The official source archive MD5 matches the manifest.
- Full Rust/Doris compilation and final binary ABI validation were not
run locally; compilation is requested through CI.
### Release note
None
### Check List (For Author)
- Test: Build-script smoke checks and dependency/link-order validation
described above.
- Behavior changed: Yes. Third-party builds include paimon-rust and both
Rust libraries default to Rust 1.94.0.
- Does this need documentation: No. This prepares an internal build
dependency.
---
be/CMakeLists.txt | 3 +-
be/cmake/thirdparty.cmake | 7 ++
build.sh | 7 +-
thirdparty/build-thirdparty.sh | 161 ++++++++++++++++++++++++++--
thirdparty/test/paimon-build-test.py | 202 +++++++++++++++++++++++++++++++++++
thirdparty/vars.sh | 7 ++
6 files changed, 378 insertions(+), 9 deletions(-)
diff --git a/be/CMakeLists.txt b/be/CMakeLists.txt
index 7f8b577814d..02da8f5dc2e 100644
--- a/be/CMakeLists.txt
+++ b/be/CMakeLists.txt
@@ -860,7 +860,8 @@ if (GLIBC_COMPATIBILITY)
glibc-compatibility-explicit
glibc-compatibility
-lm
- lance_c)
+ lance_c
+ paimon_c)
endif()
if (NOT OS_MACOSX)
diff --git a/be/cmake/thirdparty.cmake b/be/cmake/thirdparty.cmake
index dcb7df7343b..723d1f8bded 100644
--- a/be/cmake/thirdparty.cmake
+++ b/be/cmake/thirdparty.cmake
@@ -120,6 +120,13 @@ add_thirdparty(lance_c LIB64 NOTADD)
if (NOT GLIBC_COMPATIBILITY)
list(APPEND COMMON_THIRDPARTY m lance_c)
endif()
+# libpaimon_c.a (built from paimon-rust) brings in Rust compiler_builtins that
+# would otherwise steal libm symbols. Place libm before it so the final linker
+# resolves C math symbols from the system library first.
+add_thirdparty(paimon_c LIB64 NOTADD)
+if (NOT GLIBC_COMPATIBILITY)
+ list(APPEND COMMON_THIRDPARTY m paimon_c)
+endif()
add_thirdparty(brpc LIB64)
add_thirdparty(rocksdb)
add_thirdparty(cyrus-sasl LIBNAME "lib/libsasl2.a")
diff --git a/build.sh b/build.sh
index 55c5bacb919..40ec83d99b2 100755
--- a/build.sh
+++ b/build.sh
@@ -486,7 +486,12 @@ else
LAST_THIRDPARTY_LIB='hadoop_hdfs_3_4/native/libhdfs.a'
fi
-if [[ ! -f "${DORIS_THIRDPARTY}/installed/lib/${LAST_THIRDPARTY_LIB}" ]]; then
+# Old installs can contain the sentinel but predate Paimon. Rebuild the whole
+# dependency set so Lance and Paimon also use the same selected Rust toolchain.
+if [[ ! -f "${DORIS_THIRDPARTY}/installed/lib/${LAST_THIRDPARTY_LIB}" ||
+ ! -f "${DORIS_THIRDPARTY}/installed/lib64/liblance_c.a" ||
+ ! -f "${DORIS_THIRDPARTY}/installed/lib64/libpaimon_c.a" ||
+ ! -f "${DORIS_THIRDPARTY}/installed/include/paimon_rust/paimon.h" ]];
then
echo "Thirdparty libraries need to be build ..."
# need remove all installed pkgs because some lib like lz4 will throw
error if its lib alreay exists
rm -rf "${DORIS_THIRDPARTY}/installed"
diff --git a/thirdparty/build-thirdparty.sh b/thirdparty/build-thirdparty.sh
index e878f5398a9..9ac1e01d02d 100755
--- a/thirdparty/build-thirdparty.sh
+++ b/thirdparty/build-thirdparty.sh
@@ -2372,6 +2372,24 @@ build_pugixml() {
}
# lance-c
+# Publish a complete archive with one rename. Copy/strip must not damage an
installed library
+# or expose a partial first installation if either command fails or the build
is interrupted.
+install_rust_archive() {
+ (
+ set -e
+ local archive="$1"
+ local destination="${TP_INSTALL_DIR}/lib64/${archive##*/}"
+ local staged
+ staged="$(mktemp "${destination}.tmp.XXXXXX")"
+ trap 'rm -f "${staged}"' EXIT
+ cp -p "${archive}" "${staged}"
+ if [[ "${STRIP_TP_LIB}" = "ON" && "${KERNEL}" != 'Darwin' ]]; then
+ strip --strip-debug --strip-unneeded "${staged}"
+ fi
+ mv -f "${staged}" "${destination}"
+ )
+}
+
build_lance_c() {
check_if_source_exist "${LANCE_C_SOURCE}"
cd "${TP_SOURCE_DIR}/${LANCE_C_SOURCE}"
@@ -2381,7 +2399,7 @@ build_lance_c() {
local cargo_bin="${LANCE_C_CARGO:-${CARGO:-cargo}}"
if ! command -v "${cargo_bin}" >/dev/null 2>&1; then
- echo "cargo is required to build lance-c. Install Rust 1.91.0 or set
LANCE_C_CARGO."
+ echo "cargo is required to build lance-c. Install Rust 1.94.0 or set
LANCE_C_CARGO."
exit 1
fi
if [[ ! -x "${TP_INSTALL_DIR}/bin/protoc" ]]; then
@@ -2389,14 +2407,20 @@ build_lance_c() {
exit 1
fi
- local required_rust_version="1.91.0"
+ local required_rust_version="1.94.0"
local cargo_env=(
"CARGO_BUILD_JOBS=${PARALLEL}"
"CARGO_TARGET_DIR=${PWD}/${BUILD_DIR}"
"PROTOC=${TP_INSTALL_DIR}/bin/protoc"
)
if command -v rustup >/dev/null 2>&1 && [[ -z "${RUSTUP_TOOLCHAIN}" ]];
then
- if ! rustup toolchain list | grep -Eq '^1\.91\.0([[:space:]-]|$)'; then
+ # The presence check must look for the toolchain the minimum actually
+ # requires, not a literal: with only an older toolchain installed the
+ # stale check would skip the install below and then force
+ # RUSTUP_TOOLCHAIN to a version rustup cannot dispatch, failing the
+ # build before any archive is produced.
+ local required_rust_regex="${required_rust_version//./\\.}"
+ if ! rustup toolchain list | grep -Eq
"^${required_rust_regex}([[:space:]-]|$)"; then
rustup toolchain install "${required_rust_version}" --profile
minimal
fi
cargo_env+=("RUSTUP_TOOLCHAIN=${required_rust_version}")
@@ -2407,7 +2431,7 @@ build_lance_c() {
echo "failed to get cargo version for lance-c. Install Rust
${required_rust_version} or set LANCE_C_CARGO/RUSTUP_TOOLCHAIN."
exit 1
fi
- # Rust 1.91.0 is the minimum supported version. Allow newer toolchains when
+ # Rust 1.94.0 is the minimum supported version. Allow newer toolchains when
# callers explicitly select one or rustup is unavailable on the system.
if ! awk -v required="${required_rust_version}" -v
actual="${cargo_version}" 'BEGIN {
split(required, r, ".");
@@ -2440,11 +2464,132 @@ build_lance_c() {
mkdir -p "${TP_INSTALL_DIR}/include" "${TP_INSTALL_DIR}/lib64"
rm -rf "${TP_INSTALL_DIR}/include/lance"
cp -av include/lance "${TP_INSTALL_DIR}/include/"
- cp -v "${BUILD_DIR}/release/liblance_c.a" "${TP_INSTALL_DIR}/lib64/"
+ install_rust_archive "${BUILD_DIR}/release/liblance_c.a"
+}
+
+build_paimon_rust() {
+ check_if_source_exist "${PAIMON_RUST_SOURCE}"
+ cd "${TP_SOURCE_DIR}/${PAIMON_RUST_SOURCE}"
+
+ rm -rf "${BUILD_DIR}"
+ mkdir -p "${BUILD_DIR}"
+
+ local cargo_bin="${PAIMON_RUST_CARGO:-${CARGO:-cargo}}"
+ if ! command -v "${cargo_bin}" >/dev/null 2>&1; then
+ echo "cargo is required to build paimon-rust. Install Rust 1.94.0 or
set PAIMON_RUST_CARGO."
+ exit 1
+ fi
+
+ local required_rust_version="1.94.0"
+ local cargo_env=(
+ "CARGO_BUILD_JOBS=${PARALLEL}"
+ "CARGO_TARGET_DIR=${PWD}/${BUILD_DIR}"
+ )
+ if command -v rustup >/dev/null 2>&1 && [[ -z "${RUSTUP_TOOLCHAIN}" ]];
then
+ # The presence check must look for the toolchain the minimum actually
+ # requires, not a literal: with only an older toolchain installed the
+ # stale check would skip the install below and then force
+ # RUSTUP_TOOLCHAIN to a version rustup cannot dispatch, failing the
+ # build before any archive is produced.
+ local required_rust_regex="${required_rust_version//./\\.}"
+ if ! rustup toolchain list | grep -Eq
"^${required_rust_regex}([[:space:]-]|$)"; then
+ rustup toolchain install "${required_rust_version}" --profile
minimal
+ fi
+ cargo_env+=("RUSTUP_TOOLCHAIN=${required_rust_version}")
+ fi
- if [[ "${STRIP_TP_LIB}" = "ON" && "${KERNEL}" != 'Darwin' ]]; then
- strip --strip-debug --strip-unneeded
"${TP_INSTALL_DIR}/lib64/liblance_c.a"
+ local cargo_version
+ if ! cargo_version="$(env "${cargo_env[@]}" "${cargo_bin}" --version | awk
'{print $2}')"; then
+ echo "failed to get cargo version for paimon-rust. Install Rust
${required_rust_version} or set PAIMON_RUST_CARGO/RUSTUP_TOOLCHAIN."
+ exit 1
fi
+ # Rust 1.94.0 is the minimum supported version. Allow newer toolchains when
+ # callers explicitly select one or rustup is unavailable on the system.
+ # NOTE: paimon_c and lance_c are both Rust staticlibs linked into the same
+ # BE binary; they must be built with the SAME rustc toolchain so the linker
+ # resolves both crates' std references against a single std copy. Mixing
+ # toolchains makes the precompiled std hashes differ and the linker pulls
+ # both std copies in, colliding on the unmangled `rust_eh_personality`
+ # (duplicate symbol). Rebuild both lance_c and paimon_rust whenever the
+ # toolchain changes, using the same RUSTUP_TOOLCHAIN for both builds.
+ if ! awk -v required="${required_rust_version}" -v
actual="${cargo_version}" 'BEGIN {
+ split(required, r, ".");
+ split(actual, a, ".");
+ for (i = 1; i <= 3; i++) {
+ if ((a[i] + 0) > (r[i] + 0)) {
+ exit 0;
+ }
+ if ((a[i] + 0) < (r[i] + 0)) {
+ exit 1;
+ }
+ }
+ exit 0;
+ }'; then
+ echo "paimon-rust requires Rust/Cargo ${required_rust_version} or
newer, but found ${cargo_version}."
+ echo "Install Rust ${required_rust_version} or set
PAIMON_RUST_CARGO/RUSTUP_TOOLCHAIN."
+ exit 1
+ fi
+
+ if [[ "${KERNEL}" != 'Darwin' ]]; then
+ cargo_env+=("CFLAGS=${CFLAGS:-} -std=gnu17")
+ fi
+
+ local cargo_args=(build --release --locked -p paimon-c --features
paimon/storage-hdfs)
+ # cbindgen invokes cargo metadata itself; command-line flags on the build
+ # and install calls do not propagate to that child process.
+ cargo_env+=("CARGO=${cargo_bin}")
+ if [[ "$(echo "${PAIMON_RUST_CARGO_OFFLINE}" | tr '[:lower:]'
'[:upper:]')" == "ON" ]]; then
+ cargo_args+=(--offline)
+ cargo_env+=("CARGO_NET_OFFLINE=true")
+ fi
+ env "${cargo_env[@]}" "${cargo_bin}" "${cargo_args[@]}"
+
+ # Generate the C header from the Rust extern "C" surface via cbindgen.
+ # cbindgen is a pinned, Doris-controlled input: an unpinned "current"
+ # release would regenerate paimon.h differently between builds. The
+ # pinned version installs under a Doris-controlled --root and its
+ # resolved absolute path is invoked directly (a custom CARGO_HOME does
+ # not necessarily put cargo-installed binaries on PATH). Offline builds
+ # pass --offline to the install command, exactly like the fetch/build
+ # handling above — cargo fails on a missing local crate cache instead
+ # of reaching for the network.
+ local cbindgen_version="0.29.4"
+ local cbindgen_bin="${PAIMON_RUST_CBINDGEN:-}"
+ if [[ -z "${cbindgen_bin}" ]]; then
+ local
cbindgen_root="${TP_SOURCE_DIR}/.doris-cbindgen-${cbindgen_version}"
+ cbindgen_bin="${cbindgen_root}/bin/cbindgen"
+ if [[ ! -x "${cbindgen_bin}" ]]; then
+ local cbindgen_install_args=(install cbindgen
+ --version "${cbindgen_version}" --locked --root
"${cbindgen_root}")
+ if [[ "$(echo "${PAIMON_RUST_CARGO_OFFLINE}" | tr '[:lower:]'
'[:upper:]')" == "ON" ]]; then
+ cbindgen_install_args+=(--offline)
+ fi
+ echo "cbindgen not found; installing pinned ${cbindgen_version}
via cargo install ..."
+ env "${cargo_env[@]}" "${cargo_bin}" "${cbindgen_install_args[@]}"
+ fi
+ elif [[ ! -x "${cbindgen_bin}" ]]; then
+ echo "PAIMON_RUST_CBINDGEN=${cbindgen_bin} is not an executable file."
+ exit 1
+ fi
+ # Write a temporary cbindgen.toml so the generated header carries our
+ # include-guard / cpp-compat settings without touching the upstream tree.
+ local cbindgen_toml="${BUILD_DIR}/cbindgen.toml"
+ mkdir -p "${BUILD_DIR}"
+ cat >"${cbindgen_toml}" <<'EOF'
+language = "C"
+include_guard = "PAIMON_C_H"
+pragma_once = true
+cpp_compat = true
+EOF
+ env "${cargo_env[@]}" "${cbindgen_bin}" bindings/c \
+ --config "${cbindgen_toml}" \
+ --output "${BUILD_DIR}/release/paimon.h"
+
+ mkdir -p "${TP_INSTALL_DIR}/include" "${TP_INSTALL_DIR}/lib64"
+ rm -rf "${TP_INSTALL_DIR}/include/paimon_rust"
+ mkdir -p "${TP_INSTALL_DIR}/include/paimon_rust"
+ cp -v "${BUILD_DIR}/release/paimon.h"
"${TP_INSTALL_DIR}/include/paimon_rust/"
+ install_rust_archive "${BUILD_DIR}/release/libpaimon_c.a"
}
if [[ "${#packages[@]}" -eq 0 ]]; then
@@ -2526,6 +2671,7 @@ if [[ "${#packages[@]}" -eq 0 ]]; then
icu
mecab_ipadic
pugixml
+ paimon_rust
)
if [[ "$(uname -s)" == 'Darwin' ]]; then
read -r -a packages <<<"binutils gettext ${packages[*]}"
@@ -2636,6 +2782,7 @@ cleanup_package_source() {
juicefs) src_var="JUICEFS_SOURCE" ;;
pugixml) src_var="PUGIXML_SOURCE" ;;
lance_c) src_var="LANCE_C_SOURCE" ;;
+ paimon_rust) src_var="PAIMON_RUST_SOURCE" ;;
aws_sdk) src_var="AWS_SDK_SOURCE" ;;
lzma) src_var="LZMA_SOURCE" ;;
xml2) src_var="XML2_SOURCE" ;;
diff --git a/thirdparty/test/paimon-build-test.py
b/thirdparty/test/paimon-build-test.py
new file mode 100644
index 00000000000..3fef1ffe6fc
--- /dev/null
+++ b/thirdparty/test/paimon-build-test.py
@@ -0,0 +1,202 @@
+#!/usr/bin/env python3
+# 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.
+
+"""Run with python3 thirdparty/test/paimon-build-test.py; no Rust downloads
required."""
+
+import os
+from pathlib import Path
+import re
+import subprocess
+import tempfile
+import unittest
+
+
+ROOT = Path(__file__).resolve().parents[2]
+
+
+class PaimonBuildTest(unittest.TestCase):
+ def setUp(self):
+ self.temp = tempfile.TemporaryDirectory()
+ self.addCleanup(self.temp.cleanup)
+ self.work = Path(self.temp.name)
+ self.env = dict(os.environ)
+ for key in ("CARGO", "CARGO_NET_OFFLINE", "RUSTUP_TOOLCHAIN"):
+ self.env.pop(key, None)
+
+ def write(self, name, text=""):
+ path = self.work / name
+ path.parent.mkdir(parents=True, exist_ok=True)
+ path.write_text(text)
+ return path
+
+ def executable(self, name, text):
+ path = self.write(name, "#!/bin/bash\nset -e\n" + text)
+ path.chmod(0o755)
+ return path
+
+ def run_bash(self, script):
+ return subprocess.run(["bash", "-ec", script], env=self.env,
+ cwd=self.work, text=True, capture_output=True)
+
+ def check_install(self, system, missing, clean=0):
+ script = (ROOT / "build.sh").read_text()
+ gate = script[script.index("# build thirdparty libraries if
necessary."):
+ script.index("update_submodule() {")]
+ sentinel = re.search(r"else\n LAST_THIRDPARTY_LIB='([^']+)'",
gate)[1]
+ if system == "Darwin":
+ sentinel = "libbrotlienc.a"
+ files = ["lib/" + sentinel, "lib64/liblance_c.a",
"lib64/libpaimon_c.a",
+ "include/paimon_rust/paimon.h"]
+ for name in files:
+ if name != missing:
+ self.write("installed/" + name)
+ # Execute the real installation gate, replacing only the expensive
build.
+ self.executable("build-thirdparty.sh", 'printf "%s\\n" "$*" >
"$BUILD_LOG"\n')
+ self.env.update(DORIS_THIRDPARTY=str(self.work), TARGET_SYSTEM=system,
+ CLEAN=str(clean), PARALLEL="2",
BUILD_LOG=str(self.work / "build.log"))
+ result = self.run_bash(gate)
+ self.assertEqual(result.returncode, 0, result.stderr)
+ self.assertEqual((self.work / "build.log").exists(), missing is not
None)
+ if missing is not None:
+ args = (self.work / "build.log").read_text().strip()
+ self.assertEqual(args, "-j 2" + (" --clean" if clean else ""))
+ # A full rebuild also replaces Lance built with the previous Rust
version.
+ self.assertFalse((self.work /
"installed/lib64/liblance_c.a").exists())
+
+ def test_old_linux_install_rebuilds(self):
+ self.check_install("Linux", "lib64/libpaimon_c.a")
+
+ def test_old_macos_install_rebuilds(self):
+ self.check_install("Darwin", "lib64/libpaimon_c.a")
+
+ def test_missing_header_rebuilds(self):
+ self.check_install("Linux", "include/paimon_rust/paimon.h")
+
+ def test_missing_lance_rebuilds(self):
+ self.check_install("Linux", "lib64/liblance_c.a")
+
+ def test_clean_option_is_preserved(self):
+ self.check_install("Linux", "lib64/libpaimon_c.a", clean=1)
+
+ def test_complete_install_is_reused(self):
+ self.check_install("Linux", None)
+
+ def archive_installer(self):
+ script = (ROOT / "thirdparty/build-thirdparty.sh").read_text()
+ return re.search(r"^install_rust_archive\(\) \{\n.*?^\}", script, re.M
| re.S)[0]
+
+ def check_archive_publication(self, name):
+ source = self.write("build/" + name, "new archive")
+ source.chmod(0o644)
+ destination = self.work / "installed/lib64" / name
+ destination.parent.mkdir(parents=True, exist_ok=True)
+ self.env.update(TP_INSTALL_DIR=str(self.work / "installed"),
+ STRIP_TP_LIB="ON", KERNEL="Linux", ARCHIVE=str(source))
+ failures = {
+ "copy": 'cp() { printf partial > "${@: -1}"; return 1; }',
+ "strip": 'strip() { printf damaged > "${@: -1}"; return 1; }',
+ "publish": 'mv() { return 1; }',
+ "success": '',
+ }
+ for replacement in (False, True):
+ for stage, injection in failures.items():
+ with self.subTest(archive=name, replacement=replacement,
stage=stage):
+ if destination.exists():
+ destination.unlink()
+ if replacement:
+ destination.write_text("old archive")
+ # Execute the production publisher with failures after
partial copy/strip;
+ # neither a first install nor a replacement may expose
those bytes.
+ result = self.run_bash(self.archive_installer() +
+ '\nstrip() { :; }\n' + injection +
+ '\ninstall_rust_archive "$ARCHIVE"')
+ if stage == "success":
+ self.assertEqual(result.returncode, 0, result.stderr)
+ self.assertEqual(destination.read_text(), "new
archive")
+ self.assertEqual(destination.stat().st_mode & 0o777,
0o644)
+ else:
+ self.assertNotEqual(result.returncode, 0)
+ if replacement:
+ self.assertEqual(destination.read_text(), "old
archive")
+ else:
+ self.assertFalse(destination.exists())
+ self.assertEqual(list(destination.parent.glob(name +
".tmp.*")), [])
+
+ def test_atomic_lance_archive_publication(self):
+ self.check_archive_publication("liblance_c.a")
+
+ def test_atomic_paimon_archive_publication(self):
+ self.check_archive_publication("libpaimon_c.a")
+
+ def check_header(self, offline, inherited_offline="", cargo_override=True):
+ script = (ROOT / "thirdparty/build-thirdparty.sh").read_text()
+ function = re.search(r"^build_paimon_rust\(\) \{\n.*?^\}", script,
re.M | re.S)[0]
+ cargo = self.executable("custom/cargo", r'''case "$1" in
+ --version) echo 'cargo 1.94.0' ;;
+ build)
+ mkdir -p "$CARGO_TARGET_DIR/release"
+ touch "$CARGO_TARGET_DIR/release/libpaimon_c.a"
+ ;;
+ metadata) printf '%s' "${CARGO_NET_OFFLINE:-unset}" > "$METADATA_LOG" ;;
+ *) exit 90 ;;
+esac
+''')
+ # PATH's Cargo deliberately fails: metadata must use the selected
executable.
+ self.executable("bin/cargo", "exit 91\n")
+ cbindgen = self.executable("bin/cbindgen", r'''"${CARGO:-cargo}"
metadata
+while [[ "$1" != --output ]]; do shift; done
+printf '/* Generated test header */\n' > "$2"
+''')
+ self.write("src/paimon/Cargo.toml")
+ self.env.update(PATH=str(self.work / "bin") + os.pathsep +
os.environ["PATH"],
+ TP_SOURCE_DIR=str(self.work / "src"),
PAIMON_RUST_SOURCE="paimon",
+ TP_INSTALL_DIR=str(self.work / "installed"),
BUILD_DIR="build",
+ PARALLEL="1", KERNEL="Linux", STRIP_TP_LIB="OFF",
+ RUSTUP_TOOLCHAIN="1.94.0",
PAIMON_RUST_CARGO_OFFLINE=offline,
+ PAIMON_RUST_CBINDGEN=str(cbindgen),
+ METADATA_LOG=str(self.work / "metadata.log"))
+ if cargo_override:
+ self.env["PAIMON_RUST_CARGO"] = str(cargo)
+ else:
+ self.env.pop("PAIMON_RUST_CARGO", None)
+ self.env["CARGO"] = str(cargo)
+ if inherited_offline:
+ self.env["CARGO_NET_OFFLINE"] = inherited_offline
+ result = self.run_bash("check_if_source_exist() { :; }\n" +
self.archive_installer()
+ + "\n" + function + "\nbuild_paimon_rust")
+ self.assertEqual(result.returncode, 0, result.stdout + result.stderr)
+ expected = "true" if offline.upper() == "ON" else inherited_offline or
"unset"
+ self.assertEqual((self.work / "metadata.log").read_text(), expected)
+ self.assertTrue((self.work /
"installed/include/paimon_rust/paimon.h").exists())
+ self.assertTrue((self.work / "installed/lib64/libpaimon_c.a").exists())
+
+ def test_header_uses_selected_cargo(self):
+ self.check_header("OFF")
+
+ def test_header_metadata_is_offline(self):
+ self.check_header("on", cargo_override=False)
+
+ def test_offline_override_wins(self):
+ self.check_header("ON", inherited_offline="false",
cargo_override=False)
+
+ def test_inherited_offline_is_preserved(self):
+ self.check_header("OFF", inherited_offline="true",
cargo_override=False)
+
+
+if __name__ == "__main__":
+ unittest.main(verbosity=2)
diff --git a/thirdparty/vars.sh b/thirdparty/vars.sh
index 348d638c85d..f17ed8df35e 100644
--- a/thirdparty/vars.sh
+++ b/thirdparty/vars.sh
@@ -622,6 +622,12 @@ LANCE_C_NAME="lance-c-v0.1.9.tar.gz"
LANCE_C_SOURCE="lance-c-0.1.9"
LANCE_C_MD5SUM="7138ed44e92d4bc91d5b522a6b92ed64"
+# paimon-rust
+PAIMON_RUST_DOWNLOAD="https://github.com/apache/paimon-rust/archive/refs/tags/v0.4.0-rc1.tar.gz"
+PAIMON_RUST_NAME="paimon-rust-v0.4.0-rc1.tar.gz"
+PAIMON_RUST_SOURCE="paimon-rust-0.4.0-rc1"
+PAIMON_RUST_MD5SUM="23cd0634692108debf77a26ef4dc20a7"
+
# all thirdparties which need to be downloaded is set in array TP_ARCHIVES
export TP_ARCHIVES=(
'MECAB_IPADIC'
@@ -710,6 +716,7 @@ export TP_ARCHIVES=(
'JUICEFS'
'PUGIXML'
'LANCE_C'
+ 'PAIMON_RUST'
)
# Only defined on the platforms upstream ships a prebuilt driver for (see
above).
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]