Skip to content

Commit bdd45a6

Browse files
author
Dane Springmeyer
committed
run clang-tidy on travis
1 parent 5baa948 commit bdd45a6

File tree

5 files changed

+245
-0
lines changed

5 files changed

+245
-0
lines changed

.clang-tidy

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
---
2+
Checks: '*'
3+
WarningsAsErrors: '*'
4+
HeaderFilterRegex: '\/src\/'
5+
AnalyzeTemporaryDtors: false
6+
CheckOptions:
7+
- key: google-readability-braces-around-statements.ShortStatementLines
8+
value: '1'
9+
- key: google-readability-function-size.StatementThreshold
10+
value: '800'
11+
- key: google-readability-namespace-comments.ShortNamespaceLines
12+
value: '10'
13+
- key: google-readability-namespace-comments.SpacesBeforeComments
14+
value: '2'
15+
- key: modernize-loop-convert.MaxCopySize
16+
value: '16'
17+
- key: modernize-loop-convert.MinConfidence
18+
value: reasonable
19+
- key: modernize-loop-convert.NamingStyle
20+
value: CamelCase
21+
- key: modernize-pass-by-value.IncludeStyle
22+
value: llvm
23+
- key: modernize-replace-auto-ptr.IncludeStyle
24+
value: llvm
25+
- key: modernize-use-nullptr.NullMacros
26+
value: 'NULL'
27+
...
28+

.travis.yml

+1
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,7 @@ script:
159159
make clean;
160160
make gyp;
161161
fi
162+
- ./scripts/clang-tidy.sh
162163

163164
after_script:
164165
- if [[ ${COVERAGE:-0} == 'True' ]]; then

scripts/clang-tidy.sh

+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
#!/usr/bin/env bash
2+
3+
set -eu
4+
set -o pipefail
5+
6+
# https://clang.llvm.org/extra/clang-tidy/
7+
8+
# to speed up re-runs, only re-create environment if needed
9+
if [[ ! -f local.env ]]; then
10+
# automatically setup environment
11+
./scripts/setup.sh --config local.env
12+
fi
13+
14+
# source the environment
15+
source local.env
16+
17+
PATH_TO_CLANG_TIDY_SCRIPT="$(pwd)/mason_packages/.link/share/run-clang-tidy.py"
18+
19+
# to speed up re-runs, only install clang-tidy if needed
20+
if [[ ! -f PATH_TO_CLANG_TIDY_SCRIPT ]]; then
21+
# The MASON_LLVM_RELEASE variable comes from `local.env`
22+
mason install clang-tidy ${MASON_LLVM_RELEASE}
23+
# We link the tools to make it easy to know ${PATH_TO_CLANG_TIDY_SCRIPT}
24+
mason link clang-tidy ${MASON_LLVM_RELEASE}
25+
fi
26+
27+
# build the compile_commands.json file if it does not exist
28+
if [[ ! -f build/compile_commands.json ]]; then
29+
# We need to clean otherwise when we make the project
30+
# will will not see all the compile commands
31+
make clean
32+
# Create the build directory to put the compile_commands in
33+
# We do this first to ensure it is there to start writing to
34+
# immediately (make make not create it right away)
35+
mkdir -p build
36+
# Run make, pipe the output to the generate_compile_commands.py
37+
# and drop them in a place that clang-tidy will automatically find them
38+
make | scripts/generate_compile_commands.py > build/compile_commands.json
39+
fi
40+
41+
# change into the build directory so that clang-tidy can find the files
42+
# at the right paths (since this is where the actual build happens)
43+
cd build
44+
${PATH_TO_CLANG_TIDY_SCRIPT} -fix
45+

scripts/generate_compile_commands.py

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
#!/usr/bin/env python
2+
3+
import sys
4+
import json
5+
import os
6+
import re
7+
8+
# Script to generate compile_commands.json based on Makefile output
9+
# Works by accepting Makefile output from stdin, parsing it, and
10+
# turning into json records. These are then printed to stdout.
11+
# More details on the compile_commands format at:
12+
# https://clang.llvm.org/docs/JSONCompilationDatabase.html
13+
#
14+
# Note: make must be run in verbose mode, e.g. V=1 make or VERBOSE=1 make
15+
#
16+
# Usage with node-cpp-skel:
17+
#
18+
# make | ./scripts/generate_compile_commands.py > build/compile_commands.json
19+
20+
# These work for node-cpp-skel to detect the files being compiled
21+
# They may need to be modified if you adapt this to another tool
22+
matcher = re.compile('^(.*) (.+cpp)')
23+
build_dir = os.path.join(os.getcwd())
24+
TOKEN_DENOTING_COMPILED_FILE='c++'
25+
26+
def generate():
27+
compile_commands = []
28+
for line in sys.stdin.readlines():
29+
if TOKEN_DENOTING_COMPILED_FILE in line:
30+
match = matcher.match(line)
31+
compile_commands.append({
32+
"directory": build_dir,
33+
"command": line.strip(),
34+
"file": os.path.normpath(os.path.join(build_dir,match.group(2)))
35+
})
36+
print json.dumps(compile_commands,indent=4)
37+
38+
if __name__ == '__main__':
39+
generate()

scripts/setup.sh

+132
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
#!/usr/bin/env bash
2+
3+
set -eu
4+
set -o pipefail
5+
6+
export MASON_RELEASE="${MASON_RELEASE:-v0.14.1}"
7+
export MASON_LLVM_RELEASE="${MASON_LLVM_RELEASE:-4.0.1}"
8+
9+
PLATFORM=$(uname | tr A-Z a-z)
10+
if [[ ${PLATFORM} == 'darwin' ]]; then
11+
PLATFORM="osx"
12+
fi
13+
14+
MASON_URL="https://s3.amazonaws.com/mason-binaries/${PLATFORM}-$(uname -m)"
15+
16+
llvm_toolchain_dir="$(pwd)/.toolchain"
17+
18+
function run() {
19+
local config=${1}
20+
# unbreak bash shell due to rvm bug on osx: https://github.com/direnv/direnv/issues/210#issuecomment-203383459
21+
# this impacts any usage of scripts that are source'd (like this one)
22+
if [[ "${TRAVIS_OS_NAME:-}" == "osx" ]]; then
23+
echo 'shell_session_update() { :; }' > ~/.direnvrc
24+
fi
25+
26+
#
27+
# COMPILER TOOLCHAIN
28+
#
29+
30+
# We install clang++ without the mason client for a couple reasons:
31+
# 1) decoupling makes it viable to use a custom branch of mason that might
32+
# modify the upstream s3 bucket in a such a way that does not give
33+
# it access to build tools like clang++
34+
# 2) Allows us to short-circuit and use a global clang++ install if it
35+
# is available to save space for local builds.
36+
GLOBAL_CLANG="${HOME}/.mason/mason_packages/${PLATFORM}-$(uname -m)/clang++/${MASON_LLVM_RELEASE}"
37+
GLOBAL_LLVM="${HOME}/.mason/mason_packages/${PLATFORM}-$(uname -m)/llvm/${MASON_LLVM_RELEASE}"
38+
if [[ -d ${GLOBAL_LLVM} ]]; then
39+
echo "Detected '${GLOBAL_LLVM}/bin/clang++', using it"
40+
local llvm_toolchain_dir=${GLOBAL_LLVM}
41+
elif [[ -d ${GLOBAL_CLANG} ]]; then
42+
echo "Detected '${GLOBAL_CLANG}/bin/clang++', using it"
43+
local llvm_toolchain_dir=${GLOBAL_CLANG}
44+
elif [[ -d ${GLOBAL_CLANG} ]]; then
45+
echo "Detected '${GLOBAL_CLANG}/bin/clang++', using it"
46+
local llvm_toolchain_dir=${GLOBAL_CLANG}
47+
elif [[ ! -d ${llvm_toolchain_dir} ]]; then
48+
BINARY="${MASON_URL}/clang++/${MASON_LLVM_RELEASE}.tar.gz"
49+
echo "Downloading ${BINARY}"
50+
mkdir -p ${llvm_toolchain_dir}
51+
curl -sSfL ${BINARY} | tar --gunzip --extract --strip-components=1 --directory=${llvm_toolchain_dir}
52+
fi
53+
54+
#
55+
# MASON
56+
#
57+
58+
function setup_mason() {
59+
local install_dir=${1}
60+
local mason_release=${2}
61+
mkdir -p ${install_dir}
62+
curl -sSfL https://github.com/mapbox/mason/archive/${mason_release}.tar.gz | tar --gunzip --extract --strip-components=1 --directory=${install_dir}
63+
}
64+
65+
setup_mason $(pwd)/.mason ${MASON_RELEASE}
66+
67+
#
68+
# ENV SETTINGS
69+
#
70+
71+
echo "export PATH=${llvm_toolchain_dir}/bin:$(pwd)/.mason:$(pwd)/mason_packages/.link/bin:"'${PATH}' > ${config}
72+
echo "export CXX=${llvm_toolchain_dir}/bin/clang++" >> ${config}
73+
echo "export MASON_RELEASE=${MASON_RELEASE}" >> ${config}
74+
echo "export MASON_LLVM_RELEASE=${MASON_LLVM_RELEASE}" >> ${config}
75+
# https://github.com/google/sanitizers/wiki/AddressSanitizerAsDso
76+
RT_BASE=${llvm_toolchain_dir}/lib/clang/${MASON_LLVM_RELEASE}/lib/$(uname | tr A-Z a-z)/libclang_rt
77+
if [[ $(uname -s) == 'Darwin' ]]; then
78+
RT_PRELOAD=${RT_BASE}.asan_osx_dynamic.dylib
79+
else
80+
RT_PRELOAD=${RT_BASE}.asan-x86_64.so
81+
fi
82+
echo "export MASON_LLVM_RT_PRELOAD=${RT_PRELOAD}" >> ${config}
83+
SUPPRESSION_FILE="/tmp/leak_suppressions.txt"
84+
echo "leak:__strdup" > ${SUPPRESSION_FILE}
85+
echo "leak:v8::internal" >> ${SUPPRESSION_FILE}
86+
echo "leak:node::CreateEnvironment" >> ${SUPPRESSION_FILE}
87+
echo "leak:node::Init" >> ${SUPPRESSION_FILE}
88+
echo "export ASAN_SYMBOLIZER_PATH=${llvm_toolchain_dir}/bin/llvm-symbolizer" >> ${config}
89+
echo "export MSAN_SYMBOLIZER_PATH=${llvm_toolchain_dir}/bin/llvm-symbolizer" >> ${config}
90+
echo "export UBSAN_OPTIONS=print_stacktrace=1" >> ${config}
91+
echo "export LSAN_OPTIONS=suppressions=${SUPPRESSION_FILE}" >> ${config}
92+
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}
93+
echo 'export MASON_SANITIZE="-fsanitize=address,undefined -fno-sanitize=vptr,function"' >> ${config}
94+
echo 'export MASON_SANITIZE_CXXFLAGS="${MASON_SANITIZE} -fno-sanitize=vptr,function -fsanitize-address-use-after-scope -fno-omit-frame-pointer -fno-common"' >> ${config}
95+
echo 'export MASON_SANITIZE_LDFLAGS="${MASON_SANITIZE}"' >> ${config}
96+
97+
exit 0
98+
}
99+
100+
function usage() {
101+
>&2 echo "Usage"
102+
>&2 echo ""
103+
>&2 echo "$ ./scripts/setup.sh --config local.env"
104+
>&2 echo "$ source local.env"
105+
>&2 echo ""
106+
exit 1
107+
}
108+
109+
if [[ ! ${1:-} ]]; then
110+
usage
111+
fi
112+
113+
# https://stackoverflow.com/questions/192249/how-do-i-parse-command-line-arguments-in-bash
114+
for i in "$@"
115+
do
116+
case $i in
117+
--config)
118+
if [[ ! ${2:-} ]]; then
119+
usage
120+
fi
121+
shift
122+
run $@
123+
;;
124+
-h | --help)
125+
usage
126+
shift
127+
;;
128+
*)
129+
usage
130+
;;
131+
esac
132+
done

0 commit comments

Comments
 (0)