Fluss C++ Bazel Usage Guide (System / Build Modes)

This guide is for:

  • C++ application teams consuming Fluss C++ bindings via Bazel
  • Maintainers evolving the Bazel integration

For the CMake flow with the same system / build dependency modes, see docs/cpp-cmake-usage.md.

Current simplification scope:

  • Keep only two dependency modes in the mainline guidance:
    • system
    • build
  • Defer strict internal-registry-only module flow from the mainline path

Scope

  • Dependency model: root module mode
  • Consumer dependency target: @fluss-cpp//bindings/cpp:fluss_cpp
  • Root MODULE.bazel is required for root module mode.
  • Build systems covered by this document: Bazel
  • Dependency modes covered by this document: system/build

Version baseline references currently used by examples:

  • protobuf/protoc: 3.25.5
  • arrow-cpp: 19.0.1

Common Consumer BUILD.bazel

Both modes use the same dependency target:

load("@rules_cc//cc:defs.bzl", "cc_binary")

cc_binary(
    name = "fluss_reader",
    srcs = ["reader.cc"],
    deps = ["@fluss-cpp//bindings/cpp:fluss_cpp"],
)

Mode 1: system (Recommended in preinstalled environments)

Use this mode when your environment already provides:

  • protoc
  • Arrow C++ (headers + shared libraries)

Consumer MODULE.bazel (pattern)

module(name = "my_cpp_app")

bazel_dep(name = "rules_cc", version = "0.2.14")
bazel_dep(name = "fluss-cpp", version = "<released-version>")

fluss_cpp = use_extension("@fluss-cpp//bindings/cpp/bazel/cpp:deps.bzl", "cpp_sdk")
fluss_cpp.config(
    mode = "system",
    protobuf_version = "3.25.5",
    arrow_cpp_version = "19.0.1",
    # Adjust Arrow paths for your environment
    system_arrow_prefix = "/usr",
    system_arrow_include_dir = "include",
    system_arrow_shared_library = "lib/x86_64-linux-gnu/libarrow.so",
    system_arrow_runtime_glob = "lib/x86_64-linux-gnu/libarrow.so*",
)
use_repo(fluss_cpp, "apache_arrow_cpp")

Build and run (consumer workspace pattern)

Run from your consumer workspace root (the directory containing MODULE.bazel and your top-level BUILD.bazel).

PROTOC_BIN="$(command -v protoc)"
CARGO_BIN="$(command -v cargo)"
bazel run \
  --action_env=PROTOC="$PROTOC_BIN" \
  --action_env=CARGO="$CARGO_BIN" \
  --action_env=PATH="$(dirname "$CARGO_BIN"):$PATH" \
  //:fluss_reader

Runnable example

  • bindings/cpp/examples/bazel-consumer/system
cd bindings/cpp/examples/bazel-consumer/system
PROTOC_BIN="$(command -v protoc)"
CARGO_BIN="$(command -v cargo)"
bazel run \
  --action_env=PROTOC="$PROTOC_BIN" \
  --action_env=CARGO="$CARGO_BIN" \
  --action_env=PATH="$(dirname "$CARGO_BIN"):$PATH" \
  //:consumer_system

Mode 2: build (No internal registry / no preinstalled Arrow)

Use this mode when Arrow C++ is not preinstalled and you want Bazel to provision it from source.

Consumer MODULE.bazel (pattern)

module(name = "my_cpp_app")

bazel_dep(name = "rules_cc", version = "0.2.14")
bazel_dep(name = "fluss-cpp", version = "<released-version>")

fluss_cpp = use_extension("@fluss-cpp//bindings/cpp/bazel/cpp:deps.bzl", "cpp_sdk")
fluss_cpp.config(
    mode = "build",
    protobuf_version = "3.25.5",
    arrow_cpp_version = "19.0.1",
)
use_repo(fluss_cpp, "apache_arrow_cpp")

Notes:

  • build mode in the core Bazel integration still uses PROTOC (env / PATH).
  • To auto-download a pinned protoc for build mode, use bindings/cpp/scripts/ensure_protoc.sh and pass the result via --action_env=PROTOC=....
  • ensure_protoc.sh auto-detects host OS/arch (linux/osx, x86_64/aarch_64).
  • Some environments may require ep_cmake_ar/ranlib/nm overrides.

Build and run (consumer workspace pattern, with auto-downloaded protoc)

Run from the fluss-rust repository root, or adjust the script path if you copied it elsewhere.

PROTOC_BIN="$(bash bindings/cpp/scripts/ensure_protoc.sh --print-path)"
bazel run --action_env=PROTOC="$PROTOC_BIN" //:fluss_reader

If cargo is not on Bazel action PATH, also pass:

CARGO_BIN="$(command -v cargo)"
bazel run \
  --action_env=PROTOC="$PROTOC_BIN" \
  --action_env=CARGO="$CARGO_BIN" \
  --action_env=PATH="$(dirname "$CARGO_BIN"):$PATH" \
  //:fluss_reader

Runnable example

  • bindings/cpp/examples/bazel-consumer/build
cd bindings/cpp/examples/bazel-consumer/build
PROTOC_BIN="$(bash ../../../scripts/ensure_protoc.sh --print-path)"
CARGO_BIN="$(command -v cargo)"
bazel run \
  --action_env=PROTOC="$PROTOC_BIN" \
  --action_env=CARGO="$CARGO_BIN" \
  --action_env=PATH="$(dirname "$CARGO_BIN"):$PATH" \
  //:consumer_build

Local Development Override (Optional)

For repository-local validation only:

local_path_override(
    module_name = "fluss-cpp",
    path = "/path/to/fluss-rust",
)

Do not keep local overrides in long-lived branches.

Repository-local examples in this repo use version = "0.1.0" together with local_path_override(...) for local validation before publishing to the Bazel registry.

Repository-local Validation (Direct Commands)

These commands validate the repository examples directly. If your environment requires a proxy for Bazel external downloads, export it before running (replace the placeholder URL with your actual proxy):

export BAZEL_PROXY_URL="http://proxy.example.com:3128"
export http_proxy="$BAZEL_PROXY_URL"
export https_proxy="$BAZEL_PROXY_URL"
export HTTP_PROXY="$http_proxy"
export HTTPS_PROXY="$https_proxy"
unset all_proxy ALL_PROXY

Validate build example

cd bindings/cpp/examples/bazel-consumer/build
PROTOC_BIN="$(bash ../../../scripts/ensure_protoc.sh --print-path)"
CARGO_BIN="$(command -v cargo)"
bazel --ignore_all_rc_files run \
  --registry=https://bcr.bazel.build \
  --lockfile_mode=off \
  --repo_env=http_proxy="${http_proxy:-}" \
  --repo_env=https_proxy="${https_proxy:-}" \
  --repo_env=HTTP_PROXY="${HTTP_PROXY:-}" \
  --repo_env=HTTPS_PROXY="${HTTPS_PROXY:-}" \
  --action_env=http_proxy="${http_proxy:-}" \
  --action_env=https_proxy="${https_proxy:-}" \
  --action_env=HTTP_PROXY="${HTTP_PROXY:-}" \
  --action_env=HTTPS_PROXY="${HTTPS_PROXY:-}" \
  --action_env=all_proxy= \
  --action_env=ALL_PROXY= \
  --action_env=PROTOC="$PROTOC_BIN" \
  --action_env=CARGO="$CARGO_BIN" \
  --action_env=PATH="$(dirname "$CARGO_BIN"):$PATH" \
  --strategy=CcCmakeMakeRule=local \
  --strategy=BootstrapGNUMake=local \
  --strategy=BootstrapPkgConfig=local \
  //:consumer_build

Validate system example (using a local Arrow prefix)

The system example defaults to /usr. If your Arrow prefix is elsewhere (for example a locally built prefix), copy the example to a temp directory and patch MODULE.bazel before running:

tmp_dir="$(mktemp -d /tmp/fluss-bazel-system-doc.XXXXXX)"
FLUSS_RUST_ROOT="$(pwd)"
cp -a bindings/cpp/examples/bazel-consumer/system/. "$tmp_dir/"
sed -i \
  -e "s|path = \"../../../../../\"|path = \"$FLUSS_RUST_ROOT\"|" \
  -e 's|system_arrow_prefix = "/usr"|system_arrow_prefix = "/tmp/fluss-system-arrow-19.0.1"|' \
  -e 's|system_arrow_shared_library = "lib/x86_64-linux-gnu/libarrow.so"|system_arrow_shared_library = "lib/libarrow.so"|' \
  -e 's|system_arrow_runtime_glob = "lib/x86_64-linux-gnu/libarrow.so\\*"|system_arrow_runtime_glob = "lib/libarrow.so*"|' \
  "$tmp_dir/MODULE.bazel"
cd "$tmp_dir"
PROTOC_BIN="$(command -v protoc)"
CARGO_BIN="$(command -v cargo)"
bazel --ignore_all_rc_files run \
  --registry=https://bcr.bazel.build \
  --lockfile_mode=off \
  --repo_env=http_proxy="${http_proxy:-}" \
  --repo_env=https_proxy="${https_proxy:-}" \
  --repo_env=HTTP_PROXY="${HTTP_PROXY:-}" \
  --repo_env=HTTPS_PROXY="${HTTPS_PROXY:-}" \
  --action_env=http_proxy="${http_proxy:-}" \
  --action_env=https_proxy="${https_proxy:-}" \
  --action_env=HTTP_PROXY="${HTTP_PROXY:-}" \
  --action_env=HTTPS_PROXY="${HTTPS_PROXY:-}" \
  --action_env=all_proxy= \
  --action_env=ALL_PROXY= \
  --action_env=PROTOC="$PROTOC_BIN" \
  --action_env=CARGO="$CARGO_BIN" \
  --action_env=PATH="$(dirname "$CARGO_BIN"):$PATH" \
  //:consumer_system

On macOS (BSD sed), replace sed -i with sed -i '' in the patch step above.

Upgrade Procedure

  1. Update bazel_dep(name = "fluss-cpp", version = "...")
  2. Update mode version settings if needed (protobuf_version, arrow_cpp_version)
  3. Run bazel mod tidy
  4. Commit MODULE.bazel and MODULE.bazel.lock
  5. Run build + tests
  6. Verify dependency graph:
bazel mod graph | rg "fluss-cpp@"

Examples and Non-Mainline References

Mainline examples:

  • bindings/cpp/examples/bazel-consumer/build
  • bindings/cpp/examples/bazel-consumer/system