Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 22 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -154,12 +154,32 @@ if(USE_CUDA AND CMAKE_CUDA_COMPILER)
endif()

find_program(LLD_PROGRAM lld)
if(LLD_PROGRAM)
if(LLD_PROGRAM AND NOT APPLE)
message(STATUS "Using lld")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fuse-ld=lld")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fuse-ld=lld")
endif()

# On macOS, LLVM/MLIR's cmake config creates partial zstd IMPORTED targets
# (shared + static) but not the zstd::libzstd alias. Homebrew's zstd cmake
# config then fails when Arrow tries to re-find zstd because some targets
# already exist. Work around by telling Arrow that zstd is already found.
# Also fix the INTERFACE_INCLUDE_DIRECTORIES: LLVM's Findzstd.cmake sets it
# to /opt/homebrew/include (all of Homebrew), which pulls in wrong versions
# of headers (e.g. fmt 11.2 vs our thirdparty fmt 11.0). Narrow it to the
# zstd-specific include path.
if(APPLE AND TARGET zstd::libzstd_shared)
set(zstdAlt_FOUND TRUE)
find_path(_ZSTD_SPECIFIC_INCLUDE zstd.h PATHS /opt/homebrew/opt/zstd/include NO_DEFAULT_PATH)
if(_ZSTD_SPECIFIC_INCLUDE)
set_target_properties(zstd::libzstd_shared PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES "${_ZSTD_SPECIFIC_INCLUDE}")
if(TARGET zstd::libzstd_static)
set_target_properties(zstd::libzstd_static PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES "${_ZSTD_SPECIFIC_INCLUDE}")
endif()
endif()
endif()
find_package(Arrow REQUIRED)
find_package(Parquet REQUIRED)

Expand Down Expand Up @@ -205,7 +225,7 @@ if(USE_HDFS)
endif()

include_directories(${PROJECT_SOURCE_DIR} ${HDFS_LIB_LOCATION})
find_library(hdfs3 NAMES libhdfs3.so HINTS ${PROJECT_BINARY_DIR}/installed/lib REQUIRED)
find_library(hdfs3 NAMES hdfs3 HINTS ${PROJECT_BINARY_DIR}/installed/lib REQUIRED)
message(STATUS "HDFS_LIB_FOUND: ${HDFS_LIB_FOUND}")
if(DEFINED HDFS_LIB_FOUND)
add_definitions(-DUSE_HDFS)
Expand Down
162 changes: 129 additions & 33 deletions build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,32 @@
# Stop immediately if any command fails.
set -e

#******************************************************************************
# Platform detection and portable helpers
#******************************************************************************
IS_DARWIN=0
if [ "$(uname -s)" == "Darwin" ]; then
IS_DARWIN=1
fi

# Portable replacement for nproc (not available on macOS)
get_nproc() {
if [ "$IS_DARWIN" == "1" ]; then
sysctl -n hw.ncpu
else
nproc
fi
}

# Portable replacement for sed -i (different syntax on macOS)
sed_inplace() {
if [ "$IS_DARWIN" == "1" ]; then
sed -i '' "$@"
else
sed -i "$@"
fi
}

build_ts_begin=$(date +%s%N)

#******************************************************************************
Expand Down Expand Up @@ -454,6 +480,10 @@ BUILD_MPI="-DUSE_MPI=OFF"
BUILD_HDFS="-DUSE_HDFS=OFF"
BUILD_IO_URING="-DUSE_IO_URING=OFF"
BUILD_PAPI="-DUSE_PAPI=ON"
# Default PAPI to OFF on macOS (not well supported)
if [ "$IS_DARWIN" == "1" ]; then
BUILD_PAPI="-DUSE_PAPI=OFF"
fi
WITH_DEPS=1
WITH_SUBMODULE_UPDATE=1

Expand Down Expand Up @@ -572,12 +602,26 @@ fi
#******************************************************************************
# #8 Download and install third-party dependencies if requested (default is yes, omit with --no-deps))
#******************************************************************************
# On macOS, use Apple Clang for third-party dependency builds to avoid
# boringssl/GCC incompatibilities. DAPHNE itself uses GCC-15 (set below).

if [ $WITH_DEPS -gt 0 ]; then
# CMake 4.x removed compatibility with cmake_minimum_required < 3.5.
# Many third-party deps use older versions; this global setting allows them to configure.
export CMAKE_POLICY_VERSION_MINIMUM=3.5

# On macOS, use GCC-15 for all builds (deps + DAPHNE) for ABI compatibility.
# The boringssl patches below handle GCC-specific issues.
if [ "$IS_DARWIN" == "1" ]; then
export CC=gcc-15
export CXX=g++-15
fi

LLVM_ARCH=X86
# optimizes for multiple x86_64 architectures
PAPI_OBLAS_ARCH=NEHALEM
# Determine CPU architecture to compile for
if [ $(arch) == 'armv*' ] || [ $(arch) == 'aarch64' ]; then
if [ $(arch) == 'armv*' ] || [ $(arch) == 'aarch64' ] || [ $(arch) == 'arm64' ]; then
echo "Building for ARMv8 architecture"
LLVM_ARCH=AArch64
PAPI_OBLAS_ARCH=ARMV8
Expand Down Expand Up @@ -625,7 +669,7 @@ if [ $WITH_DEPS -gt 0 ]; then
--with-components="coretemp infiniband io lustre net powercap rapl sde stealtime" \


CFLAGS="-fPIC -DPIC" make -j"$(nproc)" DYNAMIC_ARCH=1 TARGET="$PAPI_OBLAS_ARCH"
CFLAGS="-fPIC -DPIC" make -j"$(get_nproc)" DYNAMIC_ARCH=1 TARGET="$PAPI_OBLAS_ARCH"
make install
cd - > /dev/null
dependency_install_success "papi_v${papiVersion}"
Expand All @@ -650,7 +694,7 @@ if [ $WITH_DEPS -gt 0 ]; then
if ! is_dependency_installed "hwloc_v${hwlocVersion}"; then
cd "$sourcePrefix/$hwlocDirName/"
./configure --prefix="$hwlocInstDirName"
make -j"$(nproc)" DYNAMIC_ARCH=1 TARGET="$PAPI_OBLAS_ARCH"
make -j"$(get_nproc)" DYNAMIC_ARCH=1 TARGET="$PAPI_OBLAS_ARCH"
make install
cd - > /dev/null
dependency_install_success "hwloc_v${hwlocVersion}"
Expand Down Expand Up @@ -691,7 +735,11 @@ if [ $WITH_DEPS -gt 0 ]; then
-d "$sourcePrefix/$antlrCppRuntimeDirName"
# Github disabled the unauthenticated git:// protocol, patch antlr4 to use https://
# until we upgrade to antlr4-4.9.3+
sed -i 's#git://github.com#https://github.com#' "$sourcePrefix/$antlrCppRuntimeDirName/runtime/CMakeLists.txt"
sed_inplace 's#git://github.com#https://github.com#' "$sourcePrefix/$antlrCppRuntimeDirName/runtime/CMakeLists.txt"

# CMake 4.x no longer supports setting deprecated policies to OLD. Remove them.
sed_inplace '/CMAKE_POLICY(SET CMP00[2-5][0-9] OLD)/d' \
"$sourcePrefix/$antlrCppRuntimeDirName/CMakeLists.txt"

daphne_msg "Build Antlr v${antlrVersion}"
cmake -S "$sourcePrefix/$antlrCppRuntimeDirName" -B "${buildPrefix}/${antlrCppRuntimeDirName}" \
Expand Down Expand Up @@ -753,7 +801,15 @@ if [ $WITH_DEPS -gt 0 ]; then
if ! is_dependency_installed "${dep_openBlas[@]}"; then
cd "$sourcePrefix/$openBlasDirName"
make clean
make -j"$(nproc)" DYNAMIC_ARCH=1 TARGET="$PAPI_OBLAS_ARCH"
# GCC 15+ treats -Wincompatible-pointer-types as error; OpenBLAS 0.3.23 triggers it
# macOS doesn't support DYNAMIC_ARCH (clang assembler lacks many -mtune targets)
if [ "$IS_DARWIN" == "1" ]; then
make -j"$(get_nproc)" TARGET="$PAPI_OBLAS_ARCH" \
CFLAGS="-Wno-error=incompatible-pointer-types" \
COMMON_OPT="-Wno-error=incompatible-pointer-types"
else
make -j"$(get_nproc)" DYNAMIC_ARCH=1 TARGET="$PAPI_OBLAS_ARCH"
fi
make PREFIX="$openBlasInstDirName" install
cd - >/dev/null
dependency_install_success "${dep_openBlas[@]}"
Expand Down Expand Up @@ -782,7 +838,7 @@ if [ $WITH_DEPS -gt 0 ]; then
# abseil (compiled separately to apply a patch)
#------------------------------------------------------------------------------
abslPath=$sourcePrefix/abseil-cpp
if [ $(arch) == 'armv64' ] || [ $(arch) == 'aarch64' ]; then
if [ $(arch) == 'armv64' ] || [ $(arch) == 'aarch64' ] || [ $(arch) == 'arm64' ]; then
abslVersion=20211102.0
fi
dep_absl=("absl_v${abslVersion}" "v1")
Expand All @@ -791,7 +847,7 @@ if [ $WITH_DEPS -gt 0 ]; then
daphne_msg "Get abseil version ${abslVersion}"
rm -rf "$abslPath"
git clone --depth 1 --branch "$abslVersion" https://github.com/abseil/abseil-cpp.git "$abslPath"
if [ $(arch) == 'armv*' ] || [ $(arch) == 'aarch64' ]; then
if [ $(arch) == 'armv*' ] || [ $(arch) == 'aarch64' ] || [ $(arch) == 'arm64' ]; then
daphne_msg "Applying 0002-absl-stdmax-params.patch"
patch -Np1 -i "${patchDir}/0002-absl-stdmax-params.patch" -d "$abslPath"
fi
Expand All @@ -809,26 +865,28 @@ if [ $WITH_DEPS -gt 0 ]; then
#------------------------------------------------------------------------------
# MPI (Default is MPI library is OpenMPI but cut can be any)
#------------------------------------------------------------------------------
MPIZipName=openmpi-$openMPIVersion.tar.gz
MPIInstDirName=$installPrefix
dep_mpi=("openmpi_v${openMPIVersion}" "v1")

if ! is_dependency_downloaded "${dep_mpi[@]}"; then
daphne_msg "Get openmpi version ${openMPIVersion}"
wget "https://download.open-mpi.org/release/open-mpi/v4.1/$MPIZipName" -qO "${cacheDir}/${MPIZipName}"
tar -xf "$cacheDir/$MPIZipName" --directory "$sourcePrefix"
dependency_download_success "${dep_mpi[@]}"
mkdir -p "$MPIInstDirName"
fi
if ! is_dependency_installed "${dep_mpi[@]}"; then
cd "$sourcePrefix/openmpi-$openMPIVersion"
./configure --prefix="$MPIInstDirName"
make -j"$(nproc)" all
make install
cd -
dependency_install_success "${dep_mpi[@]}"
else
daphne_msg "No need to build OpenMPI again"
if [ "$BUILD_MPI" == "-DUSE_MPI=ON" ]; then
MPIZipName=openmpi-$openMPIVersion.tar.gz
MPIInstDirName=$installPrefix
dep_mpi=("openmpi_v${openMPIVersion}" "v1")

if ! is_dependency_downloaded "${dep_mpi[@]}"; then
daphne_msg "Get openmpi version ${openMPIVersion}"
wget "https://download.open-mpi.org/release/open-mpi/v4.1/$MPIZipName" -qO "${cacheDir}/${MPIZipName}"
tar -xf "$cacheDir/$MPIZipName" --directory "$sourcePrefix"
dependency_download_success "${dep_mpi[@]}"
mkdir -p "$MPIInstDirName"
fi
if ! is_dependency_installed "${dep_mpi[@]}"; then
cd "$sourcePrefix/openmpi-$openMPIVersion"
./configure --prefix="$MPIInstDirName"
make -j"$(get_nproc)" all
make install
cd -
dependency_install_success "${dep_mpi[@]}"
else
daphne_msg "No need to build OpenMPI again"
fi
fi
#------------------------------------------------------------------------------
# gRPC
Expand All @@ -855,8 +913,21 @@ if [ $WITH_DEPS -gt 0 ]; then
dependency_download_success "${dep_grpc[@]}"
fi
if ! is_dependency_installed "${dep_grpc[@]}"; then
# Patch boringssl for GCC compatibility on macOS:
# 1) __builtin_available() is a Clang-only builtin; on macOS 10.12+
# getentropy() is always available so the check can be removed.
# 2) -stdlib=libc++ is a Clang-only flag; GCC uses libstdc++ natively.
if [ "$IS_DARWIN" == "1" ]; then
sed_inplace 's/if (__builtin_available(macos 10\.12, \*))/if (1)/g' \
"$sourcePrefix/$grpcDirName/third_party/boringssl-with-bazel/src/crypto/fipsmodule/rand/urandom.c"
sed_inplace '/stdlib=libc++/d' \
"$sourcePrefix/$grpcDirName/third_party/boringssl-with-bazel/CMakeLists.txt"
sed_inplace '/stdlib=libc++/d' \
"$sourcePrefix/$grpcDirName/third_party/boringssl-with-bazel/src/CMakeLists.txt"
fi
cmake -G Ninja -S "$sourcePrefix/$grpcDirName" -B "$buildPrefix/$grpcDirName" \
-DCMAKE_INSTALL_PREFIX="$grpcInstDir" \
-DCMAKE_PREFIX_PATH="$installPrefix" \
-DCMAKE_BUILD_TYPE=Release \
-DgRPC_INSTALL=ON \
-DgRPC_BUILD_TESTS=OFF \
Expand Down Expand Up @@ -886,15 +957,23 @@ if [ $WITH_DEPS -gt 0 ]; then
fi

# this works around a build error that occurs on Ubuntu with Boost installed
if [ $(lsb_release -is) == "Ubuntu" ]; then
if [ $(dpkg -l | grep libboost | wc -l) == "" ]; then
if [ "$IS_DARWIN" != "1" ] && [ "$(lsb_release -is 2>/dev/null)" == "Ubuntu" ]; then
if [ "$(dpkg -l | grep libboost | wc -l)" == "" ]; then
daphne_msg "Setting BOOST_ROOT=/usr on Ubuntu Linux with libboost installed"
sleep 5
export BOOST_ROOT=/usr
fi
fi

if ! is_dependency_installed "${dep_arrow[@]}"; then
# GCC-15 is stricter about missing includes; Arrow 13 uses std::find
# without #include <algorithm> in filesystem/util_internal.cc.
if [ "$IS_DARWIN" == "1" ]; then
arrow_file="${sourcePrefix}/${arrowDirName}/cpp/src/arrow/filesystem/util_internal.cc"
if ! grep -q '#include <algorithm>' "$arrow_file" 2>/dev/null; then
sed_inplace '1s/^/#include <algorithm>\n/' "$arrow_file"
fi
fi
cmake -G Ninja -S "${sourcePrefix}/${arrowDirName}/cpp" -B "${buildPrefix}/${arrowDirName}" \
-DCMAKE_INSTALL_PREFIX="${installPrefix}" -DARROW_CSV=ON -DARROW_FILESYSTEM=ON -DARROW_PARQUET=ON \
-DARROW_WITH_BROTLI=ON -DARROW_WITH_BZ2=ON -DARROW_WITH_LZ4=ON -DARROW_WITH_SNAPPY=ON -DARROW_WITH_ZLIB=ON \
Expand Down Expand Up @@ -940,7 +1019,8 @@ if [ $WITH_DEPS -gt 0 ]; then
fi
if ! is_dependency_installed "spdlog_v${spdlogVersion}"; then
cmake -G Ninja -S "${sourcePrefix}/${spdlogDirName}" -B "${buildPrefix}/${spdlogDirName}" \
-DSPDLOG_FMT_EXTERNAL=ON -DCMAKE_INSTALL_PREFIX="${installPrefix}" -DCMAKE_POSITION_INDEPENDENT_CODE=ON
-DSPDLOG_FMT_EXTERNAL=ON -DCMAKE_INSTALL_PREFIX="${installPrefix}" -DCMAKE_PREFIX_PATH="${installPrefix}" \
-DCMAKE_POSITION_INDEPENDENT_CODE=ON
cmake --build "${buildPrefix}/${spdlogDirName}" --target install/strip
dependency_install_success "spdlog_v${spdlogVersion}"
else
Expand Down Expand Up @@ -1036,13 +1116,23 @@ if [ $WITH_DEPS -gt 0 ]; then
daphne_msg "Building LLVM/MLIR from ${llvmCommit}"
cd "${thirdpartyPath}/${llvmName}"
echo "Need to build MLIR/LLVM."
# On macOS, use GCC-15 for LLVM/MLIR build to ensure ABI compatibility
# with the rest of the project (all using libstdc++). LLD is disabled
# because it is a Clang/LLVM-specific linker.
if [ "$IS_DARWIN" == "1" ]; then
LLVM_COMPILER_FLAGS="-DCMAKE_C_COMPILER=gcc-15 -DCMAKE_CXX_COMPILER=g++-15"
LLVM_LLD_FLAG=""
else
LLVM_COMPILER_FLAGS="-DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++"
LLVM_LLD_FLAG="-DLLVM_ENABLE_LLD=ON"
fi
cmake -G Ninja -S llvm -B "$buildPrefix/$llvmName" \
-DLLVM_ENABLE_PROJECTS=mlir \
-DLLVM_BUILD_EXAMPLES=OFF \
-DLLVM_TARGETS_TO_BUILD="$LLVM_ARCH" \
-DCMAKE_BUILD_TYPE=Release \
-DLLVM_ENABLE_ASSERTIONS=ON \
-DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DLLVM_ENABLE_LLD=ON \
$LLVM_COMPILER_FLAGS $LLVM_LLD_FLAG \
-DLLVM_ENABLE_RTTI=ON \
-DCMAKE_INSTALL_PREFIX="$installPrefix"
cmake --build "$buildPrefix/$llvmName" --target check-mlir
Expand Down Expand Up @@ -1074,7 +1164,7 @@ if [ $WITH_DEPS -gt 0 ]; then
if ! is_dependency_installed "liburing_v${liburingVersion}"; then
cd "$sourcePrefix/$liburingDirName"
./configure --cc="$liburing_cc" --cxx="$liburing_cxx" --prefix="$liburingInstDirName"
make -j"$(nproc)"
make -j"$(get_nproc)"
cp ./src/liburing.a "$installPrefix/lib/"
cp -r ./src/include/* "$installPrefix/include"
cd - > /dev/null
Expand Down Expand Up @@ -1107,9 +1197,15 @@ fi

daphne_msg "Build Daphne"

DAPHNE_CMAKE_EXTRA=""
if [ "$IS_DARWIN" == "1" ]; then
# GCC-15 is already exported; explicitly pass to cmake as well.
DAPHNE_CMAKE_EXTRA="-DCMAKE_C_COMPILER=gcc-15 -DCMAKE_CXX_COMPILER=g++-15"
fi

cmake -S "$projectRoot" -B "$daphneBuildDir" -G Ninja -DANTLR_VERSION="$antlrVersion" \
-DCMAKE_PREFIX_PATH="$installPrefix" \
$BUILD_CUDA $BUILD_FPGAOPENCL $BUILD_DEBUG $BUILD_MPI $BUILD_HDFS $BUILD_PAPI
$BUILD_CUDA $BUILD_FPGAOPENCL $BUILD_DEBUG $BUILD_MPI $BUILD_HDFS $BUILD_PAPI $DAPHNE_CMAKE_EXTRA

cmake --build "$daphneBuildDir" --target "$target"

Expand Down
31 changes: 31 additions & 0 deletions doc/development/BuildingDaphne.md
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,37 @@ All possible options for the build script:

---

## Building on macOS (Experimental)

DAPHNE can be built natively on macOS with Apple Silicon (ARM64). This support is experimental.

### Prerequisites

Install [Homebrew](https://brew.sh/), then install the required packages:

```bash
brew install gcc@15 cmake ninja wget zstd libomp
```

GCC is required because DAPHNE and all its dependencies must be built with the
same C++ standard library (libstdc++). Apple Clang uses libc++, which is
ABI-incompatible and causes link failures.

### Building

```bash
./build.sh --no-papi
```

The build script automatically detects macOS and configures GCC-15 as the compiler. PAPI is not supported on macOS, so `--no-papi` is required.

### Known Limitations

- CPU pinning (thread affinity) is disabled on macOS
- PAPI-based profiling is not available
- CUDA and FPGA options are not supported on macOS
- Only Apple Silicon (ARM64) has been tested

## Building on WSL

When using Windows Subsystems for Linux (WSL), the default memory limit for WSL is 50% of the total memory of the underlying Windows host. This can lead to build fails due to SIGKILL for DAPHNE builds. [Advanced settings configuration in WSL](https://learn.microsoft.com/en-us/windows/wsl/wsl-config) describes how the memory limit can be configured.
Expand Down
Loading