| #!/usr/bin/env 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. |
| |
| # This script downloads and installs Maven Daemon (mvnd) if it's not already installed. |
| # mvnd keeps a persistent JVM that preserves Zinc's JIT-optimized code and |
| # classloader caches across builds, significantly speeding up incremental compilation. |
| # Usage: build/mvnd <maven-args> |
| # |
| |
| # Determine the current working directory |
| GLUTEN_HOME="$(cd "$(dirname "$0")"/.. && pwd)" || exit 1 |
| DOWNLOAD_DIR="${GLUTEN_HOME}/build" |
| MVND_DOWNLOAD_DIR="${DOWNLOAD_DIR}/.mvnd" |
| |
| # mvnd version to download if not found on system |
| MVND_VERSION="1.0.3" |
| |
| # Global variable for mvnd binary path |
| MVND_BIN="" |
| |
| # Detect OS and architecture for mvnd download |
| detect_platform() { |
| local os arch |
| os="$(uname -s)" |
| arch="$(uname -m)" |
| |
| case "$os" in |
| Linux) os="linux" ;; |
| Darwin) os="darwin" ;; |
| *) |
| echo "ERROR: Unsupported OS: $os. mvnd binaries are available for Linux and macOS." >&2 |
| exit 1 |
| ;; |
| esac |
| |
| case "$arch" in |
| x86_64|amd64) arch="amd64" ;; |
| aarch64|arm64) arch="aarch64" ;; |
| *) |
| echo "ERROR: Unsupported architecture: $arch. mvnd binaries are available for amd64 and aarch64." >&2 |
| exit 1 |
| ;; |
| esac |
| |
| echo "${os}-${arch}" |
| } |
| |
| install_mvnd() { |
| # Check for system mvnd first |
| local SYSTEM_MVND |
| SYSTEM_MVND="$(command -v mvnd)" |
| |
| if [ -n "$SYSTEM_MVND" ]; then |
| local MVND_DETECTED_VERSION |
| MVND_DETECTED_VERSION="$(mvnd --version 2>/dev/null | grep -i 'mvnd' | head -1 | awk '{print $NF}')" |
| echo "Using system mvnd: $SYSTEM_MVND (version $MVND_DETECTED_VERSION)" >&2 |
| MVND_BIN="$SYSTEM_MVND" |
| return 0 |
| fi |
| |
| # Detect platform |
| local PLATFORM |
| PLATFORM="$(detect_platform)" |
| |
| local MVND_DIR_NAME="maven-mvnd-${MVND_VERSION}-${PLATFORM}" |
| local MVND_LOCAL_BIN="${MVND_DOWNLOAD_DIR}/${MVND_DIR_NAME}/bin/mvnd" |
| |
| if [ ! -f "${MVND_LOCAL_BIN}" ]; then |
| echo "mvnd ${MVND_VERSION} not found locally. Downloading..." >&2 |
| |
| # Create download directory |
| mkdir -p "${MVND_DOWNLOAD_DIR}" |
| |
| local MVND_TAR="${MVND_DOWNLOAD_DIR}/${MVND_DIR_NAME}.tar.gz" |
| |
| if [ ! -f "${MVND_TAR}" ]; then |
| # Download from Apache |
| local DOWNLOAD_URL="https://downloads.apache.org/maven/mvnd/${MVND_VERSION}/${MVND_DIR_NAME}.tar.gz" |
| |
| echo "Downloading mvnd ${MVND_VERSION} for ${PLATFORM}..." >&2 |
| echo "URL: ${DOWNLOAD_URL}" >&2 |
| |
| if command -v curl > /dev/null 2>&1; then |
| curl -f -L --retry 3 --retry-delay 3 \ |
| --connect-timeout 30 --max-time 600 \ |
| -o "${MVND_TAR}" "${DOWNLOAD_URL}" || { |
| echo "ERROR: Failed to download mvnd from ${DOWNLOAD_URL}" >&2 |
| rm -f "${MVND_TAR}" |
| exit 1 |
| } |
| elif command -v wget > /dev/null 2>&1; then |
| wget --tries=3 --waitretry=3 \ |
| --connect-timeout=30 --read-timeout=600 \ |
| -O "${MVND_TAR}" "${DOWNLOAD_URL}" || { |
| echo "ERROR: Failed to download mvnd from ${DOWNLOAD_URL}" >&2 |
| rm -f "${MVND_TAR}" |
| exit 1 |
| } |
| else |
| echo "ERROR: Neither curl nor wget found. Please install one of them or install mvnd manually." >&2 |
| exit 1 |
| fi |
| |
| echo "Download completed successfully" >&2 |
| fi |
| |
| # Extract mvnd |
| echo "Extracting mvnd to ${MVND_DOWNLOAD_DIR}..." >&2 |
| if ! tar -xzf "${MVND_TAR}" -C "${MVND_DOWNLOAD_DIR}"; then |
| echo "ERROR: Failed to extract mvnd" >&2 |
| rm -f "${MVND_TAR}" |
| exit 1 |
| fi |
| |
| # Clean up tar file |
| rm -f "${MVND_TAR}" |
| |
| # Configure mvnd daemon JVM settings for Scala compilation |
| # ReservedCodeCacheSize=2g: Scala compiler generates enormous JIT code; |
| # default 240M fills up, causing ~10x slowdown in interpreted mode. |
| local MVND_PROPS="${MVND_DOWNLOAD_DIR}/${MVND_DIR_NAME}/conf/mvnd.properties" |
| if [ -f "${MVND_PROPS}" ]; then |
| echo "" >> "${MVND_PROPS}" |
| echo "# Gluten: tuned for Scala compilation workloads" >> "${MVND_PROPS}" |
| echo "mvnd.maxHeapSize = 30G" >> "${MVND_PROPS}" |
| echo "mvnd.threadStackSize = 128M" >> "${MVND_PROPS}" |
| echo "mvnd.jvmArgs = -XX:ReservedCodeCacheSize=2g" >> "${MVND_PROPS}" |
| echo "Configured mvnd daemon JVM settings in ${MVND_PROPS}" >&2 |
| fi |
| |
| echo "mvnd ${MVND_VERSION} installed successfully to ${MVND_DOWNLOAD_DIR}/${MVND_DIR_NAME}" >&2 |
| else |
| echo "Using downloaded mvnd: ${MVND_LOCAL_BIN} (version ${MVND_VERSION})" >&2 |
| fi |
| |
| # Set global variable |
| MVND_BIN="${MVND_LOCAL_BIN}" |
| } |
| |
| # Install mvnd if needed |
| install_mvnd |
| |
| # Verify mvnd binary is set |
| if [ -z "${MVND_BIN}" ]; then |
| echo "ERROR: mvnd binary not found. Please install mvnd or check your installation." >&2 |
| exit 1 |
| fi |
| |
| # Verify mvnd binary exists |
| if [ ! -f "${MVND_BIN}" ]; then |
| echo "ERROR: mvnd binary does not exist: ${MVND_BIN}" >&2 |
| exit 1 |
| fi |
| |
| _COMPILE_JVM_OPTS="-Xss128m -Xmx4g -XX:ReservedCodeCacheSize=2g" |
| # Set any `mvn` options if not already present |
| export MAVEN_OPTS=${MAVEN_OPTS:-"$_COMPILE_JVM_OPTS"} |
| |
| echo "MAVEN_OPTS: ${MAVEN_OPTS}" >&2 |
| |
| "${MVND_BIN}" "$@" |
| |
| MVND_RETCODE=$? |
| |
| exit $MVND_RETCODE |