#!/bin/sh
#
# _build/oils.sh: Generated by build/ninja_main.py
#
# For usage, run:
#
#   _build/oils.sh --help

. build/ninja-rules-cpp.sh

show_help() {
  cat <<'EOF'
Compile the oils-for-unix source into an executable.

Usage:
  _build/oils.sh FLAG* 
  _build/oils.sh --help

Flags:

  --cxx CXX [default 'cxx']
    The C++ compiler to use: 'cxx' for system compiler, 'clang', or custom
    string
  
  --variant ARG [default 'opt']
    The build variant, e.g. dbg, opt, asan, which adds compile and link flags.

  --translator ARG [default 'mycpp']
    Which bundle of translated source code to compile: mycpp, mycpp-souffle

  --suffix ARG [default '']
    Append a string like '-static' to oils-for-unix, and symlinks like osh, ysh

  --without-readline
    Don't link with GNU readline.  This overrides ./configure --without-readline

  --skip-rebuild
    If the output exists, skip the build

Env vars respected:

  OILS_PARALLEL_BUILD= [default 1]
    Set to 0 to disable parallel compilation.

  OILS_CXX_VERBOSE=    [default '']
    Set to 1 to show build details.

Compile/link flags:

  BASE_CXXFLAGS=       (defined in build/common.sh)
    Override this to disable basic flags like -fno-omit-frame-pointer

  CXXFLAGS=            [default ''] (defined in build/ninja-rules-cpp.sh)
    Space-separated list of more compiler flags

  LDFLAGS=             [default ''] (defined in build/ninja-rules-cpp.sh)
    Space-separated list of more linker flags

Compiler flags come from these sources:

  1. The $BASE_CXXFLAGS var
  2. -I $REPO_ROOT is hard-coded
  3. The build --variant, e.g. 'asan' adds -fsanitizer=address and more
  4. Flags detected by ./configure, e.g. for GNU readline
  5. The $CXXFLAGS var

Linker flags come from these sources:

  1. The build --variant, e.g. 'asan' adds -fsanitizer=address
  2. Flags detected by ./configure, like $STRIP_FLAGS and -lreadline for GNU
     readline
  3. The $LDFLAGS var

EOF
}

FLAG_cxx=cxx           # default is system compiler
FLAG_variant=opt       # default is optimized build

FLAG_translator=mycpp  # or mycpp-souffle
FLAG_suffix=''   # false

FLAG_without_readline=''
FLAG_skip_rebuild='' 

parse_flags() {
  # Note: not supporting --cxx=foo like ./configure, only --cxx foo

  while true; do
    # ${1:-} needed for set -u
    case "${1:-}" in
      '')
        break
        ;;

      -h|--help)
        show_help
        exit 0
        ;;

      --cxx)
        if test $# -eq 1; then
          die "--cxx requires an argument"
        fi
        shift
        FLAG_cxx=$1
        ;;

      --variant)
        if test $# -eq 1; then
          die "--variant requires an argument"
        fi
        shift
        FLAG_variant=$1
        ;;

      --translator)
        if test $# -eq 1; then
          die "--translator requires an argument"
        fi
        shift
        FLAG_translator=$1
        ;;

      --suffix)
        if test $# -eq 1; then
          die "--suffix requires an argument"
        fi
        shift
        FLAG_suffix=$1
        ;;

      --without-readline)
        FLAG_without_readline=true
        ;;

      --skip-rebuild)
        FLAG_skip_rebuild=true
        ;;

      *)
        die "Invalid argument '$1'"
        ;;
    esac
    shift
  done

  # legacy interface
  FLAG_cxx=${1:-$FLAG_cxx}
  FLAG_variant=${2:-$FLAG_variant}
  FLAG_translator=${3:-$FLAG_translator}
  FLAG_skip_rebuild=${4:-$FLAG_skip_rebuild}
}


OILS_PARALLEL_BUILD=${OILS_PARALLEL_BUILD:-1}

_compile_one() {
  local src=$4

  echo "CXX $src"

  # Delegate to function in build/ninja-rules-cpp.sh
  if test "${_do_fork:-}" = 1; then
    compile_one "$@" &   # we will wait later
  else
    compile_one "$@"
  fi
}
main() {
  ### Compile oils-for-unix into _bin/$compiler-$variant-sh/ (not with ninja)

  parse_flags "$@"

  # Copy into locals
  local compiler=$FLAG_cxx
  local variant=$FLAG_variant
  local translator=$FLAG_translator
  local skip_rebuild=$FLAG_skip_rebuild

  local out_name=oils-for-unix

  local out_dir
  case $translator in
    mycpp)
      out_dir=_bin/$compiler-$variant-sh
      ;;
    *)
      out_dir=_bin/$compiler-$variant-sh/$translator
      ;;
  esac
  local out_path=$out_dir/$out_name$FLAG_suffix

  echo
  echo "$0: Building $out_name: $out_path"
  echo "    PWD = $PWD"
  echo "    cxx = $compiler"
  echo "    variant = $variant"
  echo "    translator = $translator"
  echo "    suffix = $FLAG_suffix"
  if test -n "$FLAG_without_readline"; then
    echo "    without_readline = $FLAG_without_readline"
  fi
  if test -n "$skip_rebuild"; then
    echo "    skip_rebuild = $skip_rebuild"
  fi

  if test -n "$skip_rebuild" && test -f "$out_path"; then
    echo
    echo "$0: SKIPPING build because $out_path exists"
    echo
    return
  fi

  echo

  mkdir -p \
    "_bin/$compiler-$variant-sh/$translator" \
    "_build/obj/$compiler-$variant-sh/_gen/bin" \
    "_build/obj/$compiler-$variant-sh/_gen/core" \
    "_build/obj/$compiler-$variant-sh/_gen/cpp" \
    "_build/obj/$compiler-$variant-sh/_gen/data_lang" \
    "_build/obj/$compiler-$variant-sh/_gen/display" \
    "_build/obj/$compiler-$variant-sh/_gen/frontend" \
    "_build/obj/$compiler-$variant-sh/_gen/osh" \
    "_build/obj/$compiler-$variant-sh/_gen/ysh" \
    "_build/obj/$compiler-$variant-sh/cpp" \
    "_build/obj/$compiler-$variant-sh/mycpp"

  # Potentially fork this translation unit with &
  _do_fork=$OILS_PARALLEL_BUILD \
    _compile_one "$compiler" "$variant" "" \
    _gen/bin/oils_for_unix.$translator.cc "_build/obj/$compiler-$variant-sh/_gen/bin/oils_for_unix.$translator.o"
  _do_fork=  # work around bug in some versions of the dash shell

  _compile_one "$compiler" "$variant" "" \
    _gen/bin/oils_for_unix.$translator-main.cc "_build/obj/$compiler-$variant-sh/_gen/bin/oils_for_unix.$translator-main.o"

  _compile_one "$compiler" "$variant" "" \
    _gen/bin/text_files.cc "_build/obj/$compiler-$variant-sh/_gen/bin/text_files.o"

  _compile_one "$compiler" "$variant" "" \
    _gen/core/runtime.asdl.cc "_build/obj/$compiler-$variant-sh/_gen/core/runtime.asdl.o"

  _compile_one "$compiler" "$variant" "" \
    _gen/core/value.asdl.cc "_build/obj/$compiler-$variant-sh/_gen/core/value.asdl.o"

  _compile_one "$compiler" "$variant" "" \
    _gen/cpp/build_stamp.cc "_build/obj/$compiler-$variant-sh/_gen/cpp/build_stamp.o"

  _compile_one "$compiler" "$variant" "" \
    _gen/data_lang/nil8.asdl.cc "_build/obj/$compiler-$variant-sh/_gen/data_lang/nil8.asdl.o"

  _compile_one "$compiler" "$variant" "" \
    _gen/display/pretty.asdl.cc "_build/obj/$compiler-$variant-sh/_gen/display/pretty.asdl.o"

  _compile_one "$compiler" "$variant" "" \
    _gen/frontend/arg_types.cc "_build/obj/$compiler-$variant-sh/_gen/frontend/arg_types.o"

  _compile_one "$compiler" "$variant" "" \
    _gen/frontend/consts.cc "_build/obj/$compiler-$variant-sh/_gen/frontend/consts.o"

  _compile_one "$compiler" "$variant" "" \
    _gen/frontend/help_meta.cc "_build/obj/$compiler-$variant-sh/_gen/frontend/help_meta.o"

  _compile_one "$compiler" "$variant" "" \
    _gen/frontend/id_kind.asdl.cc "_build/obj/$compiler-$variant-sh/_gen/frontend/id_kind.asdl.o"

  _compile_one "$compiler" "$variant" "" \
    _gen/frontend/signal.cc "_build/obj/$compiler-$variant-sh/_gen/frontend/signal.o"

  _compile_one "$compiler" "$variant" "" \
    _gen/frontend/syntax.asdl.cc "_build/obj/$compiler-$variant-sh/_gen/frontend/syntax.asdl.o"

  _compile_one "$compiler" "$variant" "" \
    _gen/osh/arith_parse.cc "_build/obj/$compiler-$variant-sh/_gen/osh/arith_parse.o"

  _compile_one "$compiler" "$variant" "" \
    _gen/ysh/grammar_tables.cc "_build/obj/$compiler-$variant-sh/_gen/ysh/grammar_tables.o"

  _compile_one "$compiler" "$variant" "" \
    cpp/core.cc "_build/obj/$compiler-$variant-sh/cpp/core.o"

  _compile_one "$compiler" "$variant" "" \
    cpp/data_lang.cc "_build/obj/$compiler-$variant-sh/cpp/data_lang.o"

  _compile_one "$compiler" "$variant" "" \
    cpp/fanos.cc "_build/obj/$compiler-$variant-sh/cpp/fanos.o"

  _compile_one "$compiler" "$variant" "" \
    cpp/fanos_shared.c "_build/obj/$compiler-$variant-sh/cpp/fanos_shared.o"

  _compile_one "$compiler" "$variant" "" \
    cpp/frontend_flag_spec.cc "_build/obj/$compiler-$variant-sh/cpp/frontend_flag_spec.o"

  _compile_one "$compiler" "$variant" "" \
    cpp/frontend_match.cc "_build/obj/$compiler-$variant-sh/cpp/frontend_match.o"

  _compile_one "$compiler" "$variant" "" \
    cpp/frontend_pyreadline.cc "_build/obj/$compiler-$variant-sh/cpp/frontend_pyreadline.o"

  _compile_one "$compiler" "$variant" "" \
    cpp/libc.cc "_build/obj/$compiler-$variant-sh/cpp/libc.o"

  _compile_one "$compiler" "$variant" "" \
    cpp/osh.cc "_build/obj/$compiler-$variant-sh/cpp/osh.o"

  _compile_one "$compiler" "$variant" "" \
    cpp/osh_tdop.cc "_build/obj/$compiler-$variant-sh/cpp/osh_tdop.o"

  _compile_one "$compiler" "$variant" "" \
    cpp/pgen2.cc "_build/obj/$compiler-$variant-sh/cpp/pgen2.o"

  _compile_one "$compiler" "$variant" "" \
    cpp/pylib.cc "_build/obj/$compiler-$variant-sh/cpp/pylib.o"

  _compile_one "$compiler" "$variant" "" \
    cpp/stdlib.cc "_build/obj/$compiler-$variant-sh/cpp/stdlib.o"

  _compile_one "$compiler" "$variant" "" \
    mycpp/bump_leak_heap.cc "_build/obj/$compiler-$variant-sh/mycpp/bump_leak_heap.o"

  _compile_one "$compiler" "$variant" "" \
    mycpp/gc_builtins.cc "_build/obj/$compiler-$variant-sh/mycpp/gc_builtins.o"

  _compile_one "$compiler" "$variant" "" \
    mycpp/gc_iolib.cc "_build/obj/$compiler-$variant-sh/mycpp/gc_iolib.o"

  _compile_one "$compiler" "$variant" "" \
    mycpp/gc_mops.cc "_build/obj/$compiler-$variant-sh/mycpp/gc_mops.o"

  _compile_one "$compiler" "$variant" "" \
    mycpp/gc_mylib.cc "_build/obj/$compiler-$variant-sh/mycpp/gc_mylib.o"

  _compile_one "$compiler" "$variant" "" \
    mycpp/gc_str.cc "_build/obj/$compiler-$variant-sh/mycpp/gc_str.o"

  _compile_one "$compiler" "$variant" "" \
    mycpp/hash.cc "_build/obj/$compiler-$variant-sh/mycpp/hash.o"

  _compile_one "$compiler" "$variant" "" \
    mycpp/mark_sweep_heap.cc "_build/obj/$compiler-$variant-sh/mycpp/mark_sweep_heap.o"

  # wait for the translation unit before linking
  echo WAIT
  wait

  echo "LINK $out_path"
  set -- \
    "_build/obj/$compiler-$variant-sh/_gen/bin/oils_for_unix.$translator.o" \
    "_build/obj/$compiler-$variant-sh/_gen/bin/oils_for_unix.$translator-main.o" \
    "_build/obj/$compiler-$variant-sh/_gen/bin/text_files.o" \
    "_build/obj/$compiler-$variant-sh/_gen/core/runtime.asdl.o" \
    "_build/obj/$compiler-$variant-sh/_gen/core/value.asdl.o" \
    "_build/obj/$compiler-$variant-sh/_gen/cpp/build_stamp.o" \
    "_build/obj/$compiler-$variant-sh/_gen/data_lang/nil8.asdl.o" \
    "_build/obj/$compiler-$variant-sh/_gen/display/pretty.asdl.o" \
    "_build/obj/$compiler-$variant-sh/_gen/frontend/arg_types.o" \
    "_build/obj/$compiler-$variant-sh/_gen/frontend/consts.o" \
    "_build/obj/$compiler-$variant-sh/_gen/frontend/help_meta.o" \
    "_build/obj/$compiler-$variant-sh/_gen/frontend/id_kind.asdl.o" \
    "_build/obj/$compiler-$variant-sh/_gen/frontend/signal.o" \
    "_build/obj/$compiler-$variant-sh/_gen/frontend/syntax.asdl.o" \
    "_build/obj/$compiler-$variant-sh/_gen/osh/arith_parse.o" \
    "_build/obj/$compiler-$variant-sh/_gen/ysh/grammar_tables.o" \
    "_build/obj/$compiler-$variant-sh/cpp/core.o" \
    "_build/obj/$compiler-$variant-sh/cpp/data_lang.o" \
    "_build/obj/$compiler-$variant-sh/cpp/fanos.o" \
    "_build/obj/$compiler-$variant-sh/cpp/fanos_shared.o" \
    "_build/obj/$compiler-$variant-sh/cpp/frontend_flag_spec.o" \
    "_build/obj/$compiler-$variant-sh/cpp/frontend_match.o" \
    "_build/obj/$compiler-$variant-sh/cpp/frontend_pyreadline.o" \
    "_build/obj/$compiler-$variant-sh/cpp/libc.o" \
    "_build/obj/$compiler-$variant-sh/cpp/osh.o" \
    "_build/obj/$compiler-$variant-sh/cpp/osh_tdop.o" \
    "_build/obj/$compiler-$variant-sh/cpp/pgen2.o" \
    "_build/obj/$compiler-$variant-sh/cpp/pylib.o" \
    "_build/obj/$compiler-$variant-sh/cpp/stdlib.o" \
    "_build/obj/$compiler-$variant-sh/mycpp/bump_leak_heap.o" \
    "_build/obj/$compiler-$variant-sh/mycpp/gc_builtins.o" \
    "_build/obj/$compiler-$variant-sh/mycpp/gc_iolib.o" \
    "_build/obj/$compiler-$variant-sh/mycpp/gc_mops.o" \
    "_build/obj/$compiler-$variant-sh/mycpp/gc_mylib.o" \
    "_build/obj/$compiler-$variant-sh/mycpp/gc_str.o" \
    "_build/obj/$compiler-$variant-sh/mycpp/hash.o" \
    "_build/obj/$compiler-$variant-sh/mycpp/mark_sweep_heap.o"


  link "$compiler" "$variant" "" "$out_path" "$@"

  if test "$variant" = opt; then
    strip -o "$out_path.stripped" "$out_path"
  fi

  # Symlink to unstripped binary for benchmarking
  cd "$out_dir"  # dir may have spaces
  for symlink in "osh$FLAG_suffix" "ysh$FLAG_suffix"; do
    # like ln -v, which we can't use portably
    echo "    $symlink -> $out_name$FLAG_suffix"
    ln -s -f "$out_name$FLAG_suffix" $symlink
  done
}

main "$@"

