forked from Myralllka/template_cpp
-
Notifications
You must be signed in to change notification settings - Fork 5
Expand file tree
/
Copy pathcompile.sh
More file actions
executable file
·307 lines (284 loc) · 12.1 KB
/
compile.sh
File metadata and controls
executable file
·307 lines (284 loc) · 12.1 KB
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
#!/bin/bash
# The Tea-Ware License (Version 2.0)
# Copyright (c) 2024 Radomyr Husiev <h.radomyr@proton.me>
#
# This script is part of a project licensed under the Tea-Ware License.
# Feel free to use, modify, and distribute this script, keeping this notice intact.
# If we meet and you find this useful, a cup of tea would be appreciated!
#
# Full license: https://github.com/rhusiev/Tea-Ware-License-v2
set -o errexit
set -o nounset
set -o pipefail
install_prefix=".."
log=1
help_message="Usage: ./compile.sh [options]
Options:
-h --help Show help message
-o --optimize-build Compile with optimization before executing
-d --debug-build Compile with debug options
-i --relwithdebinfo-build Compile with release debug info
-I --install_prefix Installation path
-p --pipeline Enable pipeline build using different compilers and sanitizers and analyzers
-c --clean Clean cmake-build-* directories and compile.log
-n --nolog Don't log to compile.log
--s='<args>' Arguments for program when run under valgrind and sanitizers. If '--s' not present, valgrind and sanitizers will not be executed"
if [ $# -eq 0 ]; then
echo "$help_message"
exit 0
fi
for arg in "$@"; do
case $arg in
-n|--nolog)
log=0
;;
-I | --install_prefix)
if [ "$2" -eq "$2" ] 2>/dev/null; then
install_prefix=$2
shift 2
else
echo "Option --install_prefix requires a numerical argument." 2>&1
exit 1
fi
;;
esac
done
call_location=$(pwd)
if [ $log -eq 1 ]; then
echo "" > "$call_location/compile.log"
handle_output() {
while IFS= read -r line; do
echo "$line" | tee -a $call_location/compile.log | grep --invert-match ".*\(Consider enabling PVS-Studio\|Sanitizers enabled\|[Ee]nabled in CMakeLists.txt\).*"
done
}
else
handle_output() {
while IFS= read -r line; do
echo "$line" | grep --invert-match ".*\(Consider enabling PVS-Studio\|Sanitizers enabled\|[Ee]nabled in CMakeLists.txt\).*"
done
}
fi
echo "===Starting===" 2>&1 | handle_output
handle_error() {
echo "Something went wrong, restoring the original CMakeLists.txt"
sed -i 's/set(ENABLE_UBSan ON)/set(ENABLE_UBSan OFF)/g' ../CMakeLists.txt
sed -i 's/set(ENABLE_ASAN ON)/set(ENABLE_ASAN OFF)/g' ../CMakeLists.txt
sed -i 's/set(ENABLE_TSan ON)/set(ENABLE_TSan OFF)/g' ../CMakeLists.txt
sed -i 's/set(ENABLE_MSan ON)/set(ENABLE_MSan OFF)/g' ../CMakeLists.txt
sed -i "s/clang-ubsan)/${project_name})/g" ../CMakeLists.txt
sed -i "s/clang-asan)/${project_name})/g" ../CMakeLists.txt
sed -i "s/clang-tsan)/${project_name})/g" ../CMakeLists.txt
sed -i "s/clang-msan)/${project_name})/g" ../CMakeLists.txt
sed -i "s/ENABLE_PVS_STUDIO ON)/ENABLE_PVS_STUDIO OFF)/g" ../CMakeLists.txt
sed -i 's/#set(CMAKE_CXX_CLANG_TIDY "clang-tidy;-checks=\*")/set(CMAKE_CXX_CLANG_TIDY "clang-tidy;-checks=\*")/g' ../CMakeLists.txt
cd ..
remove_pvs_headers
cd -
exit 1
}
add_pvs_headers() {
cd ..
find . -type f -name "*.cpp" -o -name "*.c" -o -name "*.hpp" -o -name "*.h" | grep -P '.*\/[^.]*\.(cpp|c|hpp|h)$' >files.txt
echo "**Adding PVS headers to the files:**" 2>&1 | handle_output
# Remove files whose names start with "cmake", "CMake" or "./cmake" or "./CMake"
sed -i '/^\.\/cmake/d' files.txt
sed -i '/^\.\/CMake/d' files.txt
sed -i '/^cmake/d' files.txt
sed -i '/^CMake/d' files.txt
cat files.txt 2>&1 | handle_output
while IFS= read -r file; do
if [[ $(head -n 1 "$file") != "// This is a personal academic project. Dear PVS-Studio, please check it." ]]; then
sed -i '1s/^/\/\/ This is a personal academic project. Dear PVS-Studio, please check it.\n\/\/ PVS-Studio Static Code Analyzer for C, C++, C#, and Java: http:\/\/www.viva64.com\n/' "$file"
fi
done <files.txt
rm files.txt
cd -
}
remove_pvs_headers() {
find . -type f -name "*.cpp" -o -name "*.c" -o -name "*.hpp" -o -name "*.h" | grep -P '.*\/[^.]*\.(cpp|c|hpp|h)$' >files.txt
echo "**Removing PVS headers from files:**" 2>&1 | handle_output
# Remove files whose names start with "cmake", "CMake" or "./cmake" or "./CMake"
sed -i '/^\.\/cmake/d' files.txt
sed -i '/^\.\/CMake/d' files.txt
sed -i '/^cmake/d' files.txt
sed -i '/^CMake/d' files.txt
# cat files.txt | sed 's/^/ /' 2>&1 | handle_output
cat files.txt 2>&1 | handle_output
while IFS= read -r file; do
if [[ $(head -n 1 "$file") == "// This is a personal academic project. Dear PVS-Studio, please check it." ]]; then
sed -i '1,2d' "$file"
fi
done <files.txt
rm files.txt
}
pipeline() {
echo "===Running with Pipeline===" 2>&1 | handle_output
mkdir -p ./cmake-build-pipeline
(
pushd ./cmake-build-pipeline >/dev/null || exit 1
# Find the project_name in `set(PROJECT_NAME project_name)`
project_name=$(grep -oP '(?<=set\(PROJECT_NAME ).*(?=\))' ../CMakeLists.txt)
# CLANG
sed -i "s/ENABLE_PVS_STUDIO ON)/ENABLE_PVS_STUDIO OFF)/g" ../CMakeLists.txt
sed -i 's/set(CMAKE_CXX_CLANG_TIDY "clang-tidy;-checks=\*")/#set(CMAKE_CXX_CLANG_TIDY "clang-tidy;-checks=\*")/g' ../CMakeLists.txt
sed -i 's/set(ENABLE_UBSan OFF)/set(ENABLE_UBSan ON)/g' ../CMakeLists.txt
sed -i "s/${project_name})/clang-ubsan)/g" ../CMakeLists.txt
echo "====Compiling with Clang UBSan====" 2>&1 | handle_output
rm -rf ../cmake-build-pipeline/* # instead of just rm -rf * - in case something fails, it won't delete everything
CC=clang CXX=clang++ cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX="${install_prefix}" .. 2>&1 | handle_output || handle_error
cmake --build . 2>&1 | handle_output || handle_error
cmake --install . 2>&1 | handle_output || handle_error
echo "====Compiling with Clang ASan====" 2>&1 | handle_output
sed -i 's/set(ENABLE_UBSan ON)/set(ENABLE_UBSan OFF)/g' ../CMakeLists.txt
sed -i 's/set(ENABLE_ASAN OFF)/set(ENABLE_ASAN ON)/g' ../CMakeLists.txt
sed -i 's/clang-ubsan)/clang-asan)/g' ../CMakeLists.txt
rm -rf ../cmake-build-pipeline/*
CC=clang CXX=clang++ cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX="${install_prefix}" .. 2>&1 | handle_output || handle_error
cmake --build . 2>&1 | handle_output || handle_error
cmake --install . 2>&1 | handle_output || handle_error
echo "====Compiling with Clang TSan====" 2>&1 | handle_output
sed -i 's/set(ENABLE_ASAN ON)/set(ENABLE_ASAN OFF)/g' ../CMakeLists.txt
sed -i 's/set(ENABLE_TSan OFF)/set(ENABLE_TSan ON)/g' ../CMakeLists.txt
sed -i 's/clang-asan)/clang-tsan)/g' ../CMakeLists.txt
rm -rf ../cmake-build-pipeline/*
CC=clang CXX=clang++ cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX="${install_prefix}" .. 2>&1 | handle_output || handle_error
cmake --build . 2>&1 | handle_output || handle_error
cmake --install . 2>&1 | handle_output || handle_error
echo "====Compiling with Clang MSan====" 2>&1 | handle_output
sed -i 's/set(ENABLE_TSan ON)/set(ENABLE_TSan OFF)/g' ../CMakeLists.txt
sed -i 's/set(ENABLE_MSan OFF)/set(ENABLE_MSan ON)/g' ../CMakeLists.txt
sed -i 's/clang-tsan)/clang-msan)/g' ../CMakeLists.txt
rm -rf ../cmake-build-pipeline/*
CC=clang CXX=clang++ cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX="${install_prefix}" .. 2>&1 | handle_output || handle_error
cmake --build . 2>&1 | handle_output || handle_error
cmake --install . 2>&1 | handle_output || handle_error
sed -i 's/set(ENABLE_MSan ON)/set(ENABLE_MSan OFF)/g' ../CMakeLists.txt
sed -i "s/clang-msan)/${project_name})/g" ../CMakeLists.txt
# GCC
echo "====Compiling with GCC + PVS + clang-tidy====" 2>&1 | handle_output
add_pvs_headers
if [ -f /app/project/cmake/extra/PVS-Studio.cmake ]; then sed -i "s/cmake_minimum_required(VERSION 2.8.12)/cmake_minimum_required(VERSION 3.5)/g" /app/project/cmake/extra/PVS-Studio.cmake; fi
sed -i "s/ENABLE_PVS_STUDIO OFF)/ENABLE_PVS_STUDIO ON)/g" ../CMakeLists.txt
sed -i 's/#set(CMAKE_CXX_CLANG_TIDY "clang-tidy;-checks=\*")/set(CMAKE_CXX_CLANG_TIDY "clang-tidy;-checks=\*")/g' ../CMakeLists.txt
rm -rf ../cmake-build-pipeline/*
CC=gcc CXX=g++ cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX="${install_prefix}" .. 2>&1 | handle_output || handle_error
cmake --build . 2>&1 | handle_output || handle_error
cmake --install . 2>&1 | handle_output || handle_error
sed -i "s/ENABLE_PVS_STUDIO ON)/ENABLE_PVS_STUDIO OFF)/g" ../CMakeLists.txt
popd
)
# Remove PVS things
remove_pvs_headers
exit 0
}
sanitizers() {
sanitizers_args=$1
echo "===Running with Valgrind and Sanitizers===" 2>&1 | handle_output
echo "Sanitizers args: $sanitizers_args" 2>&1 | handle_output
project_name=$(grep -oP '(?<=set\(PROJECT_NAME ).*(?=\))' ./CMakeLists.txt)
echo "====Valgrind====" 2>&1 | handle_output
valgrind --leak-check=full --show-leak-kinds=all --track-origins=yes ./bin/$project_name $sanitizers_args 2>&1 | handle_output || handle_error
echo "====Valgrind Helgrind====" 2>&1 | handle_output
valgrind --tool=helgrind ./bin/$project_name $sanitizers_args 2>&1 | handle_output || handle_error
echo "====Valgrind DRD====" 2>&1 | handle_output
valgrind --tool=drd ./bin/$project_name $sanitizers_args 2>&1 | handle_output || handle_error
echo "====UBSan====" 2>&1 | handle_output
./bin/clang-ubsan $sanitizers_args 2>&1 | handle_output || handle_error
echo "====ASan====" 2>&1 | handle_output
./bin/clang-asan $sanitizers_args 2>&1 | handle_output || handle_error
echo "====TSan====" 2>&1 | handle_output
./bin/clang-tsan $sanitizers_args 2>&1 | handle_output || handle_error
echo "====MSan====" 2>&1 | handle_output
./bin/clang-msan $sanitizers_args 2>&1 | handle_output || handle_error
}
debug() {
echo "===Running with Debug Build===" 2>&1 | handle_output
mkdir -p ./cmake-build-debug
(
pushd ./cmake-build-debug >/dev/null || exit 1
cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX="${install_prefix}" .. 2>&1 | handle_output || exit 1
cmake --build . 2>&1 | handle_output || exit 1
cmake --install . 2>&1 | handle_output || exit 1
popd
)
}
optimize() {
echo "===Running with Optimize Build===" 2>&1 | handle_output
mkdir -p ./cmake-build-release
(
pushd ./cmake-build-release >/dev/null || exit 1
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX="${install_prefix}" .. 2>&1 | handle_output || exit 1
cmake --build . 2>&1 | handle_output || exit 1
cmake --install . 2>&1 | handle_output || exit 1
popd
)
}
relwithdebinfo() {
echo "===Running with Release Debug Info===" 2>&1 | handle_output
mkdir -p ./cmake-build-relwithdebinfo
(
pushd ./cmake-build-relwithdebinfo >/dev/null || exit 1
cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX="${install_prefix}" .. 2>&1 | handle_output || exit 1
cmake --build . 2>&1 | handle_output || exit 1
cmake --install . 2>&1 | handle_output || exit 1
popd
)
}
clean() {
echo "===Cleaning===" 2>&1 | handle_output
rm -rf cmake-build-* compile.log
}
run() {
echo "===Running custom command===" 2>&1 | handle_output
run_args=$1
echo "Running command: '$run_args'" 2>&1 | handle_output
eval $run_args 2>&1 | handle_output
}
while [[ $# -gt 0 ]]; do
case $1 in
-n | --nolog | -I | --install_prefix)
shift
;;
-d | --debug-build)
debug
shift
;;
-o | --optimize-build)
optimize
shift
;;
-i | --relwithdebinfo-build)
relwithdebinfo
shift
;;
-p | --pipeline)
pipeline
shift
;;
-c | --clean)
clean
shift
;;
--s=*)
sanitizers_args="${1#*=}"
sanitizers "$sanitizers_args"
shift
;;
-h | --help)
echo "$help_message"
exit 0
;;
\?)
echo "Invalid option: -$OPTARG" 2>&1 | handle_output
exit 1
;;
:)
echo "Option -$OPTARG requires an numerical argument." 2>&1 | handle_output
exit 1
;;
*)
echo "Unknown argument: $1"
break
;;
esac
done