forked from oils-for-unix/oils
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathovm-compile.sh
executable file
·434 lines (370 loc) · 10.9 KB
/
ovm-compile.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
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
#!/usr/bin/env bash
#
# Compile OVM tarball.
#
# Usage:
# build/ovm-compile.sh <function name>
set -o nounset
set -o pipefail
set -o errexit
shopt -s strict:all 2>/dev/null || true # dogfood for OSH
REPO_ROOT=$(cd $(dirname $0)/..; pwd)
readonly REPO_ROOT
source build/common.sh
source-detected-config-or-die() {
if ! source _build/detected-config.sh; then
# Make this error stand out.
echo
echo "FATAL: can't find _build/detected-config.h. Run './configure'"
echo
exit 1
fi
}
# NOTES on trying to delete certain modules:
#
# _warnings.c: There weren't that many; it probably could be deleted.
# bufferobject.c: the types.py module uses it.
# Python-ast.h: pythonrun.c uses it in several places (mod_ty), and a lot of
# stuff uses pythonrun.c.
# pythonrun.c: lots interpreter flags and interpreter initialization caused
# link errors.
# pyctype.c: Tables needed for many string operations.
# getargs.c: needed for Python-C API, e.g. PyArg_ParseTuple.
# dtoa.c: not tried, but I assume that %.3f for 'time' uses it.
readonly OVM_PYTHON_OBJS='
Python/_warnings.c
Python/bltinmodule.c
Python/ceval.c
Python/errors.c
Python/getargs.c
Python/getcompiler.c
Python/getplatform.c
Python/getversion.c
Python/import.c
Python/marshal.c
Python/modsupport.c
Python/mystrtoul.c
Python/mysnprintf.c
Python/pyarena.c
Python/pyctype.c
Python/pyfpe.c
Python/pystate.c
Python/pythonrun.c
Python/random.c
Python/structmember.c
Python/sysmodule.c
Python/traceback.c
Python/pystrtod.c
Python/dtoa.c
Python/pymath.c
'
# NOTE: pystrtod.c needs some floating point functions in pymath.c
OBJECT_OBJS='
Objects/abstract.c
Objects/boolobject.c
Objects/bufferobject.c
Objects/bytes_methods.c
Objects/capsule.c
Objects/cellobject.c
Objects/classobject.c
Objects/cobject.c
Objects/codeobject.c
Objects/descrobject.c
Objects/enumobject.c
Objects/exceptions.c
Objects/genobject.c
Objects/fileobject.c
Objects/floatobject.c
Objects/frameobject.c
Objects/funcobject.c
Objects/intobject.c
Objects/iterobject.c
Objects/listobject.c
Objects/longobject.c
Objects/dictobject.c
Objects/methodobject.c
Objects/moduleobject.c
Objects/object.c
Objects/obmalloc.c
Objects/rangeobject.c
Objects/setobject.c
Objects/sliceobject.c
Objects/stringobject.c
Objects/structseq.c
Objects/tupleobject.c
Objects/typeobject.c
Objects/weakrefobject.c
'
# Non-standard lib stuff.
MODULE_OBJS='
Modules/main.c
Modules/gcmodule.c
'
# The stuff in Modules/Setup.dist, signalmodule.c. NOTE: In Python,
# signalmodule.c is specified in Modules/Setup.config, which comes from
# 'configure' output.
MODOBJS='
Modules/errnomodule.c
Modules/pwdmodule.c
Modules/_weakref.c
Modules/zipimport.c
Modules/signalmodule.c
'
# Parser/myreadline.c is needed for raw_input() to work. There is a dependency
# from Python/bltinmodule.c to it.
OVM_LIBRARY_OBJS="
Modules/getbuildinfo.c
Parser/myreadline.c
$OBJECT_OBJS
$OVM_PYTHON_OBJS
$MODULE_OBJS
$MODOBJS
"
readonly EMPTY_STR='""'
# Stub out a few variables
readonly PREPROC_FLAGS=(
-D OVM_MAIN \
-D PYTHONPATH="$EMPTY_STR" \
-D VERSION="$EMPTY_STR" \
-D VPATH="$EMPTY_STR" \
-D Py_BUILD_CORE \
# Python already has support for disabling complex numbers!
-D WITHOUT_COMPLEX
)
# NOTE: build/oil-defs is hard-coded to the oil.ovm app. We're abandoning
# hello.ovm and opy.ovm for now, but those can easily be added later. We
# haven't mangled the CPython source!
readonly INCLUDE_PATHS=(
-I . # for pyconfig.h
-I .. # for _gen/frontend/id_kind_asdl_c.h etc.
-I Include
-I ../build/oil-defs
-I ../py-yajl
# Note: This depends on build/py.sh yajl-release
-I ../py-yajl/yajl/yajl-2.1.1/include
)
readonly CC=${CC:-cc} # cc should be on POSIX systems
# BASE_CFLAGS is copied by observation from what configure.ac does on my Ubuntu
# 16.04 system. Then we check if it works on Alpine Linux too.
# "Python violates C99 rules, by casting between incompatible pointer types.
# GCC may generate bad code as a result of that, so use -fno-strict-aliasing if
# supported."
# - gcc 4.x and Clang need -fwrapv
# TODO:
# - -DNDEBUG is also passed. That turns off asserts. Do we want that?
# - We should auto-detect the flags in configure, or simplify the source so it
# isn't necessary. Python's configure.ac sometimes does it by compiling a test
# file; at other times it does it by grepping $CC --help.
# pyext/fanos.c needs -std=c99
BASE_CFLAGS='-fno-strict-aliasing -fwrapv -Wall -Wstrict-prototypes -std=c99'
# These flags are disabled for OS X. I would have thought it would work in
# Clang? It works with both GCC and Clang on Linux.
# https://stackoverflow.com/questions/6687630/how-to-remove-unused-c-c-symbols-with-gcc-and-ld
#BASE_CFLAGS="$BASE_CFLAGS -fdata-sections -ffunction-sections"
# Needed after cpython-defs filtering.
BASE_CFLAGS="$BASE_CFLAGS -Wno-unused-variable -Wno-unused-function"
readonly BASE_CFLAGS
BASE_LDFLAGS=''
# Disabled for OS X
# BASE_LDFLAGS='-Wl,--gc-sections'
# The user should be able to customize CFLAGS, but it shouldn't disable what's
# in BASE_CFLAGS.
readonly CFLAGS=${CFLAGS:-}
readonly LDFLAGS=${LDFLAGS:-}
build() {
local out=${1:-$PY27/ovm2}
local module_init=${2:-$PY27/Modules/config.c}
local main_name=${3:-_tmp/hello/main_name.c}
local c_module_srcs=${4:-_tmp/hello/c-module-srcs.txt}
shift 4
local abs_out=$PWD/$out
local abs_module_init=$PWD/$module_init
local abs_main_name=$PWD/$main_name
local abs_c_module_srcs=$PWD/$c_module_srcs
#echo $OVM_LIBRARY_OBJS
# HAVE_READLINE defined in detected-config.sh.
source-detected-config-or-die
pushd $PY27
local readline_flags=''
if [[ "$HAVE_READLINE" -eq 1 ]]; then
# Readline interface for tokenizer.c and [raw_]input() in bltinmodule.c.
# For now, we are using raw_input() for the REPL. TODO: Parameterize this!
# We should create a special no_readline_raw_input().
c_module_src_list=$(cat $abs_c_module_srcs)
if [[ -n "$READLINE_DIR" ]]; then
readline_flags+="-L $READLINE_DIR/lib -I $READLINE_DIR/include "
fi
# NOTE: pyconfig.h has HAVE_LIBREADLINE but doesn't appear to use it?
readline_flags+="-l readline -D HAVE_READLINE"
else
# don't fail
c_module_src_list=$(grep -E -v '/readline.c|/line_input.c' $abs_c_module_srcs || true)
fi
# $PREFIX comes from ./configure and defaults to /usr/local.
# $EXEC_PREFIX is a GNU thing and used in getpath.c. Could probably get rid
# of it.
time $CC \
${BASE_CFLAGS} \
${CFLAGS} \
"${INCLUDE_PATHS[@]}" \
"${PREPROC_FLAGS[@]}" \
-D PREFIX="\"$PREFIX\"" \
-D EXEC_PREFIX="\"$PREFIX\"" \
-o $abs_out \
$OVM_LIBRARY_OBJS \
$abs_module_init \
$abs_main_name \
$c_module_src_list \
Modules/ovm.c \
-l m \
${BASE_LDFLAGS} \
${LDFLAGS} \
$readline_flags \
"$@"
# NOTE:
# -l readline -l termcap -- for Python readline. Hm it builds without -l
# termcap.
# -l z WOULD be needed for zlibmodule.c, but we don't need it because our zip
# file has no compression -- see build/make_zip.py with ZIP_STORED.
# zipimport works fine without this.
}
# build the optimized one. Makefile uses -O3.
# Clang -O2 is 1.37 MB. 18 seconds to compile.
# -m32 is 1.12 MB. But I probably have to redefine a few things because
# there are more warnings.
# -O3 is 1.40 MB.
# GCC -O2 is 1.35 MB. 21 seconds to compile.
build-dbg() {
build "$@" -O0 -g -D OVM_DEBUG
}
# This will be stripped later.
build-opt() {
# frame pointer for perf. Otherwise stack traces are messed up!
# http://www.brendangregg.com/FlameGraphs/cpuflamegraphs.html#C But why
# isn't debuginfo enough? Because it's a recursive function?
# Does this make things slower? Do I need a "perf" build?
build "$@" -O3 -fno-omit-frame-pointer
}
#
# Source Release (uses same files
#
add-py27() {
xargs -I {} -- echo $PY27/{}
}
python-sources() {
echo "$OVM_LIBRARY_OBJS" | add-py27
}
_headers() {
local c_module_srcs=${1:-_tmp/hello/c-module-srcs.txt}
local abs_c_module_srcs=$PWD/$c_module_srcs
cd $PY27
# -MM: no system headers
gcc \
"${INCLUDE_PATHS[@]}" \
"${PREPROC_FLAGS[@]}" \
-MM $OVM_LIBRARY_OBJS \
Modules/ovm.c \
$(cat $abs_c_module_srcs)
}
# NOTE: 91 headers in Include, but only 81 referenced here. So it's worth it.
# These are probably for the parser.
#
# NOTE: We also should get rid of asdl.h and so forth.
python-headers() {
local c_module_srcs=$1
# 1. -MM outputs Makefile fragments, so egrep turns those into proper lines.
#
# 2. The user should generated detected-config.h, so remove it.
#
# 3. # gcc outputs paths like
# Python-2.7.13/Python/../Objects/stringlib/stringdefs.h
# but 'Python/..' causes problems for tar.
#
# NOTE: need .def for build/oil-defs.
_headers $c_module_srcs \
| egrep --only-matching '[^ ]+\.(h|def)' \
| grep -v '_build/detected-config.h' \
| sed 's|^Python/../||' \
| sort | uniq | add-py27
}
make-tar() {
local app_name=${1:-hello}
local bytecode_zip=${2:-bytecode-cpython.zip}
local out=${3:-_release/hello.tar}
local version_file
case $app_name in
oil)
version_file=oil-version.txt
;;
hello)
version_file=build/testdata/hello-version.txt
;;
*)
die "Unknown app $app_name"
exit 1
;;
esac
local version=$(head -n 1 $version_file)
echo "Creating $app_name version $version"
local c_module_srcs=_build/$app_name/c-module-srcs.txt
# Add oil-0.0.0/ to the beginning of every path.
local sed_expr="s,^,${app_name}-${version}/,"
# Differences between tarball and repo:
#
# - build/portable-rules.mk is intentionally not included in the release tarball.
# The Makefile can and should operate without it.
#
# - We include intermediate files like c-module-srcs.txt, so we don't have to
# ship tools dynamic_deps.py. The end-user build shouldn't depend on Python.
# Note: python-headers runs gcc -M, including pyconfig.h and
# _build/detected-config.h.
tar --create --transform "$sed_expr" --file $out \
LICENSE.txt \
INSTALL.txt \
configure \
install \
uninstall \
Makefile \
doc/osh.1 \
build/ovm-compile.sh \
build/ovm-actions.sh \
build/clean.sh \
build/common.sh \
build/detect-*.c \
_build/$app_name/$bytecode_zip \
_build/$app_name/*.c \
py-yajl/yajl/COPYING \
$PY27/LICENSE \
$PY27/Modules/ovm.c \
$c_module_srcs \
$(cat $c_module_srcs | add-py27) \
$(python-headers $c_module_srcs) \
$(python-sources)
ls -l $out
}
# 123K lines.
# Excluding MODOBJS, it's 104K lines.
#
# Biggest: posixmodule,unicodeobject,typeobject,ceval.
#
# Remove tmpnam from posixmodule, other cruft.
#
# Big ones to rid of: unicodeobject.c, import.c
# codecs and codecsmodule? There is some non-unicode stuff there though.
#
# Probably need unicode for compatibility with modules and web frameworks
# especially.
count-c-lines() {
pushd $PY27
wc -l $OVM_LIBRARY_OBJS | sort -n
# 90 files.
# NOTE: To count headers, use the tar file.
echo
echo 'Files:'
{ for i in $OVM_LIBRARY_OBJS; do
echo $i
done
} | wc -l
popd
}
"$@"