Skip to content

Commit

Permalink
address #12 and #13
Browse files Browse the repository at this point in the history
  • Loading branch information
Dane Springmeyer committed Aug 24, 2017
1 parent a1d10e1 commit e4bb936
Show file tree
Hide file tree
Showing 5 changed files with 177 additions and 8 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
.DS_Store
mason_packages
build
*.profdata
*.profraw
.toolchain
18 changes: 10 additions & 8 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,17 +24,19 @@ matrix:
sources: [ 'ubuntu-toolchain-r-test' ]
packages: [ 'libstdc++6', 'libstdc++-5-dev' ]
- os: osx
osx_image: xcode7.3
osx_image: xcode8.3

cache: apt
env:
global:
- CMAKE_VERSION="3.8.2"

install:
- git clone --depth=1 https://github.com/mapbox/mason.git ./.mason
- ./.mason/mason install clang++ 4.0.0
- export PATH=$(./.mason/mason prefix clang++ 4.0.0)/bin:${PATH}
- which clang++
- ./.mason/mason install cmake 3.8.2
- export PATH=$(./.mason/mason prefix cmake 3.8.2)/bin:${PATH}
# set up the environment by installing mason and clang++
- ./scripts/setup.sh --config local.env
# put mason and clang++ on PATH
- source local.env
- mason install cmake ${CMAKE_VERSION}
- mason link cmake ${CMAKE_VERSION}
- which cmake

script:
Expand Down
3 changes: 3 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,8 @@ debug:
test: default
./build/unit-tests

coverage:
./scripts/coverage.sh

clean:
rm -rf build
29 changes: 29 additions & 0 deletions scripts/coverage.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#!/usr/bin/env bash

set -eu
set -o pipefail

# http://clang.llvm.org/docs/UsersManual.html#profiling-with-instrumentation
# https://www.bignerdranch.com/blog/weve-got-you-covered/

# automatically setup environment

./scripts/setup.sh --config local.env
source local.env

make clean
export CXXFLAGS="-fprofile-instr-generate -fcoverage-mapping"
export LDFLAGS="-fprofile-instr-generate"
mason install llvm-cov ${MASON_LLVM_RELEASE}
mason link llvm-cov ${MASON_LLVM_RELEASE}
make debug
rm -f *profraw
rm -f *gcov
rm -f *profdata
LLVM_PROFILE_FILE="code-%p.profraw" make test
CXX_MODULE="./build/unit-tests"
llvm-profdata merge -output=code.profdata code-*.profraw
llvm-cov report ${CXX_MODULE} -instr-profile=code.profdata -use-color
llvm-cov show ${CXX_MODULE} -instr-profile=code.profdata src/*.cpp -filename-equivalence -use-color
llvm-cov show ${CXX_MODULE} -instr-profile=code.profdata src/*.cpp -filename-equivalence -use-color --format html > /tmp/coverage.html
echo "open /tmp/coverage.html for HTML version of this report"
132 changes: 132 additions & 0 deletions scripts/setup.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
#!/usr/bin/env bash

set -eu
set -o pipefail

export MASON_RELEASE="${MASON_RELEASE:-v0.14.1}"
export MASON_LLVM_RELEASE="${MASON_LLVM_RELEASE:-4.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"
echo "leak:__strdup" > ${SUPPRESSION_FILE}
echo "leak:v8::internal" >> ${SUPPRESSION_FILE}
echo "leak:node::CreateEnvironment" >> ${SUPPRESSION_FILE}
echo "leak:node::Init" >> ${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}
echo "export LSAN_OPTIONS=suppressions=${SUPPRESSION_FILE}" >> ${config}
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

0 comments on commit e4bb936

Please sign in to comment.