This is an automated email from the ASF dual-hosted git repository.
yuxia pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/fluss-rust.git
The following commit(s) were added to refs/heads/main by this push:
new bb8f26d feat: support bazel build for cpp bindings (#107)
bb8f26d is described below
commit bb8f26dee41f827d1937a1e68ad4b21d7b89616f
Author: AlexZhao <[email protected]>
AuthorDate: Fri Jan 2 19:37:56 2026 +0800
feat: support bazel build for cpp bindings (#107)
---
bindings/cpp/.bazelrc | 37 +++++
bindings/cpp/.gitignore | 9 ++
bindings/cpp/BUILD.bazel | 342 ++++++++++++++++++++++++++++++++++++++++++++++
bindings/cpp/MODULE.bazel | 23 ++++
bindings/cpp/ci.sh | 100 ++++++++++++++
5 files changed, 511 insertions(+)
diff --git a/bindings/cpp/.bazelrc b/bindings/cpp/.bazelrc
new file mode 100644
index 0000000..ce7d81f
--- /dev/null
+++ b/bindings/cpp/.bazelrc
@@ -0,0 +1,37 @@
+# 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.
+
+# Bazel configuration for fluss-rust C++ bindings
+
+# Enable BzlMod
+common --enable_bzlmod
+
+# Debug configuration (matches BUILD.bazel settings)
+build:debug --compilation_mode=dbg
+build:debug --copt=-g3
+build:debug --copt=-ggdb
+build:debug --copt=-O0
+build:debug --copt=-fno-omit-frame-pointer
+build:debug --copt=-DDEBUG
+build:debug --strip=never
+build:debug --linkopt=-g
+
+# Release configuration
+build:release --compilation_mode=opt
+build:release --copt=-O2
+build:release --copt=-DNDEBUG
+build:release --strip=always
diff --git a/bindings/cpp/.gitignore b/bindings/cpp/.gitignore
index 6836e70..43f761c 100644
--- a/bindings/cpp/.gitignore
+++ b/bindings/cpp/.gitignore
@@ -5,3 +5,12 @@ cmake-build-*/
*.a
*.so
*.dylib
+
+# Bazel build outputs
+bazel-build/
+bazel-bin
+bazel-out
+bazel-testlogs
+bazel-cpp
+bazel-*
+MODULE.bazel.lock
diff --git a/bindings/cpp/BUILD.bazel b/bindings/cpp/BUILD.bazel
new file mode 100644
index 0000000..81d483c
--- /dev/null
+++ b/bindings/cpp/BUILD.bazel
@@ -0,0 +1,342 @@
+# 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.
+
+licenses(["notice"])
+
+load("@rules_cc//cc:defs.bzl", "cc_library", "cc_binary")
+
+config_setting(
+ name = "debug_mode",
+ values = {"compilation_mode": "dbg"},
+)
+
+config_setting(
+ name = "fastbuild_mode",
+ values = {"compilation_mode": "fastbuild"},
+)
+
+config_setting(
+ name = "release_mode",
+ values = {"compilation_mode": "opt"},
+)
+
+genrule(
+ name = "cargo_build_debug",
+ srcs = glob([
+ "src/**/*.rs",
+ "Cargo.toml",
+ ]),
+ outs = [
+ "rust_lib_debug.a",
+ "rust_bridge_cc_debug.cc",
+ "rust_bridge_h_debug.h",
+ "src/lib.rs_debug.h",
+ "cxxbridge/rust/cxx_debug.h",
+ ],
+ cmd = """
+ set -e
+ EXECROOT=$$(pwd)
+ OUTPUT_LIB=$(location rust_lib_debug.a)
+ OUTPUT_CC=$(location rust_bridge_cc_debug.cc)
+ OUTPUT_H=$(location rust_bridge_h_debug.h)
+ OUTPUT_SRC_H=$(location src/lib.rs_debug.h)
+ OUTPUT_CXX_H=$(location cxxbridge/rust/cxx_debug.h)
+ # Resolve real source path from sandbox symlink
+ SANDBOX_CARGO=$(location Cargo.toml)
+ REAL_CARGO=$$(readlink -f $$SANDBOX_CARGO 2>/dev/null || python3 -c
"import os; print(os.path.realpath('$$SANDBOX_CARGO'))")
+ CARGO_DIR=$$(dirname $$REAL_CARGO)
+ # Find Cargo workspace root (fluss-rust directory, 2 levels up from
bindings/cpp)
+ WORKSPACE_ROOT=$$(cd $$CARGO_DIR/../.. && pwd)
+ if [ ! -f $$WORKSPACE_ROOT/Cargo.toml ]; then
+ echo "Error: Cannot find workspace root Cargo.toml at
$$WORKSPACE_ROOT" >&2
+ exit 1
+ fi
+ cd $$WORKSPACE_ROOT
+ cargo build --manifest-path $$CARGO_DIR/Cargo.toml
+ CARGO_TARGET_DIR=$$WORKSPACE_ROOT/target
+ # cxxbridge uses the Cargo package name (with hyphen): fluss-cpp
+ RUST_BRIDGE_DIR=$$CARGO_TARGET_DIR/cxxbridge/fluss-cpp/src
+ # Cargo converts hyphens to underscores in library file names:
libfluss_cpp.a
+ RUST_LIB=$$CARGO_TARGET_DIR/debug/libfluss_cpp.a
+ if [ ! -f $$RUST_LIB ]; then
+ echo "Error: Rust library not found at $$RUST_LIB" >&2
+ exit 1
+ fi
+ if [ ! -f $$RUST_BRIDGE_DIR/lib.rs.cc ]; then
+ echo "Error: cxxbridge CC file not found at
$$RUST_BRIDGE_DIR/lib.rs.cc" >&2
+ exit 1
+ fi
+ if [ ! -f $$RUST_BRIDGE_DIR/lib.rs.h ]; then
+ echo "Error: cxxbridge header file not found at
$$RUST_BRIDGE_DIR/lib.rs.h" >&2
+ exit 1
+ fi
+ cd $$EXECROOT
+ mkdir -p $$(dirname $$OUTPUT_SRC_H) $$(dirname $$OUTPUT_CXX_H)
+ cp $$RUST_LIB $$OUTPUT_LIB || (echo "Failed to copy $$RUST_LIB to
$$OUTPUT_LIB" >&2; exit 1)
+ cp $$RUST_BRIDGE_DIR/lib.rs.cc $$OUTPUT_CC || (echo "Failed to copy
$$RUST_BRIDGE_DIR/lib.rs.cc to $$OUTPUT_CC" >&2; exit 1)
+ cp $$RUST_BRIDGE_DIR/lib.rs.h $$OUTPUT_H || (echo "Failed to copy
$$RUST_BRIDGE_DIR/lib.rs.h to $$OUTPUT_H" >&2; exit 1)
+ cp $$RUST_BRIDGE_DIR/lib.rs.h $$OUTPUT_SRC_H || (echo "Failed to copy
$$RUST_BRIDGE_DIR/lib.rs.h to $$OUTPUT_SRC_H" >&2; exit 1)
+ CXX_H_SOURCE=$$CARGO_TARGET_DIR/cxxbridge/rust/cxx.h
+ if [ ! -f $$CXX_H_SOURCE ] && [ ! -L $$CXX_H_SOURCE ]; then
+ echo "Error: cxx.h not found at $$CXX_H_SOURCE" >&2
+ exit 1
+ fi
+ cp -L $$CXX_H_SOURCE $$OUTPUT_CXX_H || (echo "Failed to copy
$$CXX_H_SOURCE to $$OUTPUT_CXX_H" >&2; exit 1)
+ """,
+ message = "Building Rust library (debug) with cargo...",
+ local = 1,
+)
+
+genrule(
+ name = "cargo_build_release",
+ srcs = glob([
+ "src/**/*.rs",
+ "Cargo.toml",
+ ]),
+ outs = [
+ "rust_lib_release.a",
+ "rust_bridge_cc_release.cc",
+ "rust_bridge_h_release.h",
+ "src/lib.rs_release.h",
+ "cxxbridge/rust/cxx_release.h",
+ ],
+ cmd = """
+ set -e
+ EXECROOT=$$(pwd)
+ OUTPUT_LIB=$(location rust_lib_release.a)
+ OUTPUT_CC=$(location rust_bridge_cc_release.cc)
+ OUTPUT_H=$(location rust_bridge_h_release.h)
+ OUTPUT_SRC_H=$(location src/lib.rs_release.h)
+ OUTPUT_CXX_H=$(location cxxbridge/rust/cxx_release.h)
+ # Resolve real source path from sandbox symlink
+ SANDBOX_CARGO=$(location Cargo.toml)
+ REAL_CARGO=$$(readlink -f $$SANDBOX_CARGO 2>/dev/null || python3 -c
"import os; print(os.path.realpath('$$SANDBOX_CARGO'))")
+ CARGO_DIR=$$(dirname $$REAL_CARGO)
+ # Find Cargo workspace root (fluss-rust directory, 2 levels up from
bindings/cpp)
+ WORKSPACE_ROOT=$$(cd $$CARGO_DIR/../.. && pwd)
+ if [ ! -f $$WORKSPACE_ROOT/Cargo.toml ]; then
+ echo "Error: Cannot find workspace root Cargo.toml at
$$WORKSPACE_ROOT" >&2
+ exit 1
+ fi
+ cd $$WORKSPACE_ROOT
+ cargo build --release --manifest-path $$CARGO_DIR/Cargo.toml
+ CARGO_TARGET_DIR=$$WORKSPACE_ROOT/target
+ # cxxbridge uses the Cargo package name (with hyphen): fluss-cpp
+ RUST_BRIDGE_DIR=$$CARGO_TARGET_DIR/cxxbridge/fluss-cpp/src
+ # Cargo converts hyphens to underscores in library file names:
libfluss_cpp.a
+ RUST_LIB=$$CARGO_TARGET_DIR/release/libfluss_cpp.a
+ if [ ! -f $$RUST_LIB ]; then
+ echo "Error: Rust library not found at $$RUST_LIB" >&2
+ exit 1
+ fi
+ if [ ! -f $$RUST_BRIDGE_DIR/lib.rs.cc ]; then
+ echo "Error: cxxbridge CC file not found at
$$RUST_BRIDGE_DIR/lib.rs.cc" >&2
+ exit 1
+ fi
+ if [ ! -f $$RUST_BRIDGE_DIR/lib.rs.h ]; then
+ echo "Error: cxxbridge header file not found at
$$RUST_BRIDGE_DIR/lib.rs.h" >&2
+ exit 1
+ fi
+ cd $$EXECROOT
+ mkdir -p $$(dirname $$OUTPUT_SRC_H) $$(dirname $$OUTPUT_CXX_H)
+ cp $$RUST_LIB $$OUTPUT_LIB || (echo "Failed to copy $$RUST_LIB to
$$OUTPUT_LIB" >&2; exit 1)
+ cp $$RUST_BRIDGE_DIR/lib.rs.cc $$OUTPUT_CC || (echo "Failed to copy
$$RUST_BRIDGE_DIR/lib.rs.cc to $$OUTPUT_CC" >&2; exit 1)
+ cp $$RUST_BRIDGE_DIR/lib.rs.h $$OUTPUT_H || (echo "Failed to copy
$$RUST_BRIDGE_DIR/lib.rs.h to $$OUTPUT_H" >&2; exit 1)
+ cp $$RUST_BRIDGE_DIR/lib.rs.h $$OUTPUT_SRC_H || (echo "Failed to copy
$$RUST_BRIDGE_DIR/lib.rs.h to $$OUTPUT_SRC_H" >&2; exit 1)
+ CXX_H_SOURCE=$$CARGO_TARGET_DIR/cxxbridge/rust/cxx.h
+ if [ ! -f $$CXX_H_SOURCE ] && [ ! -L $$CXX_H_SOURCE ]; then
+ echo "Error: cxx.h not found at $$CXX_H_SOURCE" >&2
+ exit 1
+ fi
+ cp -L $$CXX_H_SOURCE $$OUTPUT_CXX_H || (echo "Failed to copy
$$CXX_H_SOURCE to $$OUTPUT_CXX_H" >&2; exit 1)
+ """,
+ message = "Building Rust library (release) with cargo...",
+ local = 1,
+)
+
+filegroup(
+ name = "lib_rs_h_selected",
+ srcs = select({
+ ":debug_mode": [":src/lib.rs_debug.h"],
+ ":fastbuild_mode": [":src/lib.rs_debug.h"],
+ ":release_mode": [":src/lib.rs_release.h"],
+ }),
+)
+
+genrule(
+ name = "lib_rs_h_unified",
+ srcs = [":lib_rs_h_selected"],
+ outs = ["src/lib.rs.h"],
+ cmd = "cp $(location :lib_rs_h_selected) $(location src/lib.rs.h)",
+ message = "Unifying lib.rs.h for C++ includes",
+)
+
+filegroup(
+ name = "rust_bridge_cc_selected",
+ srcs = select({
+ ":debug_mode": [":rust_bridge_cc_debug.cc"],
+ ":fastbuild_mode": [":rust_bridge_cc_debug.cc"],
+ ":release_mode": [":rust_bridge_cc_release.cc"],
+ }),
+)
+
+genrule(
+ name = "rust_bridge_cc_unified",
+ srcs = [":rust_bridge_cc_selected"],
+ outs = ["rust_bridge_cc.cc"],
+ cmd = "cp $(location :rust_bridge_cc_selected) $(location
rust_bridge_cc.cc)",
+ message = "Unifying rust_bridge_cc.cc for C++ compilation",
+)
+
+filegroup(
+ name = "rust_bridge_h_selected",
+ srcs = select({
+ ":debug_mode": [":rust_bridge_h_debug.h"],
+ ":fastbuild_mode": [":rust_bridge_h_debug.h"],
+ ":release_mode": [":rust_bridge_h_release.h"],
+ }),
+)
+
+genrule(
+ name = "rust_bridge_h_unified",
+ srcs = [":rust_bridge_h_selected"],
+ outs = ["rust_bridge_h.h"],
+ cmd = "cp $(location :rust_bridge_h_selected) $(location rust_bridge_h.h)",
+ message = "Unifying rust_bridge_h.h for C++ includes",
+)
+
+filegroup(
+ name = "cxx_h_selected",
+ srcs = select({
+ ":debug_mode": [":cxxbridge/rust/cxx_debug.h"],
+ ":fastbuild_mode": [":cxxbridge/rust/cxx_debug.h"],
+ ":release_mode": [":cxxbridge/rust/cxx_release.h"],
+ }),
+)
+
+genrule(
+ name = "cxx_h_unified",
+ srcs = [":cxx_h_selected"],
+ outs = ["cxxbridge/rust/cxx.h"],
+ cmd = "mkdir -p $$(dirname $(location cxxbridge/rust/cxx.h)) && cp
$(location :cxx_h_selected) $(location cxxbridge/rust/cxx.h)",
+ message = "Unifying cxx.h for C++ includes",
+)
+
+cc_import(
+ name = "rust_lib",
+ static_library = select({
+ ":debug_mode": ":rust_lib_debug.a",
+ ":fastbuild_mode": ":rust_lib_debug.a",
+ ":release_mode": ":rust_lib_release.a",
+ }),
+ alwayslink = True,
+)
+
+cc_library(
+ name = "fluss_cpp",
+ srcs = [
+ "src/admin.cpp",
+ "src/connection.cpp",
+ "src/table.cpp",
+ ":rust_bridge_cc_unified",
+ ],
+ hdrs = [
+ "include/fluss.hpp",
+ ],
+ textual_hdrs = [
+ "src/ffi_converter.hpp",
+ ":rust_bridge_h_unified",
+ ":lib_rs_h_unified",
+ ":cxx_h_unified",
+ ],
+ strip_include_prefix = "include",
+ copts = [
+ "-std=c++17",
+ ] + select({
+ ":debug_mode": [
+ "-g3",
+ "-O0",
+ "-ggdb",
+ "-fno-omit-frame-pointer",
+ "-DDEBUG",
+ ],
+ ":fastbuild_mode": [
+ "-g",
+ "-O0",
+ ],
+ ":release_mode": [
+ "-O2",
+ "-DNDEBUG",
+ ],
+ }),
+ includes = [
+ "src",
+ "cxxbridge",
+ ],
+ linkopts = [
+ "-ldl",
+ "-lpthread",
+ ] + select({
+ ":debug_mode": ["-g"],
+ ":fastbuild_mode": ["-g"],
+ ":release_mode": [],
+ }) + select({
+ "@platforms//os:macos": [
+ "-framework", "CoreFoundation",
+ "-framework", "Security",
+ ],
+ "//conditions:default": [],
+ }),
+ deps = [
+ ":rust_lib",
+ ],
+ visibility = ["//visibility:public"],
+)
+
+cc_binary(
+ name = "fluss_cpp_example",
+ srcs = [
+ "examples/example.cpp",
+ ],
+ deps = [":fluss_cpp"],
+ copts = [
+ "-std=c++17",
+ ] + select({
+ ":debug_mode": [
+ "-g3",
+ "-O0",
+ "-ggdb",
+ "-fno-omit-frame-pointer",
+ "-DDEBUG",
+ ],
+ ":fastbuild_mode": [
+ "-g",
+ "-O0",
+ ],
+ ":release_mode": [
+ "-O2",
+ "-DNDEBUG",
+ ],
+ }),
+ linkopts = select({
+ ":debug_mode": ["-g"],
+ ":fastbuild_mode": ["-g"],
+ ":release_mode": [],
+ }),
+ visibility = ["//visibility:public"],
+)
+
diff --git a/bindings/cpp/MODULE.bazel b/bindings/cpp/MODULE.bazel
new file mode 100644
index 0000000..f75d3e6
--- /dev/null
+++ b/bindings/cpp/MODULE.bazel
@@ -0,0 +1,23 @@
+# 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.
+
+module(
+ name = "fluss_cpp",
+)
+
+bazel_dep(name = "rules_cc", version = "0.0.17")
+bazel_dep(name = "platforms", version = "0.0.10")
diff --git a/bindings/cpp/ci.sh b/bindings/cpp/ci.sh
new file mode 100755
index 0000000..b5eb967
--- /dev/null
+++ b/bindings/cpp/ci.sh
@@ -0,0 +1,100 @@
+#!/bin/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.
+
+set -xe
+
+DIR="$(cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd)"
+
+# Set Bazel output base to bazel-build directory
+# This ensures all Bazel outputs are in bazel-build/.bazel-output-base
+BAZEL_OUTPUT_BASE="$DIR/bazel-build/.bazel-output-base"
+
+# Create output base directory if it doesn't exist
+mkdir -p "$BAZEL_OUTPUT_BASE"
+
+# Wrapper function to run bazel with --output_base
+bazel() {
+ command bazel --output_base="$BAZEL_OUTPUT_BASE" "$@"
+}
+
+compile() {
+ bazel build //:fluss_cpp
+}
+
+build_example() {
+ bazel build //:fluss_cpp_example
+}
+
+run_example() {
+ build_example
+ bazel run //:fluss_cpp_example
+}
+
+clean() {
+ bazel clean
+ # Remove bazel-* symlinks (Bazel automatically creates these)
+ rm -f "$DIR"/bazel-*
+ # Also remove the bazel-build directory if it exists
+ if [ -d "$DIR/bazel-build" ]; then
+ rm -rf "$DIR/bazel-build"
+ fi
+ echo "Cleaned all Bazel outputs and symlinks"
+}
+
+show_outputs() {
+ echo "=== Library outputs ==="
+ bazel cquery //:fluss_cpp --output=files 2>/dev/null || echo "Run 'bazel
build //:fluss_cpp' first"
+ echo ""
+ echo "=== Example binary outputs ==="
+ bazel cquery //:fluss_cpp_example --output=files 2>/dev/null || echo "Run
'bazel build //:fluss_cpp_example' first"
+ echo ""
+ echo "=== To run the example ==="
+ echo " bazel run //:fluss_cpp_example"
+ echo ""
+ echo "=== To find outputs manually ==="
+ echo " bazel info bazel-bin"
+}
+
+case $1 in
+ compile )
+ compile
+ ;;
+ example )
+ build_example
+ ;;
+ run )
+ run_example
+ ;;
+ outputs )
+ show_outputs
+ ;;
+ clean )
+ clean
+ ;;
+ * )
+ echo "Usage: $0 {compile|example|run|outputs|clean}"
+ echo ""
+ echo "Commands:"
+ echo " compile - Build the fluss_cpp library"
+ echo " example - Build the example binary"
+ echo " run - Build and run the example binary"
+ echo " outputs - Show the location of build outputs"
+ echo " clean - Clean all Bazel outputs"
+ exit 1
+ ;;
+esac