Skip to content

Commit ab9fac3

Browse files
committed
[chore](build) Add paimon-rust third-party build integration
### What problem does this PR solve? Related PR: #66227 Problem Summary: Prepare the Paimon Rust C library dependency independently of the reader implementation. Pin the Apache v0.4.0-rc1 source, build its HDFS-enabled static library and generated C header, align Lance and Paimon on Rust 1.94.0, and preserve libm and glibc compatibility link ordering. ### Release note None ### Check List (For Author) - Test: Shell syntax, mock build/install scenarios, CMake link-order checks, and source archive checksum verification passed. Full native compilation was not run locally. - Behavior changed: Yes, third-party builds include paimon-rust and use Rust 1.94.0 for both Rust libraries. - Does this need documentation: No, this prepares an internal build dependency.
1 parent 6cfe365 commit ab9fac3

4 files changed

Lines changed: 153 additions & 5 deletions

File tree

‎be/CMakeLists.txt‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -860,7 +860,8 @@ if (GLIBC_COMPATIBILITY)
860860
glibc-compatibility-explicit
861861
glibc-compatibility
862862
-lm
863-
lance_c)
863+
lance_c
864+
paimon_c)
864865
endif()
865866

866867
if (NOT OS_MACOSX)

‎be/cmake/thirdparty.cmake‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,13 @@ add_thirdparty(lance_c LIB64 NOTADD)
120120
if (NOT GLIBC_COMPATIBILITY)
121121
list(APPEND COMMON_THIRDPARTY m lance_c)
122122
endif()
123+
# libpaimon_c.a (built from paimon-rust) brings in Rust compiler_builtins that
124+
# would otherwise steal libm symbols. Place libm before it so the final linker
125+
# resolves C math symbols from the system library first.
126+
add_thirdparty(paimon_c LIB64 NOTADD)
127+
if (NOT GLIBC_COMPATIBILITY)
128+
list(APPEND COMMON_THIRDPARTY m paimon_c)
129+
endif()
123130
add_thirdparty(brpc LIB64)
124131
add_thirdparty(rocksdb)
125132
add_thirdparty(cyrus-sasl LIBNAME "lib/libsasl2.a")

‎thirdparty/build-thirdparty.sh‎

Lines changed: 137 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2381,22 +2381,28 @@ build_lance_c() {
23812381

23822382
local cargo_bin="${LANCE_C_CARGO:-${CARGO:-cargo}}"
23832383
if ! command -v "${cargo_bin}" >/dev/null 2>&1; then
2384-
echo "cargo is required to build lance-c. Install Rust 1.91.0 or set LANCE_C_CARGO."
2384+
echo "cargo is required to build lance-c. Install Rust 1.94.0 or set LANCE_C_CARGO."
23852385
exit 1
23862386
fi
23872387
if [[ ! -x "${TP_INSTALL_DIR}/bin/protoc" ]]; then
23882388
echo "protoc is required to build lance-c. Build protobuf first."
23892389
exit 1
23902390
fi
23912391

2392-
local required_rust_version="1.91.0"
2392+
local required_rust_version="1.94.0"
23932393
local cargo_env=(
23942394
"CARGO_BUILD_JOBS=${PARALLEL}"
23952395
"CARGO_TARGET_DIR=${PWD}/${BUILD_DIR}"
23962396
"PROTOC=${TP_INSTALL_DIR}/bin/protoc"
23972397
)
23982398
if command -v rustup >/dev/null 2>&1 && [[ -z "${RUSTUP_TOOLCHAIN}" ]]; then
2399-
if ! rustup toolchain list | grep -Eq '^1\.91\.0([[:space:]-]|$)'; then
2399+
# The presence check must look for the toolchain the minimum actually
2400+
# requires, not a literal: with only an older toolchain installed the
2401+
# stale check would skip the install below and then force
2402+
# RUSTUP_TOOLCHAIN to a version rustup cannot dispatch, failing the
2403+
# build before any archive is produced.
2404+
local required_rust_regex="${required_rust_version//./\\.}"
2405+
if ! rustup toolchain list | grep -Eq "^${required_rust_regex}([[:space:]-]|$)"; then
24002406
rustup toolchain install "${required_rust_version}" --profile minimal
24012407
fi
24022408
cargo_env+=("RUSTUP_TOOLCHAIN=${required_rust_version}")
@@ -2407,7 +2413,7 @@ build_lance_c() {
24072413
echo "failed to get cargo version for lance-c. Install Rust ${required_rust_version} or set LANCE_C_CARGO/RUSTUP_TOOLCHAIN."
24082414
exit 1
24092415
fi
2410-
# Rust 1.91.0 is the minimum supported version. Allow newer toolchains when
2416+
# Rust 1.94.0 is the minimum supported version. Allow newer toolchains when
24112417
# callers explicitly select one or rustup is unavailable on the system.
24122418
if ! awk -v required="${required_rust_version}" -v actual="${cargo_version}" 'BEGIN {
24132419
split(required, r, ".");
@@ -2447,6 +2453,131 @@ build_lance_c() {
24472453
fi
24482454
}
24492455

2456+
build_paimon_rust() {
2457+
check_if_source_exist "${PAIMON_RUST_SOURCE}"
2458+
cd "${TP_SOURCE_DIR}/${PAIMON_RUST_SOURCE}"
2459+
2460+
rm -rf "${BUILD_DIR}"
2461+
mkdir -p "${BUILD_DIR}"
2462+
2463+
local cargo_bin="${PAIMON_RUST_CARGO:-${CARGO:-cargo}}"
2464+
if ! command -v "${cargo_bin}" >/dev/null 2>&1; then
2465+
echo "cargo is required to build paimon-rust. Install Rust 1.94.0 or set PAIMON_RUST_CARGO."
2466+
exit 1
2467+
fi
2468+
2469+
local required_rust_version="1.94.0"
2470+
local cargo_env=(
2471+
"CARGO_BUILD_JOBS=${PARALLEL}"
2472+
"CARGO_TARGET_DIR=${PWD}/${BUILD_DIR}"
2473+
)
2474+
if command -v rustup >/dev/null 2>&1 && [[ -z "${RUSTUP_TOOLCHAIN}" ]]; then
2475+
# The presence check must look for the toolchain the minimum actually
2476+
# requires, not a literal: with only an older toolchain installed the
2477+
# stale check would skip the install below and then force
2478+
# RUSTUP_TOOLCHAIN to a version rustup cannot dispatch, failing the
2479+
# build before any archive is produced.
2480+
local required_rust_regex="${required_rust_version//./\\.}"
2481+
if ! rustup toolchain list | grep -Eq "^${required_rust_regex}([[:space:]-]|$)"; then
2482+
rustup toolchain install "${required_rust_version}" --profile minimal
2483+
fi
2484+
cargo_env+=("RUSTUP_TOOLCHAIN=${required_rust_version}")
2485+
fi
2486+
2487+
local cargo_version
2488+
if ! cargo_version="$(env "${cargo_env[@]}" "${cargo_bin}" --version | awk '{print $2}')"; then
2489+
echo "failed to get cargo version for paimon-rust. Install Rust ${required_rust_version} or set PAIMON_RUST_CARGO/RUSTUP_TOOLCHAIN."
2490+
exit 1
2491+
fi
2492+
# Rust 1.94.0 is the minimum supported version. Allow newer toolchains when
2493+
# callers explicitly select one or rustup is unavailable on the system.
2494+
# NOTE: paimon_c and lance_c are both Rust staticlibs linked into the same
2495+
# BE binary; they must be built with the SAME rustc toolchain so the linker
2496+
# resolves both crates' std references against a single std copy. Mixing
2497+
# toolchains makes the precompiled std hashes differ and the linker pulls
2498+
# both std copies in, colliding on the unmangled `rust_eh_personality`
2499+
# (duplicate symbol). Rebuild both lance_c and paimon_rust whenever the
2500+
# toolchain changes, using the same RUSTUP_TOOLCHAIN for both builds.
2501+
if ! awk -v required="${required_rust_version}" -v actual="${cargo_version}" 'BEGIN {
2502+
split(required, r, ".");
2503+
split(actual, a, ".");
2504+
for (i = 1; i <= 3; i++) {
2505+
if ((a[i] + 0) > (r[i] + 0)) {
2506+
exit 0;
2507+
}
2508+
if ((a[i] + 0) < (r[i] + 0)) {
2509+
exit 1;
2510+
}
2511+
}
2512+
exit 0;
2513+
}'; then
2514+
echo "paimon-rust requires Rust/Cargo ${required_rust_version} or newer, but found ${cargo_version}."
2515+
echo "Install Rust ${required_rust_version} or set PAIMON_RUST_CARGO/RUSTUP_TOOLCHAIN."
2516+
exit 1
2517+
fi
2518+
2519+
if [[ "${KERNEL}" != 'Darwin' ]]; then
2520+
cargo_env+=("CFLAGS=${CFLAGS:-} -std=gnu17")
2521+
fi
2522+
2523+
local cargo_args=(build --release --locked -p paimon-c --features paimon/storage-hdfs)
2524+
if [[ "$(echo "${PAIMON_RUST_CARGO_OFFLINE}" | tr '[:lower:]' '[:upper:]')" == "ON" ]]; then
2525+
cargo_args+=(--offline)
2526+
fi
2527+
env "${cargo_env[@]}" "${cargo_bin}" "${cargo_args[@]}"
2528+
2529+
# Generate the C header from the Rust extern "C" surface via cbindgen.
2530+
# cbindgen is a pinned, Doris-controlled input: an unpinned "current"
2531+
# release would regenerate paimon.h differently between builds. The
2532+
# pinned version installs under a Doris-controlled --root and its
2533+
# resolved absolute path is invoked directly (a custom CARGO_HOME does
2534+
# not necessarily put cargo-installed binaries on PATH). Offline builds
2535+
# pass --offline to the install command, exactly like the fetch/build
2536+
# handling above — cargo fails on a missing local crate cache instead
2537+
# of reaching for the network.
2538+
local cbindgen_version="0.29.4"
2539+
local cbindgen_bin="${PAIMON_RUST_CBINDGEN:-}"
2540+
if [[ -z "${cbindgen_bin}" ]]; then
2541+
local cbindgen_root="${TP_SOURCE_DIR}/.doris-cbindgen-${cbindgen_version}"
2542+
cbindgen_bin="${cbindgen_root}/bin/cbindgen"
2543+
if [[ ! -x "${cbindgen_bin}" ]]; then
2544+
local cbindgen_install_args=(install cbindgen
2545+
--version "${cbindgen_version}" --locked --root "${cbindgen_root}")
2546+
if [[ "$(echo "${PAIMON_RUST_CARGO_OFFLINE}" | tr '[:lower:]' '[:upper:]')" == "ON" ]]; then
2547+
cbindgen_install_args+=(--offline)
2548+
fi
2549+
echo "cbindgen not found; installing pinned ${cbindgen_version} via cargo install ..."
2550+
env "${cargo_env[@]}" "${cargo_bin}" "${cbindgen_install_args[@]}"
2551+
fi
2552+
elif [[ ! -x "${cbindgen_bin}" ]]; then
2553+
echo "PAIMON_RUST_CBINDGEN=${cbindgen_bin} is not an executable file."
2554+
exit 1
2555+
fi
2556+
# Write a temporary cbindgen.toml so the generated header carries our
2557+
# include-guard / cpp-compat settings without touching the upstream tree.
2558+
local cbindgen_toml="${BUILD_DIR}/cbindgen.toml"
2559+
mkdir -p "${BUILD_DIR}"
2560+
cat >"${cbindgen_toml}" <<'EOF'
2561+
language = "C"
2562+
include_guard = "PAIMON_C_H"
2563+
pragma_once = true
2564+
cpp_compat = true
2565+
EOF
2566+
env "${cargo_env[@]}" "${cbindgen_bin}" bindings/c \
2567+
--config "${cbindgen_toml}" \
2568+
--output "${BUILD_DIR}/release/paimon.h"
2569+
2570+
mkdir -p "${TP_INSTALL_DIR}/include" "${TP_INSTALL_DIR}/lib64"
2571+
rm -rf "${TP_INSTALL_DIR}/include/paimon_rust"
2572+
mkdir -p "${TP_INSTALL_DIR}/include/paimon_rust"
2573+
cp -v "${BUILD_DIR}/release/paimon.h" "${TP_INSTALL_DIR}/include/paimon_rust/"
2574+
cp -v "${BUILD_DIR}/release/libpaimon_c.a" "${TP_INSTALL_DIR}/lib64/"
2575+
2576+
if [[ "${STRIP_TP_LIB}" = "ON" && "${KERNEL}" != 'Darwin' ]]; then
2577+
strip --strip-debug --strip-unneeded "${TP_INSTALL_DIR}/lib64/libpaimon_c.a"
2578+
fi
2579+
}
2580+
24502581
if [[ "${#packages[@]}" -eq 0 ]]; then
24512582
packages=(
24522583
jindofs
@@ -2526,6 +2657,7 @@ if [[ "${#packages[@]}" -eq 0 ]]; then
25262657
icu
25272658
mecab_ipadic
25282659
pugixml
2660+
paimon_rust
25292661
)
25302662
if [[ "$(uname -s)" == 'Darwin' ]]; then
25312663
read -r -a packages <<<"binutils gettext ${packages[*]}"
@@ -2636,6 +2768,7 @@ cleanup_package_source() {
26362768
juicefs) src_var="JUICEFS_SOURCE" ;;
26372769
pugixml) src_var="PUGIXML_SOURCE" ;;
26382770
lance_c) src_var="LANCE_C_SOURCE" ;;
2771+
paimon_rust) src_var="PAIMON_RUST_SOURCE" ;;
26392772
aws_sdk) src_var="AWS_SDK_SOURCE" ;;
26402773
lzma) src_var="LZMA_SOURCE" ;;
26412774
xml2) src_var="XML2_SOURCE" ;;

‎thirdparty/vars.sh‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -622,6 +622,12 @@ LANCE_C_NAME="lance-c-v0.1.9.tar.gz"
622622
LANCE_C_SOURCE="lance-c-0.1.9"
623623
LANCE_C_MD5SUM="7138ed44e92d4bc91d5b522a6b92ed64"
624624

625+
# paimon-rust
626+
PAIMON_RUST_DOWNLOAD="https://github.com/apache/paimon-rust/archive/refs/tags/v0.4.0-rc1.tar.gz"
627+
PAIMON_RUST_NAME="paimon-rust-v0.4.0-rc1.tar.gz"
628+
PAIMON_RUST_SOURCE="paimon-rust-0.4.0-rc1"
629+
PAIMON_RUST_MD5SUM="23cd0634692108debf77a26ef4dc20a7"
630+
625631
# all thirdparties which need to be downloaded is set in array TP_ARCHIVES
626632
export TP_ARCHIVES=(
627633
'MECAB_IPADIC'
@@ -710,6 +716,7 @@ export TP_ARCHIVES=(
710716
'JUICEFS'
711717
'PUGIXML'
712718
'LANCE_C'
719+
'PAIMON_RUST'
713720
)
714721

715722
# Only defined on the platforms upstream ships a prebuilt driver for (see above).

0 commit comments

Comments
 (0)