#!/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
}

# default parameters
source_path=$(dirname "$0")
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"
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"

# 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_CFLAGS="$optarg"
  ;;
  --extra-ldflags=*) LDFLAGS="$optarg $LDFLAGS"
                     EXTRA_LDFLAGS="$optarg"
  ;;
  --disable-tcg) tcg="no"
  ;;
  --enable-tcg) tcg="yes"
  ;;
  --enable-debug-info) debug_info="yes"
  ;;
  --disable-debug-info) debug_info="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 $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)/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
}

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'
else
  targetos=$(uname -s)
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 __ia64__ ; then
  cpu="ia64"
elif check_define __s390__ ; then
  if check_define __s390x__ ; then
    cpu="s390x"
  else
    cpu="s390"
  fi
elif check_define __arm__ ; then
  cpu="arm"
elif check_define __aarch64__ ; then
  cpu="aarch64"
elif check_define __hppa__ ; then
  cpu="hppa"
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|sparc64|x32)
    cpu="$cpu"
  ;;
  i386|i486|i586|i686|i86pc|BePC)
    cpu="i386"
  ;;
  x86_64|amd64)
    cpu="x86_64"
  ;;
  armv*b|armv*l|arm)
    cpu="arm"
  ;;
  aarch64|aarch64eb)
    cpu="aarch64"
  ;;
  mips*)
    cpu="mips"
  ;;
  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"
;;
GNU/kFreeBSD)
  bsd="yes"
;;
FreeBSD)
  bsd="yes"
  make="${MAKE-gmake}"
  # needed for kinfo_getvmmap(3) in libutil.h
  LIBS="-lutil $LIBS"
;;
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"
;;
SunOS)
  solaris="yes"
  make="${MAKE-gmake}"
  ld="gld"
  needs_libsunmath="no"
  solarisrev=$(uname -r | cut -f2 -d.)
  if [ "$cpu" = "i386" -o "$cpu" = "x86_64" ] ; then
    if test "$solarisrev" -le 9 ; then
      if test -f /opt/SUNWspro/prod/lib/libsunmath.so.1; then
        needs_libsunmath="yes"
        QEMU_CFLAGS="-I/opt/SUNWspro/prod/include/cc $QEMU_CFLAGS"
        LDFLAGS="-L/opt/SUNWspro/prod/lib -R/opt/SUNWspro/prod/lib $LDFLAGS"
        LIBS="-lsunmath $LIBS"
      else
        error_exit "QEMU will not link correctly on Solaris 8/X86 or 9/x86 without" \
            "libsunmath from the Sun Studio compilers tools, due to a lack of" \
            "C99 math features in libm.so in Solaris 8/x86 and Solaris 9/x86" \
            "Studio 11 can be downloaded from www.sun.com."
      fi
    fi
  fi
# 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="yes"
;;
esac

: ${make=${MAKE-make}}
: ${python=${PYTHON-python}}

# 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"
  QEMU_CFLAGS="-DWIN32_LEAN_AND_MEAN -DWINVER=0x501 $QEMU_CFLAGS"
  # enable C99/POSIX format strings (needs mingw32-runtime 3.15 or later)
  QEMU_CFLAGS="-D__USE_MINGW_ANSI_STDIO=1 $QEMU_CFLAGS"
  LIBS="-lwinmm -lws2_32 -liphlpapi $LIBS"
cat > $TMPC << EOF
int main(void) { return 0; }
EOF
  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"
    LDFLAGS="-static $LDFLAGS"
  ;;
  --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"
  ;;
  *)
      echo "ERROR: unknown option $opt"
      echo "Try '$0 --help' for more information"
      exit 1
  ;;
  esac
done

if ! has $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 < (2,4) or sys.version_info >= (3,))'; then
  error_exit "Cannot use '$python', Python 2.4 or later is required." \
      "Note that Python 3 or later is not yet supported." \
      "Use --python=/path/to/python to specify a supported Python."
fi

# 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"
EXTRA_CFLAGS="$CPU_CFLAGS $EXTRA_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
  --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

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 $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.
cat > $TMPC << EOF
int main(void) { return 0; }
EOF
for flag in $gcc_flags; do
    # 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 $flag | sed -e 's/^-Wno-/-W/')"
    if compile_prog "-Werror $optflag" "" ; 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

# Workaround for http://gcc.gnu.org/PR55489.  Happens with -fPIE/-fPIC and
# large functions that use global variables.  The bug is in all releases of
# GCC, but it became particularly acute in 4.6.x and 4.7.x.  It is fixed in
# 4.7.3 and 4.8.0.  We should be able to delete this at the end of 2013.
cat > $TMPC << EOF
#if __GNUC__ == 4 && (__GNUC_MINOR__ == 6 || (__GNUC_MINOR__ == 7 && __GNUC_PATCHLEVEL__ <= 2))
int main(void) { return 0; }
#else
#error No bug in this compiler.
#endif
EOF
if compile_prog "-Werror -fno-gcse" "" ; then
  TRANSLATE_OPT_CFLAGS=-fno-gcse
fi

if test "$static" = "yes" ; then
  if test "$pie" = "yes" ; then
    error_exit "static and pie are mutually incompatible"
  else
    pie="no"
  fi
fi

if test "$pie" = ""; then
  case "$cpu-$targetos" in
    i386-Linux|x86_64-Linux|x32-Linux|i386-OpenBSD|x86_64-OpenBSD)
      ;;
    *)
      pie="no"
      ;;
  esac
fi

if test "$pie" != "no" ; then
  cat > $TMPC << EOF

#ifdef __linux__
#  define THREAD __thread
#else
#  define THREAD
#endif

static THREAD int tls_var;

int main(void) { return tls_var; }

EOF
  if compile_prog "-fPIE -DPIE" "-pie"; then
    QEMU_CFLAGS="-fPIE -DPIE $QEMU_CFLAGS"
    LDFLAGS="-pie $LDFLAGS"
    pie="yes"
    if compile_prog "" "-Wl,-z,relro -Wl,-z,now" ; then
      LDFLAGS="-Wl,-z,relro -Wl,-z,now $LDFLAGS"
    fi
  else
    if 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
  fi

  if compile_prog "-fno-pie" "-nopie"; then
    CFLAGS_NOPIE="-fno-pie"
    LDFLAGS_NOPIE="-nopie"
  fi
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.

cpuid_h=no
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

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

int128=no
cat > $TMPC << EOF
#if defined(__clang_major__) && defined(__clang_minor__)
# if ((__clang_major__ < 3) || (__clang_major__ == 3) && (__clang_minor__ < 2))
#  error __int128_t does not work in CLANG before 3.2
# endif
#endif
__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

#########################################
# 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

#########################################
# 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

# 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

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"
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"
if test -n "$sparc_cpu"; then
    echo "Target Sparc Arch $sparc_cpu"
fi
echo "PIE               $pie"
echo "TCG support       $tcg"
if test "$tcg" = "yes" ; then
    echo "TCG debug enabled $debug_tcg"
    echo "TCG interpreter   $tcg_interpreter"
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 "extra_cflags=$EXTRA_CFLAGS" >> $config_host_mak
echo "extra_ldflags=$EXTRA_LDFLAGS" >> $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
  echo "CONFIG_SOLARIS_VERSION=$solarisrev" >> $config_host_mak
  if test "$needs_libsunmath" = "yes" ; then
    echo "CONFIG_NEEDS_LIBSUNMATH=y" >> $config_host_mak
  fi
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 "$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

# 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 "$atomic64" = "yes" ; then
  echo "CONFIG_ATOMIC64=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"
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 "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
if test "$cross_prefix" != ""; then
  echo "AUTOCONF_HOST := --host=${cross_prefix%-}"     >> $config_host_mak
else
  echo "AUTOCONF_HOST := "                             >> $config_host_mak
fi
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
echo "TRANSLATE_OPT_CFLAGS=$TRANSLATE_OPT_CFLAGS" >> $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_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
  ;;
  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_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
printf "exec" >>config.status
printf " '%s'" "$0" "$@" >>config.status
echo ' "$@"' >>config.status
chmod +x config.status

rm -r "$TMPDIR1"
