blob: 3e802a7e63a19d23fb1feb3b77cc7d7cdeff0c40 [file] [log] [blame]
#!/bin/bash
# Based on setup-helper-functions.sh from Facebook Velox
#
# Copyright (c) Facebook, Inc. and its affiliates.
#
# Licensed 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.
# github_checkout $REPO $VERSION $GIT_CLONE_PARAMS clones or re-uses an existing clone of the
# specified repo, checking out the requested version.
DEPENDENCY_DIR=${DEPENDENCY_DIR:-$(pwd)/deps-download}
OS_CXXFLAGS=""
function run_and_time {
time "$@" || (echo "Failed to run $* ." ; exit 1 )
{ echo "+ Finished running $*"; } 2> /dev/null
}
function prompt {
(
while true; do
local input="${PROMPT_ALWAYS_RESPOND:-}"
echo -n "$(tput bold)$* [Y, n]$(tput sgr0) "
[[ -z "${input}" ]] && read input
if [[ "${input}" == "Y" || "${input}" == "y" || "${input}" == "" ]]; then
return 0
elif [[ "${input}" == "N" || "${input}" == "n" ]]; then
return 1
fi
done
) 2> /dev/null
}
function github_checkout {
local REPO=$1
shift
local VERSION=$1
shift
local GIT_CLONE_PARAMS=$@
local DIRNAME=$(basename $REPO)
SUDO="${SUDO:-""}"
cd "${DEPENDENCY_DIR}"
if [ -z "${DIRNAME}" ]; then
echo "Failed to get repo name from ${REPO}"
exit 1
fi
if [ -d "${DIRNAME}" ] && prompt "${DIRNAME} already exists. Delete?"; then
${SUDO} rm -rf "${DIRNAME}"
fi
if [ ! -d "${DIRNAME}" ]; then
git clone -q -b $VERSION $GIT_CLONE_PARAMS "https://github.com/${REPO}.git"
fi
cd "${DIRNAME}"
}
# get_cxx_flags [$CPU_ARCH]
# Echos appropriate compiler flags.
# If $CPU_ARCH is set then we use that else we determine best possible set of flags
# to use based on current cpu architecture.
# The goal of this function is to consolidate all architecture specific flags to one
# location.
# The values that CPU_ARCH can take are as follows:
# arm64 : Target Apple silicon.
# aarch64: Target general 64 bit arm cpus.
# avx: Target Intel CPUs with AVX.
# sse: Target Intel CPUs with sse.
# Echo's the appropriate compiler flags which can be captured as so
# CXX_FLAGS=$(get_cxx_flags) or
# CXX_FLAGS=$(get_cxx_flags "avx")
function get_cxx_flags {
local CPU_ARCH=${1:-""}
local OS=$(uname)
local MACHINE=$(uname -m)
if [[ -z "$CPU_ARCH" ]]; then
if [ "$OS" = "Darwin" ]; then
if [ "$MACHINE" = "arm64" ]; then
CPU_ARCH="arm64"
else # x86_64
local CPU_CAPABILITIES=$(sysctl -a | grep machdep.cpu.features | awk '{print tolower($0)}')
if [[ $CPU_CAPABILITIES =~ "avx" ]]; then
CPU_ARCH="avx"
else
CPU_ARCH="sse"
fi
fi
elif [ "$OS" = "Linux" ]; then
if [ "$MACHINE" = "aarch64" ]; then
CPU_ARCH="aarch64"
else # x86_64
local CPU_CAPABILITIES=$(cat /proc/cpuinfo | grep flags | head -n 1| awk '{print tolower($0)}')
if [[ $CPU_CAPABILITIES =~ "avx" ]]; then
CPU_ARCH="avx"
elif [[ $CPU_CAPABILITIES =~ "sse" ]]; then
CPU_ARCH="sse"
fi
fi
else
echo "Unsupported platform $OS"; exit 1;
fi
fi
case $CPU_ARCH in
"arm64")
echo -n "-mcpu=apple-m1+crc -std=c++17 -fvisibility=hidden"
;;
"avx")
echo -n "-mavx2 -mfma -mavx -mf16c -mlzcnt -std=c++17 -mbmi2"
;;
"sse")
echo -n "-msse4.2 -std=c++17"
;;
"aarch64")
# Read Arm MIDR_EL1 register to detect Arm cpu.
# https://developer.arm.com/documentation/100616/0301/register-descriptions/aarch64-system-registers/midr-el1--main-id-register--el1
ARM_CPU_FILE="/sys/devices/system/cpu/cpu0/regs/identification/midr_el1"
# https://gitlab.arm.com/telemetry-solution/telemetry-solution/-/blob/main/data/pmu/cpu/neoverse/neoverse-n1.json#L13
# N1:d0c; N2:d49; V1:d40;
Neoverse_N1="d0c"
Neoverse_N2="d49"
Neoverse_V1="d40"
if [ -f "$ARM_CPU_FILE" ]; then
hex_ARM_CPU_DETECT=`cat $ARM_CPU_FILE`
# PartNum, [15:4]: The primary part number such as Neoverse N1/N2 core.
ARM_CPU_PRODUCT=${hex_ARM_CPU_DETECT: -4:3}
if [ "$ARM_CPU_PRODUCT" = "$Neoverse_N1" ]; then
echo -n "-mcpu=neoverse-n1 -std=c++17"
elif [ "$ARM_CPU_PRODUCT" = "$Neoverse_N2" ]; then
echo -n "-mcpu=neoverse-n2 -std=c++17"
elif [ "$ARM_CPU_PRODUCT" = "$Neoverse_V1" ]; then
echo -n "-mcpu=neoverse-v1 -std=c++17"
else
echo -n "-march=armv8-a+crc+crypto -std=c++17"
fi
else
echo -n "-std=c++17"
fi
;;
*)
echo -n "Architecture not supported!"
esac
}
function wget_and_untar {
local URL=$1
local DIR=$2
mkdir -p "${DEPENDENCY_DIR}"
pushd "${DEPENDENCY_DIR}"
SUDO="${SUDO:-""}"
if [ -d "${DIR}" ]; then
if prompt "${DIR} already exists. Delete?"; then
${SUDO} rm -rf "${DIR}"
else
popd
return
fi
fi
mkdir -p "${DIR}"
pushd "${DIR}"
curl -L "${URL}" > $2.tar.gz
tar -xz --strip-components=1 -f $2.tar.gz
popd
popd
}
function cmake_install_dir {
pushd "${DEPENDENCY_DIR}/$1"
# remove the directory argument
shift
cmake_install $@
popd
}
function cmake_install {
local NAME=$(basename "$(pwd)")
local BINARY_DIR=_build
SUDO="${SUDO:-""}"
if [ -d "${BINARY_DIR}" ]; then
if prompt "Do you want to rebuild ${NAME}?"; then
${SUDO} rm -rf "${BINARY_DIR}"
else
return
fi
fi
mkdir -p "${BINARY_DIR}"
COMPILER_FLAGS=$(get_cxx_flags)
# Add platform specific CXX flags if any
COMPILER_FLAGS+=${OS_CXXFLAGS}
# CMAKE_POSITION_INDEPENDENT_CODE is required so that CelebornCpp can be built into dynamic libraries
cmake -Wno-dev -B"${BINARY_DIR}" \
-GNinja \
-DCMAKE_POSITION_INDEPENDENT_CODE=ON \
-DCMAKE_CXX_STANDARD=17 \
"${INSTALL_PREFIX+-DCMAKE_PREFIX_PATH=}${INSTALL_PREFIX-}" \
"${INSTALL_PREFIX+-DCMAKE_INSTALL_PREFIX=}${INSTALL_PREFIX-}" \
-DCMAKE_CXX_FLAGS="$COMPILER_FLAGS" \
-DBUILD_TESTING=OFF \
"$@"
# Exit if the build fails.
cmake --build "${BINARY_DIR}" || { echo 'build failed' ; exit 1; }
${SUDO} cmake --install "${BINARY_DIR}"
}