| 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 |
|