-
Notifications
You must be signed in to change notification settings - Fork 0
/
uncertain.sh
executable file
·405 lines (339 loc) · 10 KB
/
uncertain.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
#!/bin/bash
# \todo: keep CONAN_VERSION updated, test thoroughly whenever you do, leave this "todo" here
CONAN_VERSION=1.59
GCOVR_VERSION=6.0
COVERAGE_INPUT_DIR=build
COVERAGE_OUTPUT_DIR=coverage-reports
STATIC_CHECKS_DIR=static-checks
# Fail if any command fails
set -e
set -o pipefail
# Print each command as it executes
QUIET="--quiet"
if [ -n "$VERBOSE" ]; then
set -o xtrace
QUIET=""
fi
# This script should work no matter where you call it from.
cd "$(dirname "$0")"
FAILURE=1
SUCCESS=0
# Check if Darwin or Linux
case "$OSTYPE" in
darwin*) echo "Running Darwin: ok" ;;
linux*) echo "Running Linux: ok" ;;
*)
echo "Error: This script only supports 'Darwin' or 'Linux'. You have $OSTYPE."
exit $FAILURE
;;
esac
# For private tokens stored locally
if [ -f .env ]; then
source .env
fi
####################
# HELPER FUNCTIONS #
####################
print_help() {
cat <<EOF
Uncertain library build & test utilities.
The following options are available:
install One-time installation of build toolchain and dependencies
config One-time configuration of conan remotes
clean Clean build directory
build Build tests and examples, options:
[--debug] - what it says (default=release)
[-j] - parallel build (auto select max-1 cores)
[--no-checks] - build without exporting symbols for static checks
check Run static checks - cppcheck and clang-tidy, options:
[--html] - run silent, but generate html reports, and open them in browser
test Run unit tests and demos, options:
[-j] - parallel build (auto select max-1 cores)
cov Generate code coverage reports
[--upload] - upload reports to codecov and coveralls
coverity Generate coverity static analysis and package for upload
[--yes] - actually upload it, eating into your quota
help/-h Display this dialog
EOF
}
ensure_not_root() {
if [ "$EUID" -eq 0 ]; then
if [ -z "${FORCED_ROOT}" ]; then
echo "Please do not run with root privileges!"
exit $FAILURE
else
echo "---=== FORCED_ROOT override ===---"
fi
fi
}
get_num_cpus() {
# build with 1 less than total number of CPUS, minimum 1
NUM_CPUS=$(cat /proc/cpuinfo | grep -c processor)
let NUM_CPUS-=1
if [ "$NUM_CPUS" -lt "1" ]; then
NUM_CPUS=1
fi
echo ${NUM_CPUS}
}
clean_dir() {
dir_name=$1
if [ -d "$dir_name" ]; then
echo "Removing $dir_name"
rm -rf "$dir_name"
return $SUCCESS
elif [ -f "$dir_name" ]; then
echo "File with this name already exists, not a directory."
return $FAILURE
fi
}
create_clean_directory() {
dir_name=$1
clean_dir "$dir_name"
if mkdir -p "$dir_name"; then
echo "Clean directory created: $dir_name"
return $SUCCESS
else
echo "Creating directory failed: $dir_name"
return $FAILURE
fi
}
install_linux() {
sudo apt-get update
sudo apt-get install -y cmake python3-pip python3-setuptools clang-tidy cppcheck lcov
}
install_pip() {
pip3 install -U pip
pip3 install install conan==$CONAN_VERSION
pip3 install install gcovr==$GCOVR_VERSION
pip3 install install codecov cpp-coveralls clang-html
}
configure_conan() {
source "${HOME}/.profile"
conan profile new --detect default
conan profile update settings.compiler.libcxx=libstdc++11 default
}
run_cppcheck() {
echo "Running cppcheck..."
if [ "$1" == "html" ]; then
CPPCHECK_OUTPUT_DIR=${STATIC_CHECKS_DIR}/cppcheck
create_clean_directory ${CPPCHECK_OUTPUT_DIR}
xml_opts="--xml --output-file=${CPPCHECK_OUTPUT_DIR}/report.xml"
fi
cppcheck --language=c++ --enable=all --inconclusive --force --inline-suppr ${QUIET} \
--project=build/compile_commands.json \
--suppress=missingIncludeSystem \
--suppress=*:*/gtest/* \
--addon=misc \
${xml_opts} \
.
# --addon=misra.py \
if [ "$1" == "html" ]; then
cppcheck-htmlreport --file=${CPPCHECK_OUTPUT_DIR}/report.xml \
--title="Uncertain lib" \
--report-dir=${CPPCHECK_OUTPUT_DIR} --source-dir=.
python -m webbrowser "${CPPCHECK_OUTPUT_DIR}/index.html"
fi
}
run_clang_tidy() {
echo "Running clang-tidy..."
j_opt=$2
CLANG_TIDY_EXEC="run-clang-tidy"
CLANG_TIDY_VERSION=$(echo "$(clang-tidy --version | sed -n 1p)" | awk -F[" ".] '{print $4}')
if [ "$1" == "html" ]; then
TIDY_OUTPUT_DIR=${STATIC_CHECKS_DIR}/clang-tidy
TIDY_FILE=${TIDY_OUTPUT_DIR}/logfile.log
create_clean_directory ${TIDY_OUTPUT_DIR}
else
TIDY_FILE="/dev/stdout"
fi
files=$(find . -regextype posix-extended -regex '.*\.(cpp|hpp|h|tpp)' -not -path "*build*")
echo "Using $CLANG_TIDY_EXEC $j_opt with version=${CLANG_TIDY_VERSION}"
echo -e "Will analyze the following files:\n${files}"
$CLANG_TIDY_EXEC -quiet ${j_opt} -p build ${files} \
-header-filter='^.*\/(source|examples|tests)\/.*\.(hpp|cpp|h|tpp)$'\
> ${TIDY_FILE}
if [ "$1" == "html" ]; then
sed -i "s@$(pwd)@@g" ${TIDY_FILE}
clang-tidy-html ${TIDY_FILE} -o ${TIDY_OUTPUT_DIR}/clang.html \
-d "https://releases.llvm.org/${CLANG_TIDY_VERSION}.0.0/tools/clang/tools/extra/docs/clang-tidy/checks/list.html"
python -m webbrowser "${TIDY_OUTPUT_DIR}/clang.html"
fi
}
generate_coverage_reports() {
echo "Generating test coverage reports..."
create_clean_directory ${COVERAGE_OUTPUT_DIR}
lcov ${QUIET} --directory "$COVERAGE_INPUT_DIR" --capture \
--output-file "$COVERAGE_OUTPUT_DIR/coverage.info"
lcov ${QUIET} --remove "$COVERAGE_OUTPUT_DIR/coverage.info" \
--output-file "$COVERAGE_OUTPUT_DIR/coverage_trimmed.info" \
"/usr/include*" \
"*/tests/*" \
"*gtest*"
rm "$COVERAGE_OUTPUT_DIR/coverage.info"
mv "$COVERAGE_OUTPUT_DIR/coverage_trimmed.info" "$COVERAGE_OUTPUT_DIR/coverage.info"
}
view_coverage() {
genhtml ${QUIET} "$COVERAGE_OUTPUT_DIR/coverage.info" \
--output-directory "$COVERAGE_OUTPUT_DIR"
echo "Coverage reports generated at '$COVERAGE_OUTPUT_DIR/index.html'"
echo " You may open it in browser with 'python3 -m webbrowser ${COVERAGE_OUTPUT_DIR}/index.html'"
python -m webbrowser "${COVERAGE_OUTPUT_DIR}/index.html"
}
upload_codecov() {
echo "Uploading coverage reports to Codecov"
curl -Os https://uploader.codecov.io/latest/linux/codecov
chmod +x codecov
./codecov
rm codecov
}
upload_coveralls() {
echo "Uploading coverage reports to Coveralls"
cpp-coveralls -t $COVERALLS_REPO_TOKEN --build-root build --gcov-options '\-lp' \
-r . \
-E ".*gtest.*" -E ".*CMakeFiles.*" \
-e build/lib -e build/tests -e build/examples -e tests -e examples
}
upload_codacy() {
echo "Uploading coverage reports to Codacy"
bash <(curl -Ls https://coverage.codacy.com/get.sh) report -r ./coverage-reports/coverage.info
}
########
# HELP #
########
if [ "$1" == "help" ] || [ "$1" == "-h" ]; then
print_help
exit $SUCCESS
###########
# INSTALL #
###########
elif [ "$1" == "install" ]; then
case "$OSTYPE" in
linux*)
ensure_not_root
install_linux
install_pip
exit $SUCCESS
;;
*)
echo "Error: No installation scripts for $OSTYPE."
exit $FAILURE
;;
esac
#############
# CONFIGURE #
#############
elif [ "$1" == "configure" ]; then
ensure_not_root
configure_conan
exit $SUCCESS
#########
# CLEAN #
#########
elif [ "$1" == "clean" ]; then
clean_dir build
clean_dir "$COVERAGE_OUTPUT_DIR"
exit $SUCCESS
#########
# BUILD #
#########
elif [ "$1" == "build" ]; then
config_type="Release"
if [ "$2" == "--debug" ] || [ "$3" == "--debug" ] || [ "$4" == "--debug" ]; then
config_type="Debug"
fi
j_opt=""
if [ "$2" == "-j" ] || [ "$3" == "-j" ] || [ "$4" == "-j" ]; then
j_opt="-j$(eval get_num_cpus)"
fi
checks_opt="-DCMAKE_EXPORT_COMPILE_COMMANDS=ON"
if [ "$2" == "--no-checks" ] || [ "$3" == "--no-checks" ] || [ "$4" == "--no-checks" ]; then
checks_opt=""
fi
ensure_not_root
create_clean_directory build
pushd build
cmake -DCMAKE_BUILD_TYPE=${config_type} ${checks_opt} ..
make everything ${j_opt}
popd
exit $SUCCESS
#########
# CHECK #
#########
elif [ "$1" == "check" ]; then
if [ "$2" == "-j" ] || [ "$3" == "-j" ]; then
j_opt="-j$(eval get_num_cpus)"
fi
if [ "$2" == "--html" ] || [ "$3" == "--html" ]; then
run_clang_tidy html $j_opt
run_cppcheck html
else
run_clang_tidy nohtml $j_opt
run_cppcheck
fi
########
# TEST #
########
elif [ "$1" == "test" ]; then
j_opt=""
if [ "$2" == "-j" ]; then
j_opt="-j$(eval get_num_cpus)"
fi
ensure_not_root
create_clean_directory build
pushd build
cmake -DCMAKE_BUILD_TYPE=Debug -DCOV=1 ..
make run_tests ${j_opt}
make examples ${j_opt}
./bin/ms_demo > null
./bin/full_demo > null
popd
exit $SUCCESS
############
# COVERAGE #
############
elif [ "$1" == "cov" ]; then
ensure_not_root
generate_coverage_reports
if [ "$2" == "--upload" ]; then
source "${HOME}/.profile"
upload_codacy
upload_codecov
upload_coveralls
else
view_coverage
fi
exit $SUCCESS
############
# COVERITY #
############
elif [ "$1" == "coverity" ]; then
ensure_not_root
create_clean_directory build
pushd build
cmake ..
# assumes cov-build has been downloaded and installed to system (or to path) from
# https://scan.coverity.com/download?tab=cxx
cov-build --dir cov-int make everything
tar caf myproject.bz2 cov-int
GIT_BRANCH="$(git rev-parse --abbrev-ref HEAD)"
GIT_SHORT_SHA="$(git rev-parse --short HEAD)"
VERSION_NAME="${GIT_BRANCH}-${GIT_SHORT_SHA}"
if [ "$2" == "--yes" ]; then
echo "Actually uploading coverity scan data. Watch that quota!"
curl \
--form token=${COVERITY_TOKEN} --form email=${COVERITY_EMAIL} --form file=@./myproject.bz2 \
--form version="${VERSION_NAME}" --form description="Uncertain lib" \
https://scan.coverity.com/builds?project=martukas%2Funcertain
else
echo "Dry run only. Would upload to: ${VERSION_NAME}"
fi
popd
exit $SUCCESS
################
# ERROR & HELP #
################
else
echo "No valid options provided :\("
print_help
exit $FAILURE
fi