| #!/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}" |
| } |