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

367 lines, 218 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 *)
95 flags="$flags -D MARK_SWEEP"
96 ;;
97 esac
98
99 # First half of variant: what affects ALL translation units
100
101 case $variant in
102 dbg*)
103 flags="$flags -O0 -g"
104 ;;
105
106 asan*)
107 # CLEAN_PROCESS_EXIT avoids spurious memory leaks
108 flags="$flags -O0 -g -fsanitize=address -D CLEAN_PROCESS_EXIT"
109 ;;
110
111 tsan*)
112 flags="$flags -O0 -g -fsanitize=thread"
113 ;;
114
115 ubsan*)
116 # Extra flag to make it fatal
117 # https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html
118
119 flags="$flags -O0 -g -fsanitize=undefined -fno-sanitize-recover=null"
120 ;;
121
122 opt*)
123 flags="$flags -O2 -g -D OPTIMIZED"
124 ;;
125
126 coverage*)
127 # source-based coverage is more precise than say sanitizer-based
128 # https://clang.llvm.org/docs/SourceBasedCodeCoverage.html
129 flags="$flags -O0 -g -fprofile-instr-generate -fcoverage-mapping"
130 ;;
131
132 uftrace*)
133 # -O0 creates a A LOT more data. But sometimes we want to see the
134 # structure of the code.
135 # NewStr(), OverAllocatedStr(), StrFromC() etc. are not inlined
136 # Ditto vector::size(), std::forward, len(), etc.
137
138 local opt='-O0'
139 #local opt='-O2'
140 flags="$flags $opt -g -pg"
141 ;;
142
143 (*)
144 die "Invalid variant $variant"
145 ;;
146 esac
147
148 # for cxx-dbg32, cxx-opt32+bumpleak, etc.
149 case $variant in
150 *32*)
151 flags="$flags -m32"
152 ;;
153 esac
154
155 # OPTIONAL second half of variant: for the application
156
157 case $variant in
158 *+gcalways)
159 flags="$flags -D GC_ALWAYS"
160 ;;
161
162 *+tcmalloc)
163 flags="$flags -D TCMALLOC"
164 ;;
165
166 *+bumpleak)
167 flags="$flags -D BUMP_LEAK"
168 ;;
169 *+bumproot)
170 flags="$flags -D BUMP_LEAK -D BUMP_ROOT"
171 ;;
172
173 *+bumpsmall)
174 # the pool allocator should approximate opt+bumpsmall (which doesn't support GC)
175 flags="$flags -D BUMP_ROOT -D BUMP_SMALL -D NO_POOL_ALLOC"
176 ;;
177
178 *+nopool)
179 flags="$flags -D NO_POOL_ALLOC"
180 ;;
181 esac
182
183 # needed to strip unused symbols
184 # https://stackoverflow.com/questions/6687630/how-to-remove-unused-c-c-symbols-with-gcc-and-ld
185
186 # Note: -ftlo doesn't do anything for size?
187
188 flags="$flags -fdata-sections -ffunction-sections"
189
190 # https://ninja-build.org/manual.html#ref_headers
191 if test -n "$dotd"; then
192 flags="$flags -MD -MF $dotd"
193 fi
194}
195
196setglobal_link_flags() {
197 local variant=$1
198
199 case $variant in
200 # Must REPEAT these flags, otherwise we lose sanitizers / coverage
201 asan*)
202 link_flags='-fsanitize=address'
203 ;;
204
205 tcmalloc)
206 # Need to tell the dynamic loader where to find tcmalloc
207 link_flags='-ltcmalloc -Wl,-rpath,/usr/local/lib'
208 ;;
209
210 tsan)
211 link_flags='-fsanitize=thread'
212 ;;
213 ubsan*)
214 link_flags='-fsanitize=undefined'
215 ;;
216 coverage*)
217 link_flags='-fprofile-instr-generate -fcoverage-mapping'
218 ;;
219 esac
220
221 case $variant in
222 # TODO: 32-bit variants can't handle -l readline right now.
223 *32*)
224 link_flags="$link_flags -m32"
225 ;;
226
227 *)
228 if test "$HAVE_READLINE" = 1; then
229 link_flags="$link_flags -lreadline"
230 fi
231 if test -n "$READLINE_DIR"; then
232 link_flags="$link_flags -L${READLINE_DIR}/lib"
233 fi
234 ;;
235 esac
236
237 if test -n "${STRIP_FLAGS:-}"; then
238 link_flags="$link_flags -Wl,$STRIP_FLAGS"
239 fi
240}
241
242compile_one() {
243 ### Compile one translation unit. Invoked by build.ninja
244
245 local compiler=$1
246 local variant=$2
247 local more_cxx_flags=$3
248 local in=$4
249 local out=$5
250 local dotd=${6:-} # optional .d file
251
252 setglobal_compile_flags "$variant" "$more_cxx_flags" "$dotd"
253
254 case $out in
255 (_build/preprocessed/*)
256 flags="$flags -E"
257 ;;
258
259 # DISABLE spew for mycpp-generated code. mycpp/pea could flag this at the
260 # PYTHON level, rather than doing it at the C++ level.
261 (_build/obj/*/_gen/bin/oils_for_unix.mycpp.o)
262 flags="$flags -Wno-unused-variable -Wno-unused-but-set-variable"
263 ;;
264 esac
265
266 # TODO: exactly when is -fPIC needed? Clang needs it sometimes?
267 if test $compiler = 'clang' && test $variant != 'opt'; then
268 flags="$flags -fPIC"
269 fi
270
271 # this flag is only valid in Clang, doesn't work in continuous build
272 if test "$compiler" = 'clang'; then
273 flags="$flags -ferror-limit=10"
274 fi
275
276 setglobal_cxx $compiler
277
278 if test -n "${OILS_CXX_VERBOSE:-}"; then
279 echo '__' "$cxx" $flags -o "$out" -c "$in" >&2
280 fi
281
282 # Not using arrays because this is POSIX shell
283 local prefix=''
284 if test -n "${TIME_TSV_OUT:-}"; then
285 prefix="benchmarks/time_.py --tsv --out $TIME_TSV_OUT --append --rusage --field compile_one --field $out --"
286 fi
287
288 $prefix "$cxx" $flags -o "$out" -c "$in"
289}
290
291link() {
292 ### Link a binary. Invoked by build.ninja
293
294 local compiler=$1
295 local variant=$2
296 local more_link_flags=$3
297 local out=$4
298 shift 4
299 # rest are inputs
300
301 setglobal_link_flags $variant
302
303 setglobal_cxx $compiler
304
305 local prefix=''
306 if test -n "${TIME_TSV_OUT:-}"; then
307 prefix="benchmarks/time_.py --tsv --out $TIME_TSV_OUT --append --rusage --field link --field $out --"
308 fi
309
310 if test -n "${OILS_CXX_VERBOSE:-}"; then
311 echo "__ $prefix $cxx -o $out $@ $link_flags" >&2
312 fi
313 # IMPORTANT: Flags like -ltcmalloc have to come AFTER objects! Weird but
314 # true.
315 $prefix "$cxx" -o "$out" "$@" $link_flags $more_link_flags
316}
317
318compile_and_link() {
319 ### This function is no longer used; use 'compile_one' and 'link'
320
321 local compiler=$1
322 local variant=$2
323 local more_cxx_flags=$3
324 local out=$4
325 shift 4
326
327 setglobal_compile_flags "$variant" "$more_cxx_flags" "" # no dotd
328
329 setglobal_link_flags $variant
330
331 setglobal_cxx $compiler
332
333 if test -n "${OILS_CXX_VERBOSE:-}"; then
334 echo "__ $cxx -o $out $flags $@ $link_flags" >&2
335 fi
336
337 "$cxx" -o "$out" $flags "$@" $link_flags
338}
339
340strip_() {
341 ### Invoked by ninja
342
343 local in=$1
344 local stripped=$2
345 local symbols=${3:-}
346
347 strip -o $stripped $in
348
349 if test -n "$symbols"; then
350 objcopy --only-keep-debug $in $symbols
351 objcopy --add-gnu-debuglink=$symbols $stripped
352 fi
353}
354
355symlink() {
356 local dir=$1
357 local in=$2
358 local out=$3
359
360 cd $dir
361 ln -s -f -v $in $out
362}
363
364# test/cpp-unit.sh sources this
365if test $(basename $0) = 'ninja-rules-cpp.sh'; then
366 "$@"
367fi