#!/bin/sh
#
# Configure script for OS/161 tree.
# This generates the file "defs.mk" at the top level of the tree.
#
# Usage: ./configure [options]
#   where you can get a list of the options by doing ./configure --help.
#
# Must be run with the top of the OS/161 tree as its current directory.
#
# Note: while this superficially acts like a GNU Autoconf configure
# script, it was not generated by autoconf. Scripts generated by 
# autoconf are much harder to read. :-)
#


# gcc warnings to use.
# (If you change this, rerun the script to propagate it to defs.mk.)
# -Werror will be added if the --werror argument is given.
WARNINGS='-Wall -W -Wwrite-strings'

# Target hardware platform.
PLATFORM='mips'

# Default optimize/debug flag: optimize.
OPTFLAGS='-O2'

# Default location of the root of the installed system.
# Note that we quote it such that the reference to the home directory
# is a make variable, not a shell variable. This means it gets expanded
# when make runs rather than when this script runs.
OSTREE='$(HOME)/cs161/root'

# Default toolchain name.
TOOLPREFIX="cs161-" 

##################################################

#
# Check to make sure we're in the right place.

if [ ! -d kern/userprog ]; then
    echo 'Please run configure from the top of the OS/161 tree.'
    exit 1
fi

#
# Process the command-line options.

while [ "x$1" != x ]; do
    case "$1" in
	--debug) OPTFLAGS='-g';;
	--werror|--Werror) WARNINGS="$WARNINGS -Werror";;
	--ostree=*) OSTREE=`echo $1 | sed 's,^[^=]*=,,'`;;
	--toolprefix=*) TOOLPREFIX=`echo $1 | sed 's,^[^=]*=,,'`;;
	--help|*)
		more <<EOF
Usage: ./configure [options]
  where the options are:
    --help               Print this message.

    --debug              Compile the user-level programs with debug info.
                         This is disabled by default because there's no
                         support for userlevel source debugging in OS/161.
                         (Note: debug info in the kernel is controlled by
                         the kernel config file.)

    --werror             Compile with -Werror, so that compiler warnings 
                         are turned into errors and cause the build to
			 stop. Recommended, because on long builds you 
                         don't always notice warnings as they go by, but
                         disabled by default.

    --ostree=PATH        Install the compiled system in a directory tree
                         rooted at PATH. Default is \$HOME/cs161/root.

    --toolprefix=NAME    Set up to use compiler and tools named with a
                         prefix of NAME. The default is "cs161-", so the
                         tools used are called cs161-gcc, cs161-ld, etc.
                         The directory with these tools should be on your
                         shell's search path.
EOF
    exit
    ;;
    esac
shift
done

####################

# Assume gcc on the host. It would be nice to probe this, but for now
# it doesn't seem worthwhile.

HOST_CC=gcc

####################

# Figure out if the host system needs us to use ranlib or not. Assume
# that if it exists, we should use it. This is a bad assumption on
# BSD/OS 2.1, but hopefully that won't come up, as BSD/OS 2.1 is quite
# out of date now.

echo -n 'Checking for ranlib... '

STUFF=`(ranlib) 2>&1`

if echo $STUFF | grep 'not found' >/dev/null 2>&1; then
    echo 'no'
    HOST_RANLIB=true
else
    echo 'yes'
    HOST_RANLIB=ranlib
fi


####################

# Check if the host system supports 4.4BSD <err.h>.

echo -n "Checking for <err.h>... "

cat > __conftest.c <<EOF
#include <err.h>
int
main()
{
    err(0, "works");
    return 1;
}
EOF

OK=0
if $HOST_CC __conftest.c -o __conftest >/dev/null 2>&1; then
    if ./__conftest >/dev/null 2>&1; then
	OK=1
    fi
fi

rm -f __conf*

if [ $OK = 1 ]; then
    echo 'yes'
else
    echo 'no'
    COMPAT_CFLAGS="${COMPATCFLAGS} -DNEED_ERR"
    COMPAT_TARGETS="${HOSTTARGETS} install-errh"
fi

####################

# Now generate defs.mk.

echo 'Generating defs.mk.'

(
    # First, put an explanatory comment at the top.
    cat <<EOF
# This file was generated by configure. Edits will disappear if you rerun
# configure. If you find that you need to edit this file to make things
# work, let the course staff know and we'll try to fix the configure script.
#
# 
# The purpose of this file is to hold all the makefile definitions
# needed to adjust the OS/161 build process to any particular
# environment. If I've done it right, all you need to do is rerun the
# configure script and make clean if you decide to work from Linux or
# BSD instead of Digital Unix. If I've done it mostly right, you may
# need to edit this file but you still hopefully won't need to edit
# any of the makefiles.
#

EOF
    # Initialize various variables.
cat <<EOF

#
# Initialize various variables that we set only with += in case some make
# has a default value we weren't expecting.
#
CFLAGS=
KCFLAGS=
HOST_CFLAGS=
LDFLAGS=
KLDFLAGS=
HOST_LDFLAGS=
LIBS=
HOST_LIBS=

EOF

    # Define OSTREE.

cat <<EOF
#
# Location of installed runnable system tree.
#
# This must be an absolute path, because it is used from different
# levels of the source tree.
#
OSTREE=${OSTREE}

EOF

    # Define PLATFORM.
cat <<EOF
#
# Name of the platform we're building OS/161 to run on.
#
PLATFORM=${PLATFORM}

EOF

if [ "x$PLATFORM" = xmips ]; then
cat <<EOF
#
# As of cs161-toolchain-1.2 the MIPS toolchain is a mips-linux one
# that generates more or less SVR4 ELF ABI compliant code. This means
# that by default all code is PIC (position-independent code), which
# is all very well but not what we want. So we use -fno-pic to turn
# this behavior off. It turns out you need -mno-abicalls too to turn
# it off completely.
#
CFLAGS+=-mno-abicalls -fno-pic
KCFLAGS+=-mno-abicalls -fno-pic

# If using an older cs161-toolchain for MIPS, you'll need this instead:
#LDFLAGS+=-Ttext 0x1000
EOF
fi

    # Long explanatory comment about the two sets of compiler tools.
    cat <<EOF
#
# Because OS/161 runs on one architecture (probably MIPS or ANT32) and
# is compiled on another (probably Alpha or i386) it is important to
# make sure the right compiler (and assembler, linker, etc.) is used
# at every point.
#
# A compiler compiles *running on* one platform, and *generates code*
# that may run on a different platform. Thus, supposing that you are 
# building MIPS OS/161 on i386 Linux, there are four possible compilers.
# (If you are building some other OS/161 or building on some other
# platform, make the appropriate substitutions.) These four are:
#
#    (1) runs on i386 Linux, generates code for i386 Linux
#    (2) runs on i386 Linux, generates code for MIPS OS/161
#    (3) runs on MIPS OS/161, generates code for i386 Linux
#    (4) runs on MIPS OS/161, generates code for MIPS OS/161
#
# Note that when building on i386 Linux, there is no use for a
# compiler that runs on MIPS OS/161; you can't run it. Thus cases
# (3) and (4) do not interest us.
#
# However, in the course of the build, there are places where it is
# necessary to compile and run programs on the machine the build is
# happening on. Thus, the makefiles need to be able to access *both*
# compiler (1) and compiler (2).
#
# We do this by defining the make variable CC to be the common case,
# compiler (2), and the make variable HOST_CC to be compiler (1). 
# Similar variables are defined for the other bits of the toolchain,
# like AS (assembler), LD (linker), and SIZE (size program).
#
# Then, programs to be run during the build can be compiled with 
# HOST_CC, and components of the system can be built with CC.
#

EOF

    # define CC, LDCC, AS, LD, AR, RANLIB, SIZE, STRIP,
    # the tools for building OS/161.

    cat <<EOF

# CC: compiler, when compiling to object files
CC=${TOOLPREFIX}gcc 
# LDCC: compiler, when linking
LDCC=${TOOLPREFIX}gcc
# AS: assembler.
AS=${TOOLPREFIX}as
# LD: linker
LD=${TOOLPREFIX}ld
# AR: archiver (librarian)
AR=${TOOLPREFIX}ar
# RANLIB: library postprocessor
RANLIB=${TOOLPREFIX}ranlib
# NM: prints symbol tables
NM=${TOOLPREFIX}nm
# SIZE: prints size of binaries
SIZE=${TOOLPREFIX}size
# STRIP: strips debug info
STRIP=${TOOLPREFIX}strip

EOF

    # define HOST_CC, HOST_LDCC, HOST_AS, HOST_LD, HOST_AR, HOST_RANLIB,
    # HOST_NM, HOST_SIZE, HOST_STRIP, the tools for building programs 
    # that run on the host system.

cat <<EOF

# compiler for host system
HOST_CC=${HOST_CC}

# compiler for host system, when linking
HOST_LDCC=${HOST_CC}

# assembler for host system
HOST_AS=as

# linker for host system
HOST_LD=ld

# archiver (librarian) for host system
HOST_AR=ar

# ranlib (library postprocessor) for host system... or "true" to skip it
HOST_RANLIB=${HOST_RANLIB}

# nm for host system
HOST_NM=nm

# size for host system
HOST_SIZE=size

# strip for host system
HOST_STRIP=strip

EOF

    # Define compiler and linker flags we're going to use based on the
    # requests above.

    # This keeps the shell from interpreting the $() inside the here-document.
    HINC='-I$(OSTREE)/hostinclude'

    cat <<EOF

# The HOST_... versions are for compiling/linking for the host system.
# The K... versions are for the kernel build. 

# Compile flags. 
# The kernel has its own debug/optimize setting in the kernel config, so
# we don't include ours.
CFLAGS+=${WARNINGS} ${OPTFLAGS}
KCFLAGS+=${WARNINGS}
HOST_CFLAGS+=${WARNINGS} ${OPTFLAGS} ${HINC}

# Linker flags
LDFLAGS+=
KLDFLAGS+=
HOST_LDFLAGS+=

# Libraries
# 
LIBS+=
HOST_LIBS+=

EOF

    # Config information for the hostcompat library
    cat <<EOF

# These are cflags used to conditionally compile src/lib/hostcompat.
COMPAT_CFLAGS=${COMPAT_CFLAGS}

# These are make targets that we conditionally enable when installing
# in src/lib/hostcompat.
COMPAT_TARGETS=${COMPAT_TARGETS}

EOF

    # Define additional flags for making the toolchain do what we want.
    cat <<EOF

# When we compile OS/161 programs, we want to use the OS/161 header files
# and libraries. By default, gcc will look in some include directory and
# some lib directory that it was told to use when it was compiled. We 
# assume that directory isn't ours. (If it is, all these variables can
# be set to empty, but everything will still work if you don't.)
EOF
echo 'TREE_CFLAGS=-nostdinc -I$(OSTREE)/include'
echo 'TREE_LDFLAGS=-nostdlib -L$(OSTREE)/lib $(OSTREE)/lib/crt0.o'
echo 'TREE_LIBS=-lc'

) > defs.mk

