#!/usr/bin/env bash # # Compile Python code with OPy. # # NOTE: this is roughly analogous to build/actions.sh and may be moved # there. # # Usage: # ./build.sh set -o nounset set -o pipefail set -o errexit readonly THIS_DIR=$[cd $[dirname $0] && pwd] source $THIS_DIR/common.sh source $THIS_DIR/../build/common.sh # for OIL_SYMLINKS proc md5-manifest { local tree=$1 pushd $tree # size and name find . -type f | sort | xargs stat --format '%s %n' | tee SIZES.txt find . -type f | sort | xargs md5sum | tee MD5.txt popd } proc _compile-tree { local src_tree=$1 local dest_tree=$2 local version=$3 shift 3 rm -r -f $dest_tree #local ext=opyc local ext=pyc for rel_path in [@ARGV] { echo $rel_path local dest=$(dest_tree)/$(rel_path%.py).$(ext) mkdir -p $[dirname $dest] # TODO: Get rid of stdlib (compile) and compiler2. Now that OPy works, we # just want opy and ccompile. if test $version = ccompile { misc/ccompile.py $src_tree/$(rel_path) $dest } elif test $version = opy { $THIS_DIR/../bin/opyc compile $src_tree/$(rel_path) $dest } else { die "bad" } } tree $dest_tree md5-manifest $dest_tree } # Like _compile-tree, but takes pairs on stdin. # Used by the Makefile. proc compile-manifest { local dest_dir=$1 while read full_src_path rel_dest_path { local dest=$dest_dir/$rel_dest_path mkdir -p $[dirname $dest] log " $full_src_path" $THIS_DIR/../bin/opyc compile $full_src_path $dest local rel_py_path=$(rel_dest_path%.pyc).py # .pyc -> py # .pyc manifest to include in zip files echo $dest $rel_dest_path echo $full_src_path $rel_py_path } } # UNUSED proc make-mains { local dir=$(1:-_tmp/oil-opy) # Have to use shells cripts rather than symlinks because .pyc files aren't # executable. # TODO: Use oil.ovm instead of system Python. for link in [$(OIL_SYMLINKS[@])] { do { echo '#!/bin/sh' echo "main=$link" echo 'exec python $(dirname $0)/oil.pyc $main "$@"' } >$dir/bin/$link chmod --verbose +x $dir/bin/$link } } # TODO: This should be for unit tests only. Probably don't need "mains". # # It overlaps with the normal build. This is like build/oil-manifest.txt, but # it's missing some stuff like the help. The Makefile rule for # _build/oil/bytecode.zip calls actions.sh files-manifest. # # Instead of printing .pyc, modify build/app_deps.py to print _tmp/oil/*.pyc ! proc _fill-oil-tree { local dir=$(1:-_tmp/repo-with-opy) cp -v ../osh/{osh,types}.asdl $dir/osh cp -v ../core/runtime.asdl $dir/core cp -v ../asdl/arith.asdl $dir/asdl ln -v -s -f $PWD/../{libc,fastlex}.so $dir ln -v -s -f $PWD/../oil-version.txt $dir # Needed for help text. ln -v -s -f --no-target-directory $PWD/../_build $dir/_build # Running core/process_test.py depends on this existing! mkdir -v -p $dir/_tmp local stub=$dir/bin/osh-byterun cat >$stub <<'EOF' #!/bin/bash readonly THIS_DIR=$(cd $(dirname $0) && pwd) exec python $THIS_DIR/opy_.pyc opyc run $THIS_DIR/oil.pyc osh "$@" EOF chmod +x $stub #make-mains $dir } # Compile with both compile() and OPy. # TODO: # - What about the standard library? The whole app bundle should be # compiled with OPy. # - This could be part of the Travis build. It will ensure no Python 2 # print statements sneak in. proc oil-repo { local repo_root=$[cd $THIS_DIR/.. && pwd] local files=( $(oil-python-sources $repo_root) ) # array _compile-tree $repo_root _tmp/repo-with-cpython/ ccompile $(files[@]) _compile-tree $repo_root _tmp/repo-with-opy/ opy $(files[@]) _fill-oil-tree _tmp/repo-with-cpython _fill-oil-tree _tmp/repo-with-opy } proc _oil-bin-manifest { # NOTE: These need to be made unique. build/make_zip.py, but our shell # alias doesn't. # For some reason sys.modules has different modules with the same __file__. do { build/actions.sh runpy-py-to-compile build/actions.sh py-to-compile '.' 'bin.oil' } | sort | uniq } proc oil-bin { pushd $THIS_DIR/.. >/dev/null _oil-bin-manifest | compile-manifest _tmp/oil-with-opy popd >/dev/null } proc _opy-bin-manifest { build/actions.sh py-to-compile '.' 'bin.opy_' } proc opy-bin { pushd .. >/dev/null _opy-bin-manifest | compile-manifest _tmp/opy-with-opy popd >/dev/null } @ARGV