1 | #!/usr/bin/env bash
|
2 | #
|
3 | # Compile Python code with OPy.
|
4 | #
|
5 | # NOTE: this is roughly analogous to build/ovm-actions.sh and may be moved
|
6 | # there.
|
7 | #
|
8 | # Usage:
|
9 | # opy/build.sh <function name>
|
10 |
|
11 | set -o nounset
|
12 | set -o pipefail
|
13 | set -o errexit
|
14 |
|
15 | REPO_ROOT=$(cd "$(dirname $0)/.."; pwd)
|
16 | readonly REPO_ROOT
|
17 |
|
18 | source $REPO_ROOT/opy/common.sh # oil-python-sources
|
19 |
|
20 | md5-manifest() {
|
21 | local tree=$1
|
22 | pushd $tree
|
23 | # size and name
|
24 | find . -type f | sort | xargs stat --format '%s %n' | tee SIZES.txt
|
25 | find . -type f | sort | xargs md5sum | tee MD5.txt
|
26 | popd
|
27 | }
|
28 |
|
29 | _compile-tree() {
|
30 | local src_tree=$1
|
31 | local dest_tree=$2
|
32 | local version=$3
|
33 | shift 3
|
34 |
|
35 | rm -r -f $dest_tree
|
36 |
|
37 | #local ext=opyc
|
38 | local ext=pyc
|
39 |
|
40 | for rel_path in "$@"; do
|
41 | echo $rel_path
|
42 | local dest=${dest_tree}/${rel_path%.py}.${ext}
|
43 | mkdir -p $(dirname $dest)
|
44 |
|
45 | # TODO: Get rid of stdlib (compile) and compiler2. Now that OPy works, we
|
46 | # just want opy and ccompile.
|
47 |
|
48 | if test $version = ccompile; then
|
49 | misc/ccompile.py $src_tree/${rel_path} $dest
|
50 | elif test $version = opy; then
|
51 | $REPO_ROOT/bin/opyc compile $src_tree/${rel_path} $dest
|
52 | else
|
53 | die "bad"
|
54 | fi
|
55 | done
|
56 |
|
57 | #tree $dest_tree
|
58 | md5-manifest $dest_tree
|
59 | }
|
60 |
|
61 | # Like _compile-tree, but takes pairs on stdin.
|
62 | # Used by the Makefile.
|
63 | compile-manifest() {
|
64 | local dest_dir=$1
|
65 |
|
66 | # Python 2.7.14 on Ubuntu 17.10: ./regtest.sh verify-golden doesn't work.
|
67 | # Many diffs.
|
68 | # Our own Python 2.7.13: doesn't work.
|
69 | #local py=../_devbuild/cpython-full/python
|
70 |
|
71 | # Our own Python 2.7.12: Just one diff in hashlib.pyc!
|
72 | #local py=../_devbuild/cpython-full-2712/python
|
73 |
|
74 | local py=''
|
75 |
|
76 | while read full_src_path rel_dest_path; do
|
77 | local dest=$dest_dir/$rel_dest_path
|
78 | mkdir -p $(dirname $dest)
|
79 | log " $full_src_path"
|
80 |
|
81 | # Save space by omitting docstring.
|
82 | $py $REPO_ROOT/bin/opyc compile --emit-docstring=0 $full_src_path $dest
|
83 |
|
84 | local rel_py_path=${rel_dest_path%.pyc}.py # .pyc -> py
|
85 |
|
86 | # .pyc manifest to include in zip files
|
87 | echo $dest $rel_dest_path
|
88 | echo $full_src_path $rel_py_path
|
89 | done
|
90 | }
|
91 |
|
92 | # TODO: This should be for unit tests only. Probably don't need "mains".
|
93 | #
|
94 | # It overlaps with the normal build. This is like build/oil-manifest.txt, but
|
95 | # it's missing some stuff like the help. The Makefile rule for
|
96 | # _build/oil/bytecode.zip calls actions.sh files-manifest.
|
97 | #
|
98 | # Instead of printing .pyc, modify build/dynamic_deps.py to print _tmp/oil/*.pyc !
|
99 |
|
100 | _fill-oil-tree() {
|
101 | local dir=${1:-_tmp/repo-with-opy}
|
102 |
|
103 | if test -d ../_devbuild/help; then # doesn't exist in CI
|
104 | mkdir -p $dir/_devbuild/help
|
105 | # For help text.
|
106 | cp -v ../_devbuild/help/* $dir/_devbuild/help
|
107 | fi
|
108 |
|
109 | cp -v ../asdl/*.asdl $dir/asdl
|
110 | ln -v -s -f $PWD/../{libc,fastlex}.so $dir
|
111 | ln -v -s -f $PWD/../oil-version.txt $dir
|
112 |
|
113 | # OPy needs this for the grammar pickle? Maybe just copy it.
|
114 | ln -v -s -f --no-target-directory $PWD/../_build $dir/_build
|
115 |
|
116 | # Running core/process_test.py depends on this existing!
|
117 | mkdir -v -p $dir/_tmp
|
118 |
|
119 | local stub=$dir/bin/osh-byterun
|
120 | cat >$stub <<'EOF'
|
121 | #!/bin/bash
|
122 | readonly THIS_DIR=$(cd $(dirname $0) && pwd)
|
123 | exec python $THIS_DIR/opy_.pyc opyc run $THIS_DIR/oil.pyc osh "$@"
|
124 | EOF
|
125 | chmod +x $stub
|
126 |
|
127 | #make-mains $dir
|
128 | }
|
129 |
|
130 | # Compile with both compile() and OPy.
|
131 | # TODO:
|
132 | # - What about the standard library? The whole app bundle should be compiled
|
133 | # with OPy.
|
134 | oil-repo() {
|
135 | local files=( $(oil-python-sources $REPO_ROOT) ) # array
|
136 |
|
137 | _compile-tree $REPO_ROOT _tmp/repo-with-cpython/ ccompile "${files[@]}"
|
138 | _compile-tree $REPO_ROOT _tmp/repo-with-opy/ opy "${files[@]}"
|
139 |
|
140 | _fill-oil-tree _tmp/repo-with-cpython
|
141 | _fill-oil-tree _tmp/repo-with-opy
|
142 | }
|
143 |
|
144 | _oil-bin-manifest() {
|
145 | # NOTE: These need to be made unique. build/make_zip.py, but our shell
|
146 | # alias doesn't.
|
147 | # For some reason sys.modules has different modules with the same __file__.
|
148 |
|
149 | { build/ovm-actions.sh runpy-py-to-compile
|
150 | build/ovm-actions.sh py-to-compile '.' 'bin.oil'
|
151 | } | sort | uniq
|
152 | }
|
153 |
|
154 | oil-bin() {
|
155 | pushd $REPO_ROOT >/dev/null
|
156 | _oil-bin-manifest | compile-manifest _tmp/oil-with-opy
|
157 | popd >/dev/null
|
158 | }
|
159 |
|
160 | _opy-bin-manifest() {
|
161 | build/ovm-actions.sh py-to-compile '.' 'bin.opy_'
|
162 | }
|
163 |
|
164 | opy-bin() {
|
165 | pushd .. >/dev/null
|
166 | _opy-bin-manifest | compile-manifest _tmp/opy-with-opy
|
167 | popd >/dev/null
|
168 | }
|
169 |
|
170 | astgen() {
|
171 | tools/astgen.py tools/ast.txt > compiler2/ast.py
|
172 | }
|
173 |
|
174 | "$@"
|
175 |
|