~andyc/oil

c06036b648e0a5cecdfa1efee08c45340136efd4 — Andy Chu a month ago 809e9ae
[build] Ninja runs mycpp examples in test and benchmark mode.

Need to generalize it more.
6 files changed, 124 insertions(+), 50 deletions(-)

A mycpp/common.sh
M mycpp/configure.py
M mycpp/harness.sh
M mycpp/ninja.sh
M mycpp/run.sh
A mycpp/steps.sh
A mycpp/common.sh => mycpp/common.sh +15 -0
@@ 0,0 1,15 @@
#
# Common functions
#

# Include guard.
test -n "${__MYCPP_COMMON_SH:-}" && return
readonly __MYCPP_COMMON_SH=1

readonly THIS_DIR=$(cd $(dirname $0) && pwd)
readonly REPO_ROOT=$(cd $THIS_DIR/.. && pwd)

time-tsv() {
  $REPO_ROOT/benchmarks/time_.py --tsv "$@"
}


M mycpp/configure.py => mycpp/configure.py +38 -43
@@ 2,40 2,32 @@
"""
configure.py

Layout:
Generates a Ninja file which uses this layout.

examples/
  cgi.py
  containers.py

_gen/
  cgi.cc
  containers.cc
  (and _raw.cc generated by shell; not visible to Ninja)
_ninja/
  tasks/        # *.txt and *.task.txt for .wwz
    typecheck/  # optionally run

  - change this to _translate?
    # optionally logged?
    translate/
    compile/

_bin/
  cgi.{gc_debug,asan,opt}
  containers.{gc_debug,asan,opt}
    test/
      python/
      cpp/
    benchmark/
      python/
      cpp/

  - change this to _build?  Then you'll have build logs too.

_test/
  cgi.{gc_debug,asan,opt}.task.txt   # status, elapsed time, rusage()
  cgi.{gc_debug,asan,opt}.log        # stdout an stderr

_benchmark/
  cgi.{gc_debug,asan,opt}.task.txt   # status, elapsed time, rusage()
  cgi.{gc_debug,asan,opt}.log        # stdout an stderr

  For 'opt', this is a benchmark.  For gc_debug and asan, it's really a stress
  test.
  gen/    # source
  bin/    # binaries

Also:

- TSV summary of all task.txt
  - test and benchmark.  And maybe translate/compile
- .wwz archive of all the logs.
- Turn it into HTML and link to logs.  Basically just like Toil does.



@@ 76,36 68,39 @@ def main(argv):
         command='./run.sh ninja-compile $variant $in $out',
         description='compile $variant $in $out')
  n.newline()
  n.rule('task',
         command='./steps.sh task $in $out $log_out',
         description='task $in $out $log_out')
  n.newline()

  #examples = ['cgi', 'containers']
  examples = ['cgi']

  # TODO:
  # _ninja/
  #   logs/  # side effects
  #     typecheck/  # optional?
  #     translate/
  #     compile/
  #     test/
  #     benchmark/
  #   tasks/  # these are proper outputs, at least for test and benchmark?
  #     typecheck/  # optional?
  #     translate/
  #     compile/
  #     test/
  #     benchmark/
  #
  #   gen/    # source
  #   bin/    # binaries

  examples = ['cgi', 'containers']
  for ex in examples:
    n.build('_ninja/gen/%s.cc' % ex, 'translate', 'examples/%s.py' % ex)
    n.newline()

    # TODO: Can also parameterize by CXX: Clang or GCC.
    for variant in ['gc_debug', 'asan', 'opt']:
      n.build('_ninja/bin/%s.$variant' % ex, 'compile', '_ninja/gen/%s.cc' % ex,
      n.build('_ninja/bin/%s.$variant' % ex,
              'compile',
              '_ninja/gen/%s.cc' % ex,
              variables=[('variant', variant)])
      n.newline()

      # Run the binary in two ways
      for task in ['test', 'benchmark']:
        n.build('_ninja/tasks/%s/%s.$variant.task.txt' % (task, ex),
                'task',
                '_ninja/bin/%s.$variant' % ex,
                variables=[
                  ('variant', variant),
                  # Why do I need to expand variant here?  It's not defined
                  # yet.
                  ('log_out', '_ninja/tasks/%s/%s.%s.log.txt' % (task, ex, variant)),
                ])
        n.newline()


if __name__ == '__main__':
  try:

M mycpp/harness.sh => mycpp/harness.sh +2 -0
@@ 1,5 1,7 @@
# harness.sh: Allow customization of compile/build/run for each example.

source common.sh  # time-tsv

EXAMPLES=( $(cd examples && echo *.py) )
EXAMPLES=( "${EXAMPLES[@]//.py/}" )


M mycpp/ninja.sh => mycpp/ninja.sh +19 -1
@@ 7,8 7,12 @@ set -o nounset
set -o pipefail
set -o errexit

config() {
  ./configure.py
  cat build.ninja
}

all() {
  mkdir --verbose -p _ninja/{bin,gen}
  ./configure.py
  ninja
}


@@ 17,4 21,18 @@ clean() {
  rm --verbose -r -f _ninja
}

loop() {
  clean

  set +o errexit
  all
  set -o errexit

  echo

  # Borrowed from benchmark-all
  echo $'status\telapsed_secs\tuser_secs\tsys_secs\tmax_rss_KiB\tbin\ttask_out'
  cat _ninja/tasks/*/*.task.txt
}

"$@"

M mycpp/run.sh => mycpp/run.sh +1 -6
@@ 41,8 41,7 @@ set -o nounset
set -o pipefail
set -o errexit

readonly THIS_DIR=$(cd $(dirname $0) && pwd)
readonly REPO_ROOT=$(cd $THIS_DIR/.. && pwd)
source common.sh  # THIS_DIR and REPO_ROOT

readonly MYPY_REPO=${MYPY_REPO:-~/git/languages/mypy}



@@ 58,10 57,6 @@ export ASAN_SYMBOLIZER_PATH="$REPO_ROOT/$CLANG_DIR_RELATIVE/bin/llvm-symbolizer"

readonly DBG_FLAGS='-O0 -g'

time-tsv() {
  $REPO_ROOT/benchmarks/time_.py --tsv "$@"
}

create-venv() {
  local dir=_tmp/mycpp-venv
  #python3.6 -m venv $dir

A mycpp/steps.sh => mycpp/steps.sh +49 -0
@@ 0,0 1,49 @@
#!/usr/bin/env bash
#
# Build steps invoked by Ninja.
#
# Usage:
#   ./steps.sh <function name>
#
# Naming Convention:
#
#   ./configure.py - generates build.ninja
#   build.ninja
#   ninja.sh - wrapper for 'clean' and 'all'.  Invokes Ninja.
#   steps.sh - invoked BY ninja.
#   _ninja/ - tree
#
# TODO: build/actions.sh should be renamed build/steps.sh?  "actions" implies a
# side effect, where as "steps" largely know their outputs an outputs largely

set -o nounset
set -o pipefail
set -o errexit

source common.sh

# TODO: Move ninja-{translate,compile} here


task() {
  local bin=$1  # Run this
  local task_out=$2  # task file
  local log_out=$3

  case $bin in
    _ninja/bin/*.asan)
      # copied from run.sh and build/mycpp.sh
      export ASAN_OPTIONS='detect_leaks=0'
      ;;
  esac

  case $task_out in
    _ninja/tasks/benchmark/*)
      export BENCHMARK=1
      ;;
  esac

  time-tsv -o $task_out --rusage --field $bin --field $task_out -- $bin >$log_out 2>&1
}

"$@"