#!/bin/sh
#
# qemu configure script (c) 2003 Fabrice Bellard
#

# Unset some variables known to interfere with behavior of common tools,
# just as autoconf does.
CLICOLOR_FORCE= GREP_OPTIONS=
unset CLICOLOR_FORCE GREP_OPTIONS

# Temporary directory used for files created while
# configure runs. Since it is in the build directory
# we can safely blow away any previous version of it
# (and we need not jump through hoops to try to delete
# it when configure exits.)
TMPDIR1="config-temp"
rm -rf "${TMPDIR1}"
mkdir -p "${TMPDIR1}"
if [ $? -ne 0 ]; then
    echo "ERROR: failed to create temporary directory"
    exit 1
fi

TMPB="qemu-conf"
TMPC="${TMPDIR1}/${TMPB}.c"
TMPO="${TMPDIR1}/${TMPB}.o"
TMPL="${TMPDIR1}/${TMPB}.lo"
TMPA="${TMPDIR1}/lib${TMPB}.la"
TMPE="${TMPDIR1}/${TMPB}.exe"

rm -f config.log

# Print a helpful header at the top of config.log
echo "# QEMU configure log $(date)" >> config.log
printf "# Configured with:" >> config.log
printf " '%s'" "$0" "$@" >> config.log
echo >> config.log
echo "#" >> config.log

error_exit() {
    echo
    echo "ERROR: $1"
    while test -n "$2"; do
        echo "       $2"
        shift
    done
    echo
    exit 1
}

do_compiler() {
    # Run the compiler, capturing its output to the log. First argument
    # is compiler binary to execute.
    local compiler="$1"
    shift
    echo $compiler "$@" >> config.log
    $compiler "$@" >> config.log 2>&1 || return $?
    # Test passed. If this is an --enable-werror build, rerun
    # the test with -Werror and bail out if it fails. This
    # makes warning-generating-errors in configure test code
    # obvious to developers.
    if test "$werror" != "yes"; then
        return 0
    fi
    # Don't bother rerunning the compile if we were already using -Werror
    case "$*" in
        *-Werror*)
           return 0
        ;;
    esac
    echo $compiler -Werror "$@" >> config.log
    $compiler -Werror "$@" >> config.log 2>&1 && return $?
    error_exit "configure test passed without -Werror but failed with -Werror." \
        "This is probably a bug in the configure script. The failing command" \
        "will be at the bottom of config.log." \
        "You can run configure with --disable-werror to bypass this check."
}

do_cc() {
    do_compiler "$cc" "$@"
}

compile_object() {
  do_cc $QEMU_CFLAGS -c -o $TMPO $TMPC
}

compile_prog() {
  local_cflags="$1"
  local_ldflags="$2"
  do_cc $QEMU_CFLAGS $local_cflags -o $TMPE $TMPC $LDFLAGS $local_ldflags
}

# symbolically link $1 to $2.  Portable version of "ln -sf".
symlink() {
  rm -rf "$2"
  mkdir -p "$(dirname "$2")"
  ln -s "$1" "$2"
}

# check whether a command is available to this shell (may be either an
# executable or a builtin)
has() {
    type "$1" >/dev/null 2>&1
}

# search for an executable in PATH
path_of() {
    local_command="$1"
    local_ifs="$IFS"
    local_dir=""

    # pathname has a dir component?
    if [ "${local_command#*/}" != "$local_command" ]; then
        if [ -x "$local_command" ] && [ ! -d "$local_command" ]; then
            echo "$local_command"
            return 0
        fi
    fi
    if [ -z "$local_command" ]; then
        return 1
    fi

    IFS=:
    for local_dir in $PATH; do
        if [ -x "$local_dir/$local_command" ] && [ ! -d "$local_dir/$local_command" ]; then
            echo "$local_dir/$local_command"
            IFS="${local_ifs:-$(printf ' \t\n')}"
            return 0
        fi
    done
    # not found
    IFS="${local_ifs:-$(printf ' \t\n')}"
    return 1
}

# make source path absolute
source_path=$(cd "$(dirname -- "$0")"; pwd)

if printf %s\\n "$source_path" "$PWD" | grep -q "[[:space:]:]";
then
  error_exit "main directory cannot contain spaces nor colons"
fi

# default parameters
cpu=""
static="no"
cross_prefix=""
host_cc="cc"
libs_softmmu=""
cc_i386=i386-pc-linux-gnu-gcc
debug_info="yes"
stack_protector=""

# Don't accept a target_list environment variable.
unset target_list

# Default value for a variable defining feature "foo".
#  * foo="no"  feature will only be used if --enable-foo arg is given
#  * foo=""    feature will be searched for, and if found, will be used
#              unless --disable-foo is given
#  * foo="yes" this value will only be set by --enable-foo flag.
#              feature will searched for,
#              if not found, configure exits with error
#
# Always add --enable-foo and --disable-foo command line args.
# Distributions want to ensure that several features are compiled in, and it
# is impossible without a --enable-foo that exits if a feature is not found.

debug_tcg="no"
debug="no"
sanitizers="no"
strip_opt="yes"
tcg_interpreter="no"
bigendian="no"
mingw32="no"
EXESUF=""
DSOSUF=".so"
LDFLAGS_SHARED="-shared"
bsd="no"
linux="no"
solaris="no"
softmmu="yes"
pie=""
tcg="yes"
membarrier=""
cpuid_h="no"
avx2_opt="no"

supported_cpu="no"
supported_os="no"
bogus_os="no"

# parse CC options first
for opt do
  optarg=$(expr "x$opt" : 'x[^=]*=\(.*\)')
  case "$opt" in
  --cc=*) CC="$optarg"
  ;;
  --source-path=*) source_path="$optarg"
  ;;
  --cpu=*) cpu="$optarg"
  ;;
  --extra-cflags=*) QEMU_CFLAGS="$optarg $QEMU_CFLAGS"
  ;;
  --extra-ldflags=*) LDFLAGS="$optarg $LDFLAGS"
  ;;
  --disable-tcg) tcg="no"
  ;;
  --enable-tcg) tcg="yes"
  ;;
  --enable-debug-info) debug_info="yes"
  ;;
  --disable-debug-info) debug_info="no"
  ;;
  --enable-sanitizers) sanitizers="yes"
  ;;
  --disable-sanitizers) sanitizers="no"
  ;;
  esac
done
# OS specific
# Using uname is really, really broken.  Once we have the right set of checks
# we can eliminate its usage altogether.

# Preferred compiler:
#  ${CC} (if set)
#  ${cross_prefix}gcc (if cross-prefix specified)
#  system compiler
if test -z "${CC}${cross_prefix}"; then
  cc="$host_cc"
else
  cc="${CC-${cross_prefix}gcc}"
fi

ar="${AR-${cross_prefix}ar}"
as="${AS-${cross_prefix}as}"
cpp="${CPP-$cc -E}"
objcopy="${OBJCOPY-${cross_prefix}objcopy}"
ld="${LD-${cross_prefix}ld}"
nm="${NM-${cross_prefix}nm}"
strip="${STRIP-${cross_prefix}strip}"

# If the user hasn't specified ARFLAGS, default to 'rv', just as make does.
ARFLAGS="${ARFLAGS-rv}"

# default flags for all hosts
# We use -fwrapv to tell the compiler that we require a C dialect where
# left shift of signed integers is well defined and has the expected
# 2s-complement style results. (Both clang and gcc agree that it
# provides these semantics.)
QEMU_CFLAGS="-fno-strict-aliasing -fno-common -fwrapv -std=gnu99 $QEMU_CFLAGS"
QEMU_CFLAGS="-Wall -Wundef -Wwrite-strings -Wmissing-prototypes $QEMU_CFLAGS"
QEMU_CFLAGS="-Wstrict-prototypes -Wredundant-decls $QEMU_CFLAGS"
QEMU_CFLAGS="-D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE $QEMU_CFLAGS"
QEMU_INCLUDES="-I. -I\$(SRC_PATH) -I\$(SRC_PATH)/accel/tcg -I\$(SRC_PATH)/include"
if test "$debug_info" = "yes"; then
    CFLAGS="-g $CFLAGS"
    LDFLAGS="-g $LDFLAGS"
else
    CFLAGS="-O3 $CFLAGS"
    LDFLAGS="-O3 $LDFLAGS"
fi

# make source path absolute
source_path=$(cd "$source_path"; pwd)

# running configure in the source tree?
# we know that's the case if configure is there.
if test -f "./configure"; then
    pwd_is_source_path="y"
else
    pwd_is_source_path="n"
fi

check_define() {
cat > $TMPC <<EOF
#if !defined($1)
#error $1 not defined
#endif
int main(void) { return 0; }
EOF
  compile_object
}

write_c_skeleton() {
  cat > $TMPC <<EOF
int main(void) { return 0; }
EOF
}

if check_define __linux__ ; then
  targetos="Linux"
elif check_define _WIN32 ; then
  targetos='MINGW32'
elif check_define __OpenBSD__ ; then
  targetos='OpenBSD'
elif check_define __sun__ ; then
  targetos='SunOS'
elif check_define __HAIKU__ ; then
  targetos='Haiku'
elif check_define __FreeBSD__ ; then
  targetos='FreeBSD'
elif check_define __FreeBSD_kernel__ && check_define __GLIBC__; then
  targetos='GNU/kFreeBSD'
elif check_define __DragonFly__ ; then
  targetos='DragonFly'
elif check_define __NetBSD__; then
  targetos='NetBSD'
elif check_define __APPLE__; then
  targetos='Darwin'
else
  # This is a fatal error, but don't report it yet, because we
  # might be going to just print the --help text, or it might
  # be the result of a missing compiler.
  targetos='bogus'
  bogus_os='yes'
fi

# Some host OSes need non-standard checks for which CPU to use.
# Note that these checks are broken for cross-compilation: if you're
# cross-compiling to one of these OSes then you'll need to specify
# the correct CPU with the --cpu option.
case $targetos in
Darwin)
  # on Leopard most of the system is 32-bit, so we have to ask the kernel if we can
  # run 64-bit userspace code.
  # If the user didn't specify a CPU explicitly and the kernel says this is
  # 64 bit hw, then assume x86_64. Otherwise fall through to the usual detection code.
  if test -z "$cpu" && test "$(sysctl -n hw.optional.x86_64)" = "1"; then
    cpu="x86_64"
  fi
  ;;
SunOS)
  # $(uname -m) returns i86pc even on an x86_64 box, so default based on isainfo
  if test -z "$cpu" && test "$(isainfo -k)" = "amd64"; then
    cpu="x86_64"
  fi
esac

if test ! -z "$cpu" ; then
  # command line argument
  :
elif check_define __i386__ ; then
  cpu="i386"
elif check_define __x86_64__ ; then
  if check_define __ILP32__ ; then
    cpu="x32"
  else
    cpu="x86_64"
  fi
elif check_define __sparc__ ; then
  if check_define __arch64__ ; then
    cpu="sparc64"
  else
    cpu="sparc"
  fi
elif check_define _ARCH_PPC ; then
  if check_define _ARCH_PPC64 ; then
    cpu="ppc64"
  else
    cpu="ppc"
  fi
elif check_define __mips__ ; then
  cpu="mips"
elif check_define __s390__ ; then
  if check_define __s390x__ ; then
    cpu="s390x"
  else
    cpu="s390"
  fi
elif check_define __riscv ; then
  if check_define _LP64 ; then
    cpu="riscv64"
  else
    cpu="riscv32"
  fi
elif check_define __arm__ ; then
  cpu="arm"
elif check_define __aarch64__ ; then
  cpu="aarch64"
else
  cpu=$(uname -m)
fi

ARCH=
# Normalise host CPU name and set ARCH.
# Note that this case should only have supported host CPUs, not guests.
case "$cpu" in
  ppc|ppc64|s390|s390x|x32|riscv32|riscv64)
    cpu="$cpu"
    supported_cpu="yes"
  ;;
  sparc64)
    cpu="$cpu"
  ;;
  i386|i486|i586|i686|i86pc|BePC)
    cpu="i386"
    supported_cpu="yes"
  ;;
  x86_64|amd64)
    cpu="x86_64"
    supported_cpu="yes"
  ;;
  armv*b|armv*l|arm)
    cpu="arm"
    supported_cpu="yes"
  ;;
  aarch64|aarch64eb)
    cpu="aarch64"
    supported_cpu="yes"
  ;;
  mips*)
    cpu="mips"
    supported_cpu="yes"
  ;;
  sparc|sun4[cdmuv])
    cpu="sparc"
  ;;
  *)
    # This will result in either an error or falling back to TCI later
    ARCH=unknown
  ;;
esac
if test -z "$ARCH"; then
  ARCH="$cpu"
fi

# OS specific

case $targetos in
MINGW32*)
  mingw32="yes"
  supported_os="yes"
;;
GNU/kFreeBSD)
  bsd="yes"
;;
FreeBSD)
  bsd="yes"
  make="${MAKE-gmake}"
  # needed for kinfo_getvmmap(3) in libutil.h
  LIBS="-lutil $LIBS"
  supported_os="yes"
;;
DragonFly)
  bsd="yes"
  make="${MAKE-gmake}"
;;
NetBSD)
  bsd="yes"
  make="${MAKE-gmake}"
;;
OpenBSD)
  bsd="yes"
  make="${MAKE-gmake}"
;;
Darwin)
  bsd="yes"
  darwin="yes"
  LDFLAGS_SHARED="-bundle -undefined dynamic_lookup"
  if [ "$cpu" = "x86_64" ] ; then
    QEMU_CFLAGS="-arch x86_64 $QEMU_CFLAGS"
    LDFLAGS="-arch x86_64 $LDFLAGS"
  fi
  # Disable attempts to use ObjectiveC features in os/object.h since they
  # won't work when we're compiling with gcc as a C compiler.
  QEMU_CFLAGS="-DOS_OBJECT_USE_OBJC=0 $QEMU_CFLAGS"
  supported_os="yes"
;;
SunOS)
  solaris="yes"
  make="${MAKE-gmake}"
  ld="gld"
# needed for CMSG_ macros in sys/socket.h
  QEMU_CFLAGS="-D_XOPEN_SOURCE=600 $QEMU_CFLAGS"
# needed for TIOCWIN* defines in termios.h
  QEMU_CFLAGS="-D__EXTENSIONS__ $QEMU_CFLAGS"
  QEMU_CFLAGS="-std=gnu99 $QEMU_CFLAGS"
  solarisnetlibs="-lsocket -lnsl -lresolv"
  LIBS="$solarisnetlibs $LIBS"
;;
Haiku)
  haiku="yes"
  QEMU_CFLAGS="-DB_USE_POSITIVE_POSIX_ERRORS $QEMU_CFLAGS"
  LIBS="-lposix_error_mapper -lnetwork $LIBS"
;;
Linux)
  linux="yes"
  supported_os="yes"
;;
esac

: ${make=${MAKE-make}}
# We prefer python 3.x. A bare 'python' is traditionally
# python 2.x, but some distros have it as python 3.x, so
# we check that too
python=
for binary in "${PYTHON-python3}" python
do
    if has "$binary"
    then
        python="$binary"
        break
    fi
done

# Default objcc to clang if available, otherwise use CC
if has clang; then
  objcc=clang
else
  objcc="$cc"
fi

if test "$mingw32" = "yes" ; then
  EXESUF=".exe"
  DSOSUF=".dll"
  LIBS="-lwinmm -lws2_32 -liphlpapi $LIBS"
  write_c_skeleton;
  if compile_prog "" "-liberty" ; then
    LIBS="-liberty $LIBS"
  fi
fi

werror=""

for opt do
  optarg=$(expr "x$opt" : 'x[^=]*=\(.*\)')
  case "$opt" in
  --help|-h) show_help=yes
  ;;
  --version|-V) exec cat $source_path/VERSION
  ;;
  --source-path=*)
  ;;
  --cc=*)
  ;;
  --host-cc=*) host_cc="$optarg"
  ;;
  --objcc=*) objcc="$optarg"
  ;;
  --make=*) make="$optarg"
  ;;
  --python=*) python="$optarg"
  ;;
  --extra-cflags=*)
  ;;
  --extra-ldflags=*)
  ;;
  --enable-debug-info)
  ;;
  --disable-debug-info)
  ;;
  --cpu=*)
  ;;
  --target-list=*) target_list="$optarg"
  ;;
  --static)
    static="yes"
  ;;
  --enable-debug-tcg) debug_tcg="yes"
  ;;
  --disable-debug-tcg) debug_tcg="no"
  ;;
  --enable-debug)
      # Enable debugging options that aren't excessively noisy
      debug_tcg="yes"
      debug="yes"
      strip_opt="no"
  ;;
  --disable-strip) strip_opt="no"
  ;;
  --enable-pie) pie="yes"
  ;;
  --disable-pie) pie="no"
  ;;
  --enable-werror) werror="yes"
  ;;
  --disable-werror) werror="no"
  ;;
  --enable-stack-protector) stack_protector="yes"
  ;;
  --disable-stack-protector) stack_protector="no"
  ;;
  --disable-membarrier) membarrier="no"
  ;;
  --enable-membarrier) membarrier="yes"
  ;;
  *)
      echo "ERROR: unknown option $opt"
      echo "Try '$0 --help' for more information"
      exit 1
  ;;
  esac
done

# Remove old dependency files to make sure that they get properly regenerated
rm -f *-config-devices.mak.d

if test -z "$python"
then
    error_exit "Python not found. Use --python=/path/to/python"
fi

# Note that if the Python conditional here evaluates True we will exit
# with status 1 which is a shell 'false' value.
if ! $python -c 'import sys; sys.exit(sys.version_info < (3,5))'; then
  error_exit "Cannot use '$python', Python >= 3.5 is required." \
      "Use --python=/path/to/python to specify a supported Python."
fi

# Preserve python version since some functionality is dependent on it
python_version=$($python -V 2>&1 | sed -e 's/Python\ //')

# The -B switch was added in Python 2.6.
# If it is supplied, compiled files are not written.
# Use it for Python versions which support it.
if $python -B -c 'import sys; sys.exit(0)' 2>/dev/null; then
  python="$python -B"
fi

case "$cpu" in
    ppc)
           CPU_CFLAGS="-m32"
           LDFLAGS="-m32 $LDFLAGS"
           ;;
    ppc64)
           CPU_CFLAGS="-m64"
           LDFLAGS="-m64 $LDFLAGS"
           ;;
    sparc)
           LDFLAGS="-m32 $LDFLAGS"
           CPU_CFLAGS="-m32 -mcpu=ultrasparc"
           ;;
    sparc64)
           LDFLAGS="-m64 $LDFLAGS"
           CPU_CFLAGS="-m64 -mcpu=ultrasparc"
           ;;
    s390)
           CPU_CFLAGS="-m31"
           LDFLAGS="-m31 $LDFLAGS"
           ;;
    s390x)
           CPU_CFLAGS="-m64"
           LDFLAGS="-m64 $LDFLAGS"
           ;;
    i386)
           CPU_CFLAGS="-m32"
           LDFLAGS="-m32 $LDFLAGS"
           cc_i386='$(CC) -m32'
           ;;
    x86_64)
           # ??? Only extremely old AMD cpus do not have cmpxchg16b.
           # If we truly care, we should simply detect this case at
           # runtime and generate the fallback to serial emulation.
           CPU_CFLAGS="-m64 -mcx16"
           LDFLAGS="-m64 $LDFLAGS"
           cc_i386='$(CC) -m32'
           ;;
    x32)
           CPU_CFLAGS="-mx32"
           LDFLAGS="-mx32 $LDFLAGS"
           cc_i386='$(CC) -m32'
           ;;
    # No special flags required for other host CPUs
esac

QEMU_CFLAGS="$CPU_CFLAGS $QEMU_CFLAGS"

default_target_list=""

mak_wilds=""

if [ "$softmmu" = "yes" ]; then
    mak_wilds="${mak_wilds} $source_path/default-configs/*-softmmu.mak"
fi

for config in $mak_wilds; do
    default_target_list="${default_target_list} $(basename "$config" .mak)"
done

if test x"$show_help" = x"yes" ; then
cat << EOF

Usage: configure [options]
Options: [defaults in brackets after descriptions]

Standard options:
  --help                   print this message
  --target-list=LIST       set target list (default: build everything)
$(echo Available targets: $default_target_list | \
  fold -s -w 53 | sed -e 's/^/                           /')

Advanced options (experts only):
  --source-path=PATH       path of source code [$source_path]
  --cc=CC                  use C compiler CC [$cc]
  --host-cc=CC             use C compiler CC [$host_cc] for code run at
                           build time
  --objcc=OBJCC            use Objective-C compiler OBJCC [$objcc]
  --extra-cflags=CFLAGS    append extra C compiler flags QEMU_CFLAGS
  --extra-ldflags=LDFLAGS  append extra linker flags LDFLAGS
  --make=MAKE              use specified make [$make]
  --python=PYTHON          use specified python [$python]
  --static                 enable static build [$static]
  --enable-debug-tcg       enable TCG debugging
  --disable-debug-tcg      disable TCG debugging (default)
  --enable-debug-info      enable debugging information (default)
  --disable-debug-info     disable debugging information
  --enable-debug           enable common debug build options
  --enable-sanitizers      enable default sanitizers
  --disable-strip          disable stripping binaries
  --disable-werror         disable compilation abort on warning
  --disable-stack-protector disable compiler-provided stack protection
  --enable-pie             build Position Independent Executables
  --disable-pie            do not build Position Independent Executables
  --cpu=CPU                Build for host CPU [$cpu]

NOTE: The object files are built at the place where configure is launched
EOF
exit 0
fi

# Consult white-list to determine whether to enable werror
# by default.  Only enable by default for git builds
z_version=$(cut -f3 -d. $source_path/VERSION)

if test -z "$werror" ; then
    if test -d "$source_path/.git" -a \
        \( "$linux" = "yes" -o "$mingw32" = "yes" \) ; then
        werror="yes"
    else
        werror="no"
    fi
fi

# check that the C compiler works.
cat > $TMPC <<EOF
int main(void) { return 0; }
EOF

if compile_object ; then
  : C compiler works ok
else
    error_exit "\"$cc\" either does not exist or does not work"
fi
if ! compile_prog ; then
    error_exit "\"$cc\" cannot build an executable (is your linker broken?)"
fi

if test "$bogus_os" = "yes"; then
    # Now that we know that we're not printing the help and that
    # the compiler works (so the results of the check_defines we used
    # to identify the OS are reliable), if we didn't recognize the
    # host OS we should stop now.
    error_exit "Unrecognized host OS (uname -s reports '$(uname -s)')"
fi

# Check whether the compiler matches our minimum requirements:
cat > $TMPC << EOF
#if defined(__clang_major__) && defined(__clang_minor__)
# ifdef __apple_build_version__
#  if __clang_major__ < 5 || (__clang_major__ == 5 && __clang_minor__ < 1)
#   error You need at least XCode Clang v5.1 to compile QEMU
#  endif
# else
#  if __clang_major__ < 3 || (__clang_major__ == 3 && __clang_minor__ < 4)
#   error You need at least Clang v3.4 to compile QEMU
#  endif
# endif
#elif defined(__GNUC__) && defined(__GNUC_MINOR__)
# if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 8)
#  error You need at least GCC v4.8 to compile QEMU
# endif
#else
# error You either need GCC or Clang to compiler QEMU
#endif
int main (void) { return 0; }
EOF
if ! compile_prog "" "" ; then
    error_exit "You need at least GCC v4.8 or Clang v3.4 (or XCode Clang v5.1)"
fi

gcc_flags="-Wold-style-declaration -Wold-style-definition -Wtype-limits"
gcc_flags="-Wformat-security -Wformat-y2k -Winit-self -Wignored-qualifiers $gcc_flags"
gcc_flags="-Wmissing-include-dirs -Wempty-body -Wnested-externs $gcc_flags"
gcc_flags="-Wendif-labels $gcc_flags"
gcc_flags="-Wno-initializer-overrides -Wexpansion-to-defined $gcc_flags"
gcc_flags="-Wno-string-plus-int -Wno-typedef-redefinition $gcc_flags"
# Note that we do not add -Werror to gcc_flags here, because that would
# enable it for all configure tests. If a configure test failed due
# to -Werror this would just silently disable some features,
# so it's too error prone.
cc_has_warning_flag() {
    write_c_skeleton;

    # Use the positive sense of the flag when testing for -Wno-wombat
    # support (gcc will happily accept the -Wno- form of unknown
    # warning options).
    optflag="$(echo $1 | sed -e 's/^-Wno-/-W/')"
    compile_prog "-Werror $optflag" ""
}

for flag in $gcc_flags; do
    if cc_has_warning_flag $flag ; then
        QEMU_CFLAGS="$QEMU_CFLAGS $flag"
    fi
done

if test "$stack_protector" != "no"; then
  gcc_flags="-fstack-protector-strong -fstack-protector-all"
  sp_on=0
  for flag in $gcc_flags; do
    # We need to check both a compile and a link, since some compiler
    # setups fail only on a .c->.o compile and some only at link time
    if do_cc $QEMU_CFLAGS -Werror $flag -c -o $TMPO $TMPC &&
       compile_prog "-Werror $flag" ""; then
      QEMU_CFLAGS="$QEMU_CFLAGS $flag"
      sp_on=1
      break
    fi
  done
  if test "$stack_protector" = yes; then
    if test $sp_on = 0; then
      error_exit "Stack protector not supported"
    fi
  fi
fi

# Disable -Wmissing-braces on older compilers that warn even for
# the "universal" C zero initializer {0}.
cat > $TMPC << EOF
struct {
  int a[2];
} x = {0};
EOF
if compile_object "-Werror" "" ; then
  :
else
  QEMU_CFLAGS="$QEMU_CFLAGS -Wno-missing-braces"
fi

# Static linking is not possible with modules or PIE
if test "$static" = "yes" ; then
  if test "$modules" = "yes" ; then
    error_exit "static and modules are mutually incompatible"
  fi
fi

cat > $TMPC << EOF

#ifdef __linux__
#  define THREAD __thread
#else
#  define THREAD
#endif
static THREAD int tls_var;
int main(void) { return tls_var; }
EOF

# Check we support --no-pie first; we will need this for building ROMs.
if compile_prog "-Werror -fno-pie" "-no-pie"; then
  CFLAGS_NOPIE="-fno-pie"
  LDFLAGS_NOPIE="-no-pie"
fi

if test "$static" = "yes"; then
  if test "$pie" != "no" && compile_prog "-fPIE -DPIE" "-static-pie"; then
    QEMU_CFLAGS="-fPIE -DPIE $QEMU_CFLAGS"
    QEMU_LDFLAGS="-static-pie $QEMU_LDFLAGS"
    pie="yes"
  elif test "$pie" = "yes"; then
    error_exit "-static-pie not available due to missing toolchain support"
  else
    QEMU_LDFLAGS="-static $QEMU_LDFLAGS"
    pie="no"
  fi
elif test "$pie" = "no"; then
  QEMU_CFLAGS="$CFLAGS_NOPIE $QEMU_CFLAGS"
  QEMU_LDFLAGS="$LDFLAGS_NOPIE $QEMU_LDFLAGS"
elif compile_prog "-fPIE -DPIE" "-pie"; then
  QEMU_CFLAGS="-fPIE -DPIE $QEMU_CFLAGS"
  QEMU_LDFLAGS="-pie $QEMU_LDFLAGS"
  pie="yes"
elif test "$pie" = "yes"; then
  error_exit "PIE not available due to missing toolchain support"
else
  echo "Disabling PIE due to missing toolchain support"
  pie="no"
fi

# Detect support for PT_GNU_RELRO + DT_BIND_NOW.
# The combination is known as "full relro", because .got.plt is read-only too.
if compile_prog "" "-Wl,-z,relro -Wl,-z,now" ; then
  QEMU_LDFLAGS="-Wl,-z,relro -Wl,-z,now $QEMU_LDFLAGS"
fi

##########################################
# __sync_fetch_and_and requires at least -march=i486. Many toolchains
# use i686 as default anyway, but for those that don't, an explicit
# specification is necessary

if test "$cpu" = "i386"; then
  cat > $TMPC << EOF
static int sfaa(int *ptr)
{
  return __sync_fetch_and_and(ptr, 0);
}

int main(void)
{
  int val = 42;
  val = __sync_val_compare_and_swap(&val, 0, 1);
  sfaa(&val);
  return val;
}
EOF
  if ! compile_prog "" "" ; then
    QEMU_CFLAGS="-march=i486 $QEMU_CFLAGS"
  fi
fi

#########################################
# Solaris specific configure tool chain decisions

if test "$solaris" = "yes" ; then
  if has ar; then
    :
  else
    if test -f /usr/ccs/bin/ar ; then
      error_exit "No path includes ar" \
          "Add /usr/ccs/bin to your path and rerun configure"
    fi
    error_exit "No path includes ar"
  fi
fi

if test -z "${target_list+xxx}" ; then
    target_list="$default_target_list"
else
    target_list=$(echo "$target_list" | sed -e 's/,/ /g')
fi

# Check that we recognised the target name; this allows a more
# friendly error message than if we let it fall through.
for target in $target_list; do
    case " $default_target_list " in
        *" $target "*)
            ;;
        *)
            error_exit "Unknown target name '$target'"
            ;;
    esac
done

# see if system emulation was really requested
case " $target_list " in
  *"-softmmu "*) softmmu=yes
  ;;
  *) softmmu=no
  ;;
esac

feature_not_found() {
  feature=$1
  remedy=$2

  error_exit "User requested feature $feature" \
      "configure was not able to find it." \
      "$remedy"
}

# ---
# big/little endian test
cat > $TMPC << EOF
short big_endian[] = { 0x4269, 0x4765, 0x4e64, 0x4961, 0x4e00, 0, };
short little_endian[] = { 0x694c, 0x7454, 0x654c, 0x6e45, 0x6944, 0x6e41, 0, };
extern int foo(short *, short *);
int main(int argc, char *argv[]) {
    return foo(big_endian, little_endian);
}
EOF

if compile_object ; then
    if grep -q BiGeNdIaN $TMPO ; then
        bigendian="yes"
    elif grep -q LiTtLeEnDiAn $TMPO ; then
        bigendian="no"
    else
        echo big/little test failed
    fi
else
    echo big/little test failed
fi

##########################################
# pthread probe
PTHREADLIBS_LIST="-pthread -lpthread -lpthreadGC2"

pthread=no
cat > $TMPC << EOF
#include <pthread.h>
static void *f(void *p) { return NULL; }
int main(void) {
  pthread_t thread;
  pthread_create(&thread, 0, f, 0);
  return 0;
}
EOF
if compile_prog "" "" ; then
  pthread=yes
else
  for pthread_lib in $PTHREADLIBS_LIST; do
    if compile_prog "" "$pthread_lib" ; then
      pthread=yes
      found=no
      for lib_entry in $LIBS; do
        if test "$lib_entry" = "$pthread_lib"; then
          found=yes
          break
        fi
      done
      if test "$found" = "no"; then
        LIBS="$pthread_lib $LIBS"
      fi
      break
    fi
  done
fi

if test "$mingw32" != yes -a "$pthread" = no; then
  error_exit "pthread check failed" \
      "Make sure to have the pthread libs and headers installed."
fi

# Search for bswap_32 function
byteswap_h=no
cat > $TMPC << EOF
#include <byteswap.h>
int main(void) { return bswap_32(0); }
EOF
if compile_prog "" "" ; then
  byteswap_h=yes
fi

# Search for bswap32 function
bswap_h=no
cat > $TMPC << EOF
#include <sys/endian.h>
#include <sys/types.h>
#include <machine/bswap.h>
int main(void) { return bswap32(0); }
EOF
if compile_prog "" "" ; then
  bswap_h=yes
fi

##########################################
# Do we need libm
cat > $TMPC << EOF
#include <math.h>
int main(int argc, char **argv) { return isnan(sin((double)argc)); }
EOF
if compile_prog "" "" ; then
  :
elif compile_prog "" "-lm" ; then
  LIBS="-lm $LIBS"
else
  error_exit "libm check failed"
fi

##########################################
# Do we need librt
# uClibc provides 2 versions of clock_gettime(), one with realtime
# support and one without. This means that the clock_gettime() don't
# need -lrt. We still need it for timer_create() so we check for this
# function in addition.
cat > $TMPC <<EOF
#include <signal.h>
#include <time.h>
int main(void) {
  timer_create(CLOCK_REALTIME, NULL, NULL);
  return clock_gettime(CLOCK_REALTIME, NULL);
}
EOF

if compile_prog "" "" ; then
  :
# we need pthread for static linking. use previous pthread test result
elif compile_prog "" "$pthread_lib -lrt" ; then
  LIBS="$LIBS -lrt"
fi

if test "$darwin" != "yes" -a "$mingw32" != "yes" -a "$solaris" != yes -a \
        "$haiku" != "yes" ; then
    libs_softmmu="-lutil $libs_softmmu"
fi

########################################
# check if we have valgrind/valgrind.h

valgrind_h=no
cat > $TMPC << EOF
#include <valgrind/valgrind.h>
int main(void) {
  return 0;
}
EOF
if compile_prog "" "" ; then
    valgrind_h=yes
fi

########################################
# check if cpuid.h is usable.

cat > $TMPC << EOF
#include <cpuid.h>
int main(void) {
    unsigned a, b, c, d;
    int max = __get_cpuid_max(0, 0);

    if (max >= 1) {
        __cpuid(1, a, b, c, d);
    }

    if (max >= 7) {
        __cpuid_count(7, 0, a, b, c, d);
    }

    return 0;
}
EOF
if compile_prog "" "" ; then
    cpuid_h=yes
fi

##########################################
# avx2 optimization requirement check
#
# There is no point enabling this if cpuid.h is not usable,
# since we won't be able to select the new routines.

if test $cpuid_h = yes; then
  cat > $TMPC << EOF
#pragma GCC push_options
#pragma GCC target("avx2")
#include <cpuid.h>
#include <immintrin.h>
static int bar(void *a) {
    __m256i x = *(__m256i *)a;
    return _mm256_testz_si256(x, x);
}
int main(int argc, char *argv[]) { return bar(argv[0]); }
EOF
  if compile_object "" ; then
    avx2_opt="yes"
  fi
fi

########################################
# check if __[u]int128_t is usable.

int128=no
cat > $TMPC << EOF
__int128_t a;
__uint128_t b;
int main (void) {
  a = a + b;
  b = a * b;
  a = a * a;
  return 0;
}
EOF
if compile_prog "" "" ; then
    int128=yes
fi

##########################################
# check for usable membarrier system call
if test "$membarrier" = "yes"; then
    have_membarrier=no
    if test "$mingw32" = "yes" ; then
        have_membarrier=yes
    elif test "$linux" = "yes" ; then
        cat > $TMPC << EOF
    #include <linux/membarrier.h>
    #include <sys/syscall.h>
    #include <unistd.h>
    #include <stdlib.h>
    int main(void) {
        syscall(__NR_membarrier, MEMBARRIER_CMD_QUERY, 0);
        syscall(__NR_membarrier, MEMBARRIER_CMD_SHARED, 0);
  exit(0);
    }
EOF
        if compile_prog "" "" ; then
            have_membarrier=yes
        fi
    fi
    if test "$have_membarrier" = "no"; then
      feature_not_found "membarrier" "membarrier system call not available"
    fi
else
    # Do not enable it by default even for Mingw32, because it doesn't
    # work on Wine.
    membarrier=no
fi

#########################################
# See if 128-bit atomic operations are supported.

atomic128=no
if test "$int128" = "yes"; then
  cat > $TMPC << EOF
int main(void)
{
  unsigned __int128 x = 0, y = 0;
  y = __atomic_load_16(&x, 0);
  __atomic_store_16(&x, y, 0);
  __atomic_compare_exchange_16(&x, &y, x, 0, 0, 0);
  return 0;
}
EOF
  if compile_prog "" "" ; then
    atomic128=yes
  fi
fi

cmpxchg128=no
if test "$int128" = yes -a "$atomic128" = no; then
  cat > $TMPC << EOF
int main(void)
{
  unsigned __int128 x = 0, y = 0;
  __sync_val_compare_and_swap_16(&x, y, x);
  return 0;
}
EOF
  if compile_prog "" "" ; then
    cmpxchg128=yes
  fi
fi

#########################################
# See if 64-bit atomic operations are supported.
# Note that without __atomic builtins, we can only
# assume atomic loads/stores max at pointer size.

cat > $TMPC << EOF
#include <stdint.h>
int main(void)
{
  uint64_t x = 0, y = 0;
#ifdef __ATOMIC_RELAXED
  y = __atomic_load_8(&x, 0);
  __atomic_store_8(&x, y, 0);
  __atomic_compare_exchange_8(&x, &y, x, 0, 0, 0);
  __atomic_exchange_8(&x, y, 0);
  __atomic_fetch_add_8(&x, y, 0);
#else
  typedef char is_host64[sizeof(void *) >= sizeof(uint64_t) ? 1 : -1];
  __sync_lock_test_and_set(&x, y);
  __sync_val_compare_and_swap(&x, y, 0);
  __sync_fetch_and_add(&x, y);
#endif
  return 0;
}
EOF
if compile_prog "" "" ; then
  atomic64=yes
fi

##########################################
# checks for sanitizers

have_asan=no
have_ubsan=no

if test "$sanitizers" = "yes" ; then
  write_c_skeleton
  if compile_prog "$CPU_CFLAGS -Werror -fsanitize=address" ""; then
      have_asan=yes
  fi

  # we could use a simple skeleton for flags checks, but this also
  # detect the static linking issue of ubsan, see also:
  # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=84285
  cat > $TMPC << EOF
#include <stdlib.h>
int main(void) {
    void *tmp = malloc(10);
    return *(int *)(tmp + 2);
}
EOF
  if compile_prog "$CPU_CFLAGS -Werror -fsanitize=undefined" ""; then
      have_ubsan=yes
  fi
fi

##########################################
# check if we have posix_memalign()

posix_memalign=no
cat > $TMPC << EOF
#include <stdlib.h>
int main(void) {
    void *p;
    return posix_memalign(&p, 8, 8);
}
EOF
if compile_prog "" "" ; then
    posix_memalign=yes
fi

# check for _Static_assert()

have_static_assert=no
cat > $TMPC << EOF
_Static_assert(1, "success");
int main(void) {
    return 0;
}
EOF
if compile_prog "" "" ; then
    have_static_assert=yes
fi

##########################################
# End of CC checks
# After here, no more $cc or $ld runs

if test "$have_asan" = "yes"; then
  CFLAGS="-fsanitize=address $CFLAGS"
fi
if test "$have_ubsan" = "yes"; then
  CFLAGS="-fsanitize=undefined $CFLAGS"
fi

# Now we've finished running tests it's OK to add -Werror to the compiler flags
if test "$werror" = "yes"; then
    QEMU_CFLAGS="-Werror $QEMU_CFLAGS"
fi

if test "$solaris" = "no" ; then
    if $ld --version 2>/dev/null | grep "GNU ld" >/dev/null 2>/dev/null ; then
        LDFLAGS="-Wl,--warn-common $LDFLAGS"
    fi
fi

# Use ASLR, no-SEH and DEP if available
if test "$mingw32" = "yes" ; then
    for flag in --dynamicbase --no-seh --nxcompat; do
        if $ld --help 2>/dev/null | grep ".$flag" >/dev/null 2>/dev/null ; then
            LDFLAGS="-Wl,$flag $LDFLAGS"
        fi
    done
fi

# Disable OpenBSD W^X if available
if test "$tcg" = "yes" && test "$targetos" = "OpenBSD"; then
    cat > $TMPC <<EOF
    int main(void) { return 0; }
EOF
    wx_ldflags="-Wl,-z,wxneeded"
    if compile_prog "" "$wx_ldflags"; then
        QEMU_LDFLAGS="$QEMU_LDFLAGS $wx_ldflags"
    fi
fi

echo "Source path       $source_path"
echo "C compiler        $cc"
echo "Host C compiler   $host_cc"
echo "Objective-C compiler $objcc"
echo "ARFLAGS           $ARFLAGS"
echo "CFLAGS            $CFLAGS"
echo "QEMU_CFLAGS       $QEMU_CFLAGS"
echo "LDFLAGS           $LDFLAGS"
echo "make              $make"
echo "python            $python ($python_version)"
echo "host CPU          $cpu"
echo "host big endian   $bigendian"
echo "target list       $target_list"
echo "strip binaries    $strip_opt"
echo "static build      $static"
echo "mingw32 support   $mingw32"
echo "PIE               $pie"
echo "membarrier        $membarrier"
echo "TCG support       $tcg"
if test "$tcg" = "yes" ; then
    echo "TCG debug enabled $debug_tcg"
    echo "TCG interpreter   $tcg_interpreter"
fi
echo "avx2 optimization $avx2_opt"

if test "$supported_cpu" = "no"; then
    echo
    echo "WARNING: SUPPORT FOR THIS HOST CPU WILL GO AWAY IN FUTURE RELEASES!"
    echo
    echo "CPU host architecture $cpu support is not currently maintained."
    echo "The QEMU project intends to remove support for this host CPU in"
    echo "a future release if nobody volunteers to maintain it and to"
    echo "provide a build host for our continuous integration setup."
    echo "configure has succeeded and you can continue to build, but"
    echo "if you care about QEMU on this platform you should contact"
    echo "us upstream at qemu-devel@nongnu.org."
fi

if test "$supported_os" = "no"; then
    echo
    echo "WARNING: SUPPORT FOR THIS HOST OS WILL GO AWAY IN FUTURE RELEASES!"
    echo
    echo "CPU host OS $targetos support is not currently maintained."
    echo "The QEMU project intends to remove support for this host CPU in"
    echo "a future release if nobody volunteers to maintain it and to"
    echo "provide a build host for our continuous integration setup."
    echo "configure has succeeded and you can continue to build, but"
    echo "if you care about QEMU on this platform you should contact"
    echo "us upstream at qemu-devel@nongnu.org."
fi

config_host_mak="config-host.mak"

echo "# Automatically generated by configure - do not modify" > $config_host_mak
echo >> $config_host_mak

echo all: >> $config_host_mak
echo "libs_softmmu=$libs_softmmu" >> $config_host_mak

echo "ARCH=$ARCH" >> $config_host_mak

if test "$debug_tcg" = "yes" ; then
  echo "CONFIG_DEBUG_TCG=y" >> $config_host_mak
fi
if test "$strip_opt" = "yes" ; then
  echo "STRIP=${strip}" >> $config_host_mak
fi
if test "$bigendian" = "yes" ; then
  echo "HOST_WORDS_BIGENDIAN=y" >> $config_host_mak
fi
if test "$mingw32" = "yes" ; then
  echo "CONFIG_WIN32=y" >> $config_host_mak
  rc_version=$(cat $source_path/VERSION)
  version_major=${rc_version%%.*}
  rc_version=${rc_version#*.}
  version_minor=${rc_version%%.*}
  rc_version=${rc_version#*.}
  version_subminor=${rc_version%%.*}
  version_micro=0
  echo "CONFIG_FILEVERSION=$version_major,$version_minor,$version_subminor,$version_micro" >> $config_host_mak
  echo "CONFIG_PRODUCTVERSION=$version_major,$version_minor,$version_subminor,$version_micro" >> $config_host_mak
else
  echo "CONFIG_POSIX=y" >> $config_host_mak
fi

if test "$linux" = "yes" ; then
  echo "CONFIG_LINUX=y" >> $config_host_mak
fi

if test "$solaris" = "yes" ; then
  echo "CONFIG_SOLARIS=y" >> $config_host_mak
fi
if test "$static" = "yes" ; then
  echo "CONFIG_STATIC=y" >> $config_host_mak
fi
echo "SRC_PATH=$source_path" >> $config_host_mak
echo "TARGET_DIRS=$target_list" >> $config_host_mak
if test "$byteswap_h" = "yes" ; then
  echo "CONFIG_BYTESWAP_H=y" >> $config_host_mak
fi
if test "$bswap_h" = "yes" ; then
  echo "CONFIG_MACHINE_BSWAP_H=y" >> $config_host_mak
fi
if test "$membarrier" = "yes" ; then
  echo "CONFIG_MEMBARRIER=y" >> $config_host_mak
fi
if test "$tcg" = "yes"; then
  echo "CONFIG_TCG=y" >> $config_host_mak
  if test "$tcg_interpreter" = "yes" ; then
    echo "CONFIG_TCG_INTERPRETER=y" >> $config_host_mak
  fi
fi

if test "$avx2_opt" = "yes" ; then
  echo "CONFIG_AVX2_OPT=y" >> $config_host_mak
fi

# XXX: suppress that
if [ "$bsd" = "yes" ] ; then
  echo "CONFIG_BSD=y" >> $config_host_mak
fi

if test "$valgrind_h" = "yes" ; then
  echo "CONFIG_VALGRIND_H=y" >> $config_host_mak
fi

if test "$cpuid_h" = "yes" ; then
  echo "CONFIG_CPUID_H=y" >> $config_host_mak
fi

if test "$int128" = "yes" ; then
  echo "CONFIG_INT128=y" >> $config_host_mak
fi

if test "$atomic128" = "yes" ; then
  echo "CONFIG_ATOMIC128=y" >> $config_host_mak
fi

if test "$cmpxchg128" = "yes" ; then
  echo "CONFIG_CMPXCHG128=y" >> $config_host_mak
fi

if test "$atomic64" = "yes" ; then
  echo "CONFIG_ATOMIC64=y" >> $config_host_mak
fi

if test "$have_static_assert" = "yes" ; then
  echo "CONFIG_STATIC_ASSERT=y" >> $config_host_mak
fi

if test "$tcg_interpreter" = "yes"; then
  QEMU_INCLUDES="-I\$(SRC_PATH)/tcg/tci $QEMU_INCLUDES"
elif test "$ARCH" = "sparc64" ; then
  QEMU_INCLUDES="-I\$(SRC_PATH)/tcg/sparc $QEMU_INCLUDES"
elif test "$ARCH" = "s390x" ; then
  QEMU_INCLUDES="-I\$(SRC_PATH)/tcg/s390 $QEMU_INCLUDES"
elif test "$ARCH" = "x86_64" -o "$ARCH" = "x32" ; then
  QEMU_INCLUDES="-I\$(SRC_PATH)/tcg/i386 $QEMU_INCLUDES"
elif test "$ARCH" = "ppc64" ; then
  QEMU_INCLUDES="-I\$(SRC_PATH)/tcg/ppc $QEMU_INCLUDES"
elif test "$ARCH" = "riscv32" || test "$ARCH" = "riscv64" ; then
  QEMU_INCLUDES="-I\$(SRC_PATH)/tcg/riscv $QEMU_INCLUDES"
else
  QEMU_INCLUDES="-I\$(SRC_PATH)/tcg/\$(ARCH) $QEMU_INCLUDES"
fi
QEMU_INCLUDES="-I\$(SRC_PATH)/tcg $QEMU_INCLUDES"

echo "MAKE=$make" >> $config_host_mak
echo "PYTHON=$python" >> $config_host_mak
echo "PYTHON_VERSION=$python_version" >> $config_host_mak
echo "CC=$cc" >> $config_host_mak
echo "CC_I386=$cc_i386" >> $config_host_mak
echo "HOST_CC=$host_cc" >> $config_host_mak
echo "OBJCC=$objcc" >> $config_host_mak
echo "AR=$ar" >> $config_host_mak
echo "ARFLAGS=$ARFLAGS" >> $config_host_mak
echo "AS=$as" >> $config_host_mak
echo "CPP=$cpp" >> $config_host_mak
echo "OBJCOPY=$objcopy" >> $config_host_mak
echo "LD=$ld" >> $config_host_mak
echo "NM=$nm" >> $config_host_mak
echo "CFLAGS=$CFLAGS" >> $config_host_mak
echo "CFLAGS_NOPIE=$CFLAGS_NOPIE" >> $config_host_mak
echo "QEMU_CFLAGS=$QEMU_CFLAGS" >> $config_host_mak
echo "QEMU_INCLUDES=$QEMU_INCLUDES" >> $config_host_mak
echo "LDFLAGS=$LDFLAGS" >> $config_host_mak
echo "LDFLAGS_NOPIE=$LDFLAGS_NOPIE" >> $config_host_mak
echo "LIBS+=$LIBS" >> $config_host_mak
echo "EXESUF=$EXESUF" >> $config_host_mak
echo "DSOSUF=$DSOSUF" >> $config_host_mak
echo "LDFLAGS_SHARED=$LDFLAGS_SHARED" >> $config_host_mak

for target in $target_list; do
target_dir="$target"
config_target_mak=$target_dir/config-target.mak
target_name=$(echo $target | cut -d '-' -f 1)
target_aligned_only="no"
case "$target_name" in
  alpha|hppa|mips64el|mips64|mipsel|mips|mipsn32|mipsn32el|sh4|sh4eb|sparc|sparc64|sparc32plus|xtensa|xtensaeb)
  target_aligned_only="yes"
  ;;
esac
target_bigendian="no"
case "$target_name" in
  aarch64eb|armeb|lm32|m68k|microblaze|mips|mipsn32|mips64|moxie|or32|ppc|ppcemb|ppc64|ppc64abi32|s390x|sh4eb|sparc|sparc64|sparc32plus|xtensaeb)
  target_bigendian="yes"
  ;;
esac
target_softmmu="yes"
case "$target" in
  ${target_name}-softmmu)
    target_softmmu="yes"
    ;;
  *)
    error_exit "Target '$target' not recognised"
    exit 1
    ;;
esac

mkdir -p $target_dir
echo "# Automatically generated by configure - do not modify" > $config_target_mak

bflt="no"
mttcg="no"

TARGET_ARCH="$target_name"
TARGET_BASE_ARCH=""

case "$target_name" in
  i386)
  ;;
  x86_64)
    TARGET_BASE_ARCH=i386
  ;;
  alpha)
  ;;
  arm|armeb)
    TARGET_ARCH=arm
    mttcg="yes"
    bflt="yes"
  ;;
  aarch64|aarch64eb)
    TARGET_BASE_ARCH=arm
    TARGET_ARCH=aarch64
    bflt="yes"
    mttcg="yes"
  ;;
  cris)
  ;;
  lm32)
  ;;
  m68k)
    bflt="yes"
  ;;
  microblaze|microblazeel)
    TARGET_ARCH=microblaze
    bflt="yes"
  ;;
  mips|mipsel)
    TARGET_ARCH=mips
    echo "TARGET_ABI_MIPSO32=y" >> $config_target_mak
  ;;
  mipsn32|mipsn32el)
    TARGET_ARCH=mips64
    TARGET_BASE_ARCH=mips
    echo "TARGET_ABI_MIPSN32=y" >> $config_target_mak
    echo "TARGET_ABI32=y" >> $config_target_mak
  ;;
  mips64|mips64el)
    TARGET_ARCH=mips64
    TARGET_BASE_ARCH=mips
    echo "TARGET_ABI_MIPSN64=y" >> $config_target_mak
  ;;
  tricore)
  ;;
  moxie)
  ;;
  or32)
    TARGET_ARCH=openrisc
    TARGET_BASE_ARCH=openrisc
  ;;
  ppc)
  ;;
  ppcemb)
    TARGET_BASE_ARCH=ppc
  ;;
  ppc64)
    TARGET_BASE_ARCH=ppc
  ;;
  ppc64le)
    TARGET_ARCH=ppc64
    TARGET_BASE_ARCH=ppc
  ;;
  ppc64abi32)
    TARGET_ARCH=ppc64
    TARGET_BASE_ARCH=ppc
    echo "TARGET_ABI32=y" >> $config_target_mak
  ;;
  riscv32)
    TARGET_BASE_ARCH=riscv
    TARGET_ABI_DIR=riscv
  ;;
  riscv64)
    TARGET_BASE_ARCH=riscv
    TARGET_ABI_DIR=riscv
  ;;
  sh4|sh4eb)
    TARGET_ARCH=sh4
    bflt="yes"
  ;;
  sparc)
  ;;
  sparc64)
    TARGET_BASE_ARCH=sparc
  ;;
  sparc32plus)
    TARGET_ARCH=sparc64
    TARGET_BASE_ARCH=sparc
    echo "TARGET_ABI32=y" >> $config_target_mak
  ;;
  s390x)
  ;;
  unicore32)
  ;;
  xtensa|xtensaeb)
    TARGET_ARCH=xtensa
  ;;
  *)
    error_exit "Unsupported target CPU"
  ;;
esac
# TARGET_BASE_ARCH needs to be defined after TARGET_ARCH
if [ "$TARGET_BASE_ARCH" = "" ]; then
  TARGET_BASE_ARCH=$TARGET_ARCH
fi

symlink "$source_path/Makefile.target" "$target_dir/Makefile"

upper() {
    echo "$@"| LC_ALL=C tr '[a-z]' '[A-Z]'
}

target_arch_name="$(upper $TARGET_ARCH)"
echo "TARGET_$target_arch_name=y" >> $config_target_mak
echo "TARGET_NAME=$target_name" >> $config_target_mak
echo "TARGET_BASE_ARCH=$TARGET_BASE_ARCH" >> $config_target_mak
if test "$target_aligned_only" = "yes" ; then
  echo "TARGET_ALIGNED_ONLY=y" >> $config_target_mak
fi
if test "$target_bigendian" = "yes" ; then
  echo "TARGET_WORDS_BIGENDIAN=y" >> $config_target_mak
fi
if test "$target_softmmu" = "yes" ; then
  echo "CONFIG_SOFTMMU=y" >> $config_target_mak
  if test "$mttcg" = "yes" ; then
    echo "TARGET_SUPPORTS_MTTCG=y" >> $config_target_mak
  fi
fi

# generate QEMU_CFLAGS/LDFLAGS for targets

cflags=""
ldflags=""

case "$ARCH" in
alpha)
  # Ensure there's only a single GP
  cflags="-msmall-data $cflags"
;;
esac

echo "LDFLAGS+=$ldflags" >> $config_target_mak
echo "QEMU_CFLAGS+=$cflags" >> $config_target_mak
echo "QEMU_CFLAGS+=-include ${target_name}.h" >> $config_target_mak

done # for target in $targets

# Save the configure command line for later reuse.
cat <<EOD >config.status
#!/bin/sh
# Generated by configure.
# Run this file to recreate the current configuration.
# Compiler output produced by configure, useful for debugging
# configure, is in config.log if it exists.
EOD

preserve_env() {
    envname=$1

    eval envval=\$$envname

    if test -n "$envval"
    then
  echo "$envname='$envval'" >> config.status
  echo "export $envname" >> config.status
    else
  echo "unset $envname" >> config.status
    fi
}

# Preserve various env variables that influence what
# features/build target configure will detect
preserve_env AR
preserve_env AS
preserve_env CC
preserve_env CPP
preserve_env CXX
preserve_env INSTALL
preserve_env LD
preserve_env LD_LIBRARY_PATH
preserve_env LIBTOOL
preserve_env MAKE
preserve_env NM
preserve_env OBJCOPY
preserve_env PATH
preserve_env PKG_CONFIG
preserve_env PKG_CONFIG_LIBDIR
preserve_env PKG_CONFIG_PATH
preserve_env PYTHON
preserve_env SDL_CONFIG
preserve_env SDL2_CONFIG
preserve_env SMBD
preserve_env STRIP
preserve_env WINDRES

printf "exec" >>config.status
printf " '%s'" "$0" "$@" >>config.status
echo ' "$@"' >>config.status
chmod +x config.status

rm -r "$TMPDIR1"
