#!/bin/sh

# The MIT License (MIT)
#
# Copyright (c) 2025 Fraser Heavy Software
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.



# This performs a native build of Onramp.
#
# You'll need Ninja and a C compiler installed to use this.
#
# This generates a Ninja build file similar to a configure script. You can set
# environment variables CC, CFLAGS, etc. to configure the build. It then runs
# Ninja to perform the build.
#
# See the Setup Guide (docs/setup-guide.md) for details.



set -e
cd "$(dirname "$0")/../.."

DEST=build/build.ninja



# Core POSIX setup
# This is duplicated from scripts/posix/native.sh

echo "Cleaning build/"
rm -rf build

# Setup basic POSIX paths
mkdir -p \
    build/posix/bin \
    build/posix/share/onramp/platform
(cd build/posix/share/onramp; ln -sf ../../../output/bin .)
(cd build/posix/share/onramp; ln -sf ../../../output/lib .)
(cd build/posix/share/onramp; ln -sf ../../../output/include .)

# Copy the POSIX cc wrapper into place and generate links for the other programs.
# TODO we don't have a native archiver yet so we're using the onramp archiver and its wrapper.
cp platform/cc/posix/wrap-header build/posix/share/onramp/platform
cp platform/cc/posix/onrampcc-native build/posix/bin/onrampcc
  cp platform/cc/posix/onrampar build/posix/bin
  #(cd build/posix/bin; ln -sf ../../../output/bin/ar onrampar)
(cd build/posix/bin; ln -sf ../../output/bin/hex onramphex)
(cd build/posix/bin; ln -sf ../../output/bin/vm onrampvm)

# Install headers
core/libc/common/build.sh



# Set default vars

if [ "x$CC" = "x" ]; then
    CC="cc"
fi
if [ "x$AR" = "x" ]; then
    AR="ar"
fi
if [ "x$CFLAGS" = "x" ]; then
    CFLAGS="-g -O2"
fi
if [ "x$CPPFLAGS" = "x" ]; then
    CPPFLAGS="-Wall"
fi
if [ "x$LDFLAGS" = "x" ]; then
    LDFLAGS=""
fi



# Generate rules

cat >$DEST <<EOF
# This file is generated by scripts/posix/native.sh

cflags = $CFLAGS -Icore/libo/1-opc/include
cppflags = $CPPFLAGS
ldflags = $LDFLAGS
cc = $CC
ar = $AR

# TODO onramp tools don't generate safe temporary files yet. for now we
# restrict them from running in parallel.
pool onramp_pool
 depth = 1

rule compile_native
 command = \$cc -c \$cppflags \$cflags -o \$out \$in
 description = Compiling \$out

rule archive_native
 command = \$ar rc \$out \$in
 description = Archiving \$out

rule link_native
 command = \$cc \$ldflags -o \$out \$in
 description = Linking \$out

rule compile_onramp
 command = build/posix/bin/onrampcc $
    -c -O $
    -Icore/libc/common/src $
    -o \$out $
    \$in
 description = Compiling \$out
 pool = onramp_pool

rule archive_onramp
 command = build/posix/bin/onrampar rc \$out \$in
 description = Archiving \$out
 pool = onramp_pool

rule link_onramp
 command = build/posix/bin/onrampcc -o \$out \$in
 description = Compiling \$out
 pool = onramp_pool

# builds all native tools
build native: phony $
    build/output/bin/cpp $
    build/output/bin/cci $
    build/output/bin/as $
    build/output/bin/ld $
    build/output/bin/cc $
    build/output/bin/hex $
    build/output/bin/vm $

# builds all onramp tools
# TODO move ar up once native
build all: phony $
    native $
    build/output/bin/ar.oe $
    build/output/lib/libc.oa $

default all

EOF



build() {
    rule=$1
    target=$2
    implicit_deps=$3
    shift
    shift
    shift
    if [ "x$2" = "x" ]; then
        # oneline
        echo "build $target: $rule $@ | $implicit_deps" >> $DEST
    else
        echo "build $target: $rule $" >> $DEST
        while [ "x$1" != "x" ]; do
            echo "  $1 $" >> $DEST
            shift
        done
        echo "  | $implicit_deps" >> $DEST
        echo >> $DEST
    fi
}

srcs_native() {
    dir=$1
    shift
    OBJS=
    for src in $@; do
        obj=build/intermediate/$dir/$(basename $src).o
        build compile_native $obj "" $src
        OBJS="$OBJS $obj"
    done
}

srcs_onramp() {
    dir=$1
    shift
    OBJS=
    for src in $@; do
        obj=build/intermediate/$dir/$(basename $src).oo
        build compile_onramp $obj "native" $src
        OBJS="$OBJS $obj"
    done
}

comment() {
    echo "#" "$@" >> $DEST
}



comment "libo/1-opc"
srcs_native libo-1-opc core/libo/1-opc/src/*.c
LIBO=build/intermediate/libo-1-opc/libo.a
build archive_native $LIBO "" $OBJS

comment "cpp/2-full"
srcs_native cpp-2-full core/cpp/2-full/src/*.c
build link_native build/output/bin/cpp "" $OBJS $LIBO

comment "cci/2-full"
srcs_native cci-2-full core/cci/2-full/src/*.c
build link_native build/output/bin/cci "" $OBJS $LIBO

comment "as/2-full"
srcs_native as-2-full core/as/2-full/src/*.c
build link_native build/output/bin/as "" $OBJS $LIBO

comment "ld/2-full"
srcs_native ld-2-full core/ld/2-full/src/*.c
build link_native build/output/bin/ld "" $OBJS $LIBO

comment "cc"
srcs_native cc core/cc/cc.c
build link_native build/output/bin/cc "" $OBJS $LIBO

comment "hex"
srcs_native hex-1-c89 core/hex/1-c89/hex.c
build link_native build/output/bin/hex "" $OBJS $LIBO

comment "vm/c-debugger"
srcs_native vm-c-debugger platform/vm/c-debugger/src/*.c
build link_native build/output/bin/vm "" $OBJS $LIBO

comment "ar"
# TODO use ar/1 once it exists. we have no native archive tool at all at the moment
echo "build -nostdlib: phony" >> $DEST
build link_onramp build/output/bin/ar.oe "native" \
    -nostdlib \
    \
    core/libc/0-oo/src/start.oo \
    \
    core/libc/0-oo/src/ctype.oo \
    core/libc/0-oo/src/environ.oo \
    core/libc/0-oo/src/errno.oo \
    core/libc/0-oo/src/malloc.oo \
    core/libc/0-oo/src/malloc_util.oo \
    core/libc/0-oo/src/spawn.oo \
    core/libc/0-oo/src/stdio.oo \
    core/libc/0-oo/src/string.oo \
    \
    core/libo/0-oo/src/libo-error.oo \
    core/libo/0-oo/src/libo-util.oo \
    \
    core/ar/0-cat/ar.oo

comment "libc/3-full"
srcs_onramp libc-3-full \
    core/libc/2-opc/src/start.os \
    \
    core/libc/1-omc/src/strtol.c \
    \
    core/libc/2-opc/src/assert.c \
    core/libc/2-opc/src/ctype.c \
    core/libc/2-opc/src/environ.c \
    core/libc/2-opc/src/float.c \
    core/libc/2-opc/src/format.c \
    core/libc/2-opc/src/llong.c \
    core/libc/2-opc/src/multibyte.c \
    core/libc/2-opc/src/posixio.c \
    core/libc/2-opc/src/setjmp.os \
    core/libc/2-opc/src/stdbit.c \
    core/libc/2-opc/src/stdio.c \
    core/libc/2-opc/src/stdlib.c \
    core/libc/2-opc/src/string.c \
    core/libc/2-opc/src/strings.c \
    core/libc/2-opc/src/syscalls.os \
    core/libc/2-opc/src/system.c \
    \
    core/libc/3-full/src/atexit.c \
    core/libc/3-full/src/bsearch.c \
    core/libc/3-full/src/malloc.c \
    core/libc/3-full/src/qsort.c \
    core/libc/3-full/src/rand.c \
    core/libc/3-full/src/signal.c \
    core/libc/3-full/src/stdbit_llong.c \
    core/libc/3-full/src/stdlib_3.c \
    core/libc/3-full/src/time.c
    # TODO just include libc/3/*.c once malloc works
# TODO shouldn't depend on ar.oe, necessary until we have native ar
build archive_onramp build/output/lib/libc.oa \
    "native build/output/bin/ar.oe" \
    $OBJS \
    core/libc/0-oo/src/errno.oo \
    core/libc/0-oo/src/spawn.oo

comment "sh/1 TODO"
# TODO



echo "Generated $DEST"
echo "Running: ninja -f $DEST"
ninja -f $DEST
