blob: 4d4ab131677dcd906f383043653fbaf44a001f98 [file]
#!/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.
#
# Build a multi-platform datafusion-java JAR bundling native libs for
# linux/amd64, linux/aarch64, darwin/x86_64, and darwin/aarch64. The
# resulting JAR is installed into a temporary local Maven repository
# whose path is printed at the end. This script must run on a macOS host.
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null && pwd)"
PROJECT_HOME="$(cd "${SCRIPT_DIR}/../.." >/dev/null && pwd)"
REPO="https://github.com/apache/datafusion-java.git"
BRANCH="main"
IMGTAG="latest"
function usage {
cat <<EOF
Usage: $(basename "$0") [-r repo] [-b branch] [-t tag]
-r repo git repo URL to clone inside the linux build containers
(default: ${REPO})
-b branch git branch or tag to check out inside the containers
(default: ${BRANCH})
-t tag docker image tag for the two builder images
(default: ${IMGTAG})
Produces a multi-platform datafusion-java JAR in a temporary local Maven
repo; the repo path is printed at the end. The host must be macOS.
EOF
exit 1
}
while getopts "r:b:t:h" opt; do
case "$opt" in
r) REPO="$OPTARG" ;;
b) BRANCH="$OPTARG" ;;
t) IMGTAG="$OPTARG" ;;
h|*) usage ;;
esac
done
if [ "$(uname -s)" != "Darwin" ]; then
echo "This script must run on a macOS host (got: $(uname -s))." >&2
exit 1
fi
JAVA_VERSION=$(java -version 2>&1 | awk -F '"' '/version/ {print $2}' | awk -F '.' '{print $1}')
if [ -z "$JAVA_VERSION" ] || [ "$JAVA_VERSION" -lt 17 ]; then
echo "Java 17+ is required. Found: $(java -version 2>&1 | head -n 1)" >&2
exit 1
fi
HOST_ARCH="$(uname -m)" # arm64 (Apple Silicon) or x86_64 (Intel)
case "$HOST_ARCH" in
arm64)
HOST_DARWIN_DIR="aarch64"
OTHER_DARWIN_TARGET="x86_64-apple-darwin"
OTHER_DARWIN_DIR="x86_64"
;;
x86_64)
HOST_DARWIN_DIR="x86_64"
OTHER_DARWIN_TARGET="aarch64-apple-darwin"
OTHER_DARWIN_DIR="aarch64"
;;
*)
echo "Unsupported macOS arch: $HOST_ARCH" >&2
exit 1
;;
esac
CONTAINER_AMD64="datafusion-java-amd64-builder-container"
CONTAINER_ARM64="datafusion-java-arm64-builder-container"
IMAGE_AMD64="datafusion-java-rm-amd64:${IMGTAG}"
IMAGE_ARM64="datafusion-java-rm-arm64:${IMGTAG}"
CLEANUP=1
cleanup() {
[ "$CLEANUP" != "0" ] || return 0
echo "Cleaning up build containers..."
docker rm -f "$CONTAINER_AMD64" "$CONTAINER_ARM64" >/dev/null 2>&1 || true
CLEANUP=0
}
trap cleanup SIGINT SIGTERM EXIT
echo "Cleaning leftover builder containers from any prior interrupted run"
docker rm -f "$CONTAINER_AMD64" "$CONTAINER_ARM64" >/dev/null 2>&1 || true
echo "Cleaning previous Java and native build output"
(cd "$PROJECT_HOME" && ./mvnw -q clean)
(cd "$PROJECT_HOME/native" && cargo clean)
echo "Building amd64 builder image"
docker build --no-cache \
--platform=linux/amd64 \
-t "$IMAGE_AMD64" \
"$SCRIPT_DIR/datafusion-java-rm"
echo "Building arm64 builder image"
docker build --no-cache \
--platform=linux/arm64 \
-t "$IMAGE_ARM64" \
"$SCRIPT_DIR/datafusion-java-rm"
echo "Building linux/amd64 native lib"
docker run --name "$CONTAINER_AMD64" \
--platform=linux/amd64 \
"$IMAGE_AMD64" "$REPO" "$BRANCH"
echo "Building linux/aarch64 native lib"
docker run --name "$CONTAINER_ARM64" \
--platform=linux/arm64 \
"$IMAGE_ARM64" "$REPO" "$BRANCH"
JVM_TARGET_DIR="$PROJECT_HOME/core/target/classes/org/apache/datafusion"
mkdir -p "$JVM_TARGET_DIR/linux/amd64"
docker cp \
"$CONTAINER_AMD64:/opt/datafusion-java-rm/datafusion-java/rust-target/release/libdatafusion_jni.so" \
"$JVM_TARGET_DIR/linux/amd64/"
mkdir -p "$JVM_TARGET_DIR/linux/aarch64"
docker cp \
"$CONTAINER_ARM64:/opt/datafusion-java-rm/datafusion-java/rust-target/release/libdatafusion_jni.so" \
"$JVM_TARGET_DIR/linux/aarch64/"
echo "Building macOS native libs on the host (host=$HOST_ARCH)"
rustup target add "$OTHER_DARWIN_TARGET"
# Cargo writes to the workspace `rust-target/` dir (set in .cargo/config.toml),
# not the per-crate `native/target/`, so build from the repo root.
(cd "$PROJECT_HOME" && cargo build --release -p datafusion-jni)
(cd "$PROJECT_HOME" && cargo build --release -p datafusion-jni --target "$OTHER_DARWIN_TARGET")
mkdir -p "$JVM_TARGET_DIR/darwin/$HOST_DARWIN_DIR"
cp "$PROJECT_HOME/rust-target/release/libdatafusion_jni.dylib" \
"$JVM_TARGET_DIR/darwin/$HOST_DARWIN_DIR/"
mkdir -p "$JVM_TARGET_DIR/darwin/$OTHER_DARWIN_DIR"
cp "$PROJECT_HOME/rust-target/$OTHER_DARWIN_TARGET/release/libdatafusion_jni.dylib" \
"$JVM_TARGET_DIR/darwin/$OTHER_DARWIN_DIR/"
echo "Installing JAR into local Maven repo"
LOCAL_REPO=$(mktemp -d /tmp/datafusion-java-staging-repo-XXXXXX)
(cd "$PROJECT_HOME" && ./mvnw \
"-Dmaven.repo.local=$LOCAL_REPO" \
"-Ddatafusion.native.profile=release" \
-DskipTests install)
echo ""
echo "===================================================================="
echo "Multi-platform JAR installed to local Maven repo: $LOCAL_REPO"
JAR_PATH=$(find "$LOCAL_REPO/org/apache/datafusion/datafusion-java" -name 'datafusion-java-*.jar' \
-not -name '*-sources.jar' -not -name '*-javadoc.jar' | head -n 1)
echo "JAR: $JAR_PATH"
echo "Bundled native libraries:"
unzip -l "$JAR_PATH" | grep -E 'libdatafusion_jni\.(so|dylib)$' || true
echo "===================================================================="