OILS / build / ninja-rules-cpp.sh View on Github | oilshell.org

370 lines, 221 significant
1#!/usr/bin/env bash
2#
3# Actions invoked by build.ninja, which is generated by ./NINJA-config.sh.
4#
5# It's distributed with the tarball and invoked by _build/oils.sh, so
6# it's written in a /bin/sh style. But we're not using /bin/sh yet.
7#
8# And some non-Ninja wrappers.
9#
10# Usage:
11# build/ninja-rules-cpp.sh <function name>
12#
13# Env variables:
14# BASE_CXXFLAGS= default flags passed to all compiler invocations
15# CXXFLAGS= additional flags
16# OILS_CXX_VERBOSE=1 show compiler command lines
17# TIME_TSV_OUT=file compile_one and link output rows to this TSV file
18
19set -o nounset
20set -o errexit
21# For /bin/sh portability
22#eval 'set -o pipefail'
23
24REPO_ROOT=$(cd "$(dirname $0)/.."; pwd)
25
26. build/common.sh # for $BASE_CXXFLAGS
27. build/dev-shell.sh # python2 in $PATH
28
29# for HAVE_READLINE, READLINE_DIR, and STRIP_FLAGS
30if ! . _build/detected-config.sh; then
31 die "Can't find _build/detected-config.sh. Run './configure'"
32fi
33
34line_count() {
35 local out=$1
36 shift # rest are inputs
37 wc -l "$@" | sort -n | tee $out
38}
39
40#
41# Mutable GLOBALS
42#
43
44cxx='' # compiler
45flags='' # compile flags
46link_flags='' # link flags
47
48#
49# Functions to set them
50#
51
52setglobal_cxx() {
53 local compiler=$1
54
55 case $compiler in
56 (clang) cxx=$CLANGXX ;;
57 # Note: we could get rid of this "alias", and use 'c++' everywhere
58 (cxx) cxx='c++' ;;
59
60 # e.g. could be cosmoc++
61 (*) cxx=$compiler ;;
62 esac
63}
64
65setglobal_compile_flags() {
66 ### Set flags based on $variant $more_cxx_flags and $dotd
67
68 local variant=$1
69 local more_cxx_flags=$2
70 local dotd=${3:-}
71
72 # flags from Ninja/shell respected
73 flags="$BASE_CXXFLAGS -I $REPO_ROOT $more_cxx_flags"
74
75 # Flags from env
76 # Similar to
77 # - GNU make - https://www.gnu.org/software/make/manual/html_node/Implicit-Variables.html
78 # CXXFLAGS "Extra flags to give to the C++ compiler"
79 # - CMake - https://cmake.org/cmake/help/latest/envvar/CXXFLAGS.html
80 # "Add default compilation flags to be used when compiling CXX (C++) files."
81
82 local env_flags=${CXXFLAGS:-}
83 if test -n "$env_flags"; then
84 flags="$flags $env_flags"
85 fi
86
87 if test -n "$READLINE_DIR"; then
88 flags="$flags -I${READLINE_DIR}/include"
89 fi
90
91 case $variant in
92 *+bumpleak|*+bumproot)
93 ;;
94 *+bigint)
95 flags="$flags -D MARK_SWEEP -D BIGINT"
96 ;;
97 *)
98 flags="$flags -D MARK_SWEEP"
99 ;;
100 esac
101
102 # First half of variant: what affects ALL translation units
103
104 case $variant in
105 dbg*)
106 flags="$flags -O0 -g"
107 ;;
108
109 asan*)
110 # CLEAN_PROCESS_EXIT avoids spurious memory leaks
111 flags="$flags -O0 -g -fsanitize=address -D CLEAN_PROCESS_EXIT"
112 ;;
113
114 tsan*)
115 flags="$flags -O0 -g -fsanitize=thread"
116 ;;
117
118 ubsan*)
119 # Extra flag to make it fatal
120 # https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html
121
122 flags="$flags -O0 -g -fsanitize=undefined -fno-sanitize-recover=null"
123 ;;
124
125 opt*)
126 flags="$flags -O2 -g -D OPTIMIZED"
127 ;;
128
129 coverage*)
130 # source-based coverage is more precise than say sanitizer-based
131 # https://clang.llvm.org/docs/SourceBasedCodeCoverage.html
132 flags="$flags -O0 -g -fprofile-instr-generate -fcoverage-mapping"
133 ;;
134
135 uftrace*)
136 # -O0 creates a A LOT more data. But sometimes we want to see the
137 # structure of the code.
138 # NewStr(), OverAllocatedStr(), StrFromC() etc. are not inlined
139 # Ditto vector::size(), std::forward, len(), etc.
140
141 local opt='-O0'
142 #local opt='-O2'
143 flags="$flags $opt -g -pg"
144 ;;
145
146 (*)
147 die "Invalid variant $variant"
148 ;;
149 esac
150
151 # for cxx-dbg32, cxx-opt32+bumpleak, etc.
152 case $variant in
153 *32*)
154 flags="$flags -m32"
155 ;;
156 esac
157
158 # OPTIONAL second half of variant: for the application
159
160 case $variant in
161 *+gcalways)
162 flags="$flags -D GC_ALWAYS"
163 ;;
164
165 *+tcmalloc)
166 flags="$flags -D TCMALLOC"
167 ;;
168
169 *+bumpleak)
170 flags="$flags -D BUMP_LEAK"
171 ;;
172 *+bumproot)
173 flags="$flags -D BUMP_LEAK -D BUMP_ROOT"
174 ;;
175
176 *+bumpsmall)
177 # the pool allocator should approximate opt+bumpsmall (which doesn't support GC)
178 flags="$flags -D BUMP_ROOT -D BUMP_SMALL -D NO_POOL_ALLOC"
179 ;;
180
181 *+nopool)
182 flags="$flags -D NO_POOL_ALLOC"
183 ;;
184 esac
185
186 # needed to strip unused symbols
187 # https://stackoverflow.com/questions/6687630/how-to-remove-unused-c-c-symbols-with-gcc-and-ld
188
189 # Note: -ftlo doesn't do anything for size?
190
191 flags="$flags -fdata-sections -ffunction-sections"
192
193 # https://ninja-build.org/manual.html#ref_headers
194 if test -n "$dotd"; then
195 flags="$flags -MD -MF $dotd"
196 fi
197}
198
199setglobal_link_flags() {
200 local variant=$1
201
202 case $variant in
203 # Must REPEAT these flags, otherwise we lose sanitizers / coverage
204 asan*)
205 link_flags='-fsanitize=address'
206 ;;
207
208 tcmalloc)
209 # Need to tell the dynamic loader where to find tcmalloc
210 link_flags='-ltcmalloc -Wl,-rpath,/usr/local/lib'
211 ;;
212
213 tsan)
214 link_flags='-fsanitize=thread'
215 ;;
216 ubsan*)
217 link_flags='-fsanitize=undefined'
218 ;;
219 coverage*)
220 link_flags='-fprofile-instr-generate -fcoverage-mapping'
221 ;;
222 esac
223
224 case $variant in
225 # TODO: 32-bit variants can't handle -l readline right now.
226 *32*)
227 link_flags="$link_flags -m32"
228 ;;
229
230 *)
231 if test "$HAVE_READLINE" = 1; then
232 link_flags="$link_flags -lreadline"
233 fi
234 if test -n "$READLINE_DIR"; then
235 link_flags="$link_flags -L${READLINE_DIR}/lib"
236 fi
237 ;;
238 esac
239
240 if test -n "${STRIP_FLAGS:-}"; then
241 link_flags="$link_flags -Wl,$STRIP_FLAGS"
242 fi
243}
244
245compile_one() {
246 ### Compile one translation unit. Invoked by build.ninja
247
248 local compiler=$1
249 local variant=$2
250 local more_cxx_flags=$3
251 local in=$4
252 local out=$5
253 local dotd=${6:-} # optional .d file
254
255 setglobal_compile_flags "$variant" "$more_cxx_flags" "$dotd"
256
257 case $out in
258 (_build/preprocessed/*)
259 flags="$flags -E"
260 ;;
261
262 # DISABLE spew for mycpp-generated code. mycpp/pea could flag this at the
263 # PYTHON level, rather than doing it at the C++ level.
264 (_build/obj/*/_gen/bin/oils_for_unix.mycpp.o)
265 flags="$flags -Wno-unused-variable -Wno-unused-but-set-variable"
266 ;;
267 esac
268
269 # TODO: exactly when is -fPIC needed? Clang needs it sometimes?
270 if test $compiler = 'clang' && test $variant != 'opt'; then
271 flags="$flags -fPIC"
272 fi
273
274 # this flag is only valid in Clang, doesn't work in continuous build
275 if test "$compiler" = 'clang'; then
276 flags="$flags -ferror-limit=10"
277 fi
278
279 setglobal_cxx $compiler
280
281 if test -n "${OILS_CXX_VERBOSE:-}"; then
282 echo '__' "$cxx" $flags -o "$out" -c "$in" >&2
283 fi
284
285 # Not using arrays because this is POSIX shell
286 local prefix=''
287 if test -n "${TIME_TSV_OUT:-}"; then
288 prefix="benchmarks/time_.py --tsv --out $TIME_TSV_OUT --append --rusage --field compile_one --field $out --"
289 fi
290
291 $prefix "$cxx" $flags -o "$out" -c "$in"
292}
293
294link() {
295 ### Link a binary. Invoked by build.ninja
296
297 local compiler=$1
298 local variant=$2
299 local more_link_flags=$3
300 local out=$4
301 shift 4
302 # rest are inputs
303
304 setglobal_link_flags $variant
305
306 setglobal_cxx $compiler
307
308 local prefix=''
309 if test -n "${TIME_TSV_OUT:-}"; then
310 prefix="benchmarks/time_.py --tsv --out $TIME_TSV_OUT --append --rusage --field link --field $out --"
311 fi
312
313 if test -n "${OILS_CXX_VERBOSE:-}"; then
314 echo "__ $prefix $cxx -o $out $@ $link_flags" >&2
315 fi
316 # IMPORTANT: Flags like -ltcmalloc have to come AFTER objects! Weird but
317 # true.
318 $prefix "$cxx" -o "$out" "$@" $link_flags $more_link_flags
319}
320
321compile_and_link() {
322 ### This function is no longer used; use 'compile_one' and 'link'
323
324 local compiler=$1
325 local variant=$2
326 local more_cxx_flags=$3
327 local out=$4
328 shift 4
329
330 setglobal_compile_flags "$variant" "$more_cxx_flags" "" # no dotd
331
332 setglobal_link_flags $variant
333
334 setglobal_cxx $compiler
335
336 if test -n "${OILS_CXX_VERBOSE:-}"; then
337 echo "__ $cxx -o $out $flags $@ $link_flags" >&2
338 fi
339
340 "$cxx" -o "$out" $flags "$@" $link_flags
341}
342
343strip_() {
344 ### Invoked by ninja
345
346 local in=$1
347 local stripped=$2
348 local symbols=${3:-}
349
350 strip -o $stripped $in
351
352 if test -n "$symbols"; then
353 objcopy --only-keep-debug $in $symbols
354 objcopy --add-gnu-debuglink=$symbols $stripped
355 fi
356}
357
358symlink() {
359 local dir=$1
360 local in=$2
361 local out=$3
362
363 cd $dir
364 ln -s -f -v $in $out
365}
366
367# test/cpp-unit.sh sources this
368if test $(basename $0) = 'ninja-rules-cpp.sh'; then
369 "$@"
370fi