blob: 42ce1ba8eddcf652debcae80f97d7f43fd0f2abe [file] [log] [blame]
#!/usr/bin/env bash
set -eu
set -o pipefail
export MASON_RELEASE="${_MASON_RELEASE:-v0.18.0}"
export MASON_LLVM_RELEASE="${_MASON_LLVM_RELEASE:-5.0.1}"
PLATFORM=$(uname | tr A-Z a-z)
if [[ ${PLATFORM} == 'darwin' ]]; then
PLATFORM="osx"
fi
MASON_URL="https://s3.amazonaws.com/mason-binaries/${PLATFORM}-$(uname -m)"
llvm_toolchain_dir="$(pwd)/.toolchain"
function run() {
local config=${1}
# unbreak bash shell due to rvm bug on osx: https://github.com/direnv/direnv/issues/210#issuecomment-203383459
# this impacts any usage of scripts that are source'd (like this one)
if [[ "${TRAVIS_OS_NAME:-}" == "osx" ]]; then
echo 'shell_session_update() { :; }' > ~/.direnvrc
fi
#
# COMPILER TOOLCHAIN
#
# We install clang++ without the mason client for a couple reasons:
# 1) decoupling makes it viable to use a custom branch of mason that might
# modify the upstream s3 bucket in a such a way that does not give
# it access to build tools like clang++
# 2) Allows us to short-circuit and use a global clang++ install if it
# is available to save space for local builds.
GLOBAL_CLANG="${HOME}/.mason/mason_packages/${PLATFORM}-$(uname -m)/clang++/${MASON_LLVM_RELEASE}"
GLOBAL_LLVM="${HOME}/.mason/mason_packages/${PLATFORM}-$(uname -m)/llvm/${MASON_LLVM_RELEASE}"
if [[ -d ${GLOBAL_LLVM} ]]; then
echo "Detected '${GLOBAL_LLVM}/bin/clang++', using it"
local llvm_toolchain_dir=${GLOBAL_LLVM}
elif [[ -d ${GLOBAL_CLANG} ]]; then
echo "Detected '${GLOBAL_CLANG}/bin/clang++', using it"
local llvm_toolchain_dir=${GLOBAL_CLANG}
elif [[ -d ${GLOBAL_CLANG} ]]; then
echo "Detected '${GLOBAL_CLANG}/bin/clang++', using it"
local llvm_toolchain_dir=${GLOBAL_CLANG}
elif [[ ! -d ${llvm_toolchain_dir} ]]; then
BINARY="${MASON_URL}/clang++/${MASON_LLVM_RELEASE}.tar.gz"
echo "Downloading ${BINARY}"
mkdir -p ${llvm_toolchain_dir}
curl -sSfL ${BINARY} | tar --gunzip --extract --strip-components=1 --directory=${llvm_toolchain_dir}
fi
#
# MASON
#
function setup_mason() {
local install_dir=${1}
local mason_release=${2}
mkdir -p ${install_dir}
curl -sSfL https://github.com/mapbox/mason/archive/${mason_release}.tar.gz | tar --gunzip --extract --strip-components=1 --directory=${install_dir}
}
setup_mason $(pwd)/.mason ${MASON_RELEASE}
#
# ENV SETTINGS
#
echo "export PATH=${llvm_toolchain_dir}/bin:$(pwd)/.mason:$(pwd)/mason_packages/.link/bin:"'${PATH}' > ${config}
echo "export CXX=${CXX:-${llvm_toolchain_dir}/bin/clang++}" >> ${config}
echo "export MASON_RELEASE=${MASON_RELEASE}" >> ${config}
echo "export MASON_LLVM_RELEASE=${MASON_LLVM_RELEASE}" >> ${config}
# https://github.com/google/sanitizers/wiki/AddressSanitizerAsDso
RT_BASE=${llvm_toolchain_dir}/lib/clang/${MASON_LLVM_RELEASE}/lib/$(uname | tr A-Z a-z)/libclang_rt
if [[ $(uname -s) == 'Darwin' ]]; then
RT_PRELOAD=${RT_BASE}.asan_osx_dynamic.dylib
else
RT_PRELOAD=${RT_BASE}.asan-x86_64.so
fi
echo "export MASON_LLVM_RT_PRELOAD=${RT_PRELOAD}" >> ${config}
SUPPRESSION_FILE="/tmp/leak_suppressions.txt"
# Add suppressions as needed
#echo "leak:__strdup" > ${SUPPRESSION_FILE}
echo "export ASAN_SYMBOLIZER_PATH=${llvm_toolchain_dir}/bin/llvm-symbolizer" >> ${config}
echo "export MSAN_SYMBOLIZER_PATH=${llvm_toolchain_dir}/bin/llvm-symbolizer" >> ${config}
echo "export UBSAN_OPTIONS=print_stacktrace=1" >> ${config}
if [[ -f ${SUPPRESSION_FILE} ]]; then
echo "export LSAN_OPTIONS=suppressions=${SUPPRESSION_FILE}" >> ${config}
fi
echo "export ASAN_OPTIONS=symbolize=1:abort_on_error=1:detect_container_overflow=1:check_initialization_order=1:detect_stack_use_after_return=1" >> ${config}
echo 'export MASON_SANITIZE="-fsanitize=address,undefined -fno-sanitize=vptr,function"' >> ${config}
echo 'export MASON_SANITIZE_CXXFLAGS="${MASON_SANITIZE} -fno-sanitize=vptr,function -fsanitize-address-use-after-scope -fno-omit-frame-pointer -fno-common"' >> ${config}
echo 'export MASON_SANITIZE_LDFLAGS="${MASON_SANITIZE}"' >> ${config}
exit 0
}
function usage() {
>&2 echo "Usage"
>&2 echo ""
>&2 echo "$ ./scripts/setup.sh --config local.env"
>&2 echo "$ source local.env"
>&2 echo ""
exit 1
}
if [[ ! ${1:-} ]]; then
usage
fi
# https://stackoverflow.com/questions/192249/how-do-i-parse-command-line-arguments-in-bash
for i in "$@"
do
case $i in
--config)
if [[ ! ${2:-} ]]; then
usage
fi
shift
run $@
;;
-h | --help)
usage
shift
;;
*)
usage
;;
esac
done