#!/bin/sh # # Copyright 2011 # Kaz Kylheku # Vancouver, Canada # All rights reserved. # # BSD License: # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # 3. The name of the author may not be used to endorse or promote # products derived from this software without specific prior # written permission. # # THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR # IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. # # Save command line in a way that can be re-run. # This takes care of spaces, but if there are shell-meta characters # in the arguments, oops. # set -u cmdline= for arg in "$0" "$@" ; do [ -n "$cmdline" ] && cmdline="$cmdline " case $arg in *" "* | " "* | *" " ) cmdline=$cmdline$(printf "\"%s\"" "$arg") ;; * ) cmdline=$cmdline$arg ;; esac done # # Parse configuration variables # while [ $# -gt 0 ] ; do case $1 in --no-* ) var=${1#--no-} val= ;; --*=* ) var=${1%%=*} var=${var#--} val=${1#*=} ;; --*= ) var=${1%%=*} var=${var#--} val= ;; --* ) var=${1#--} val=y ;; *=* ) var=${1%%=*} val=${1#*=} ;; *= ) var=${1%%=*} val= ;; * ) printf "$0: '$1' doesn't look like a configuration variable assignment\n" printf "$0: use --help to get help\n" exit 1 esac if ! printf $var | grep -q -E '^[A-Za-z_][A-Za-z0-9_]*$' ; then printf "$0: '$var' isn't a proper configuration variable name\n" exit 1 fi eval "$var='$val'" shift done # # Establish default values for any variables that are not specified # on the command line. The default derivations from prefix are in # Make syntax. They go verbatim into the generated config.make. # This way they can be overridden more flexibly at make time. # # # non-config # help=${help-} # # config # prefix=${prefix-/usr/local} install_prefix=${install_prefix-} bindir=${datadir-'$(prefix)/bin'} datadir=${datadir-'$(prefix)/share/txr'} mandir=${mandir-'$(prefix)/share/man'} cross=${cross-} compiler_prefix=${compiler_prefix-} ccname=${ccname-gcc} cc=${cc-'$(cross)$(compiler_prefix)$(ccname)'} intptr=${intptr-} tool_prefix=${tool_prefix-} lex=${lex-'$(cross)$(tool_prefix)flex'} lexlib=${lexlib--lfl} yaccname_given=${yaccname+yes} yaccname=${yaccname-} yacc_given=${yacc+yes} yacc=${yacc-'$(cross)$(tool_prefix)$(yaccname)'} nm=${nm-'$(cross)$(tool_prefix)nm'} opt_flags=${opt_flags--O2} lang_flags=${lang_flags--ansi -D_POSIX_C_SOURCE=2} diag_flags=${diag_flags--Wall -Wmissing-prototypes -Wstrict-prototypes} debug_flags=${debug_flags--g} inline=${inline-} platform_flags=${platform_flags-} remove_flags=${remove_flags-} lex_dbg_flags=${lex_dbg_flags-} txr_dbg_opts=${txr_dbg_opts---gc-debug} valgrind=${valgrind-} lit_align=${lit_align-} extra_debugging=${extra_debugging-} mpi_version=1.8.6 have_quilt= have_patch= # # If --help was given (or --help= or help=) then # print help and exit. The termination status is failed, to indicate # that configuration was not done. # if [ -n "$help" ] ; then cat <&1) set -- $output if [ $1 != "GNU" -o $2 != "Make" ] ; then printf "missing\n" exit 1 fi make_version=$3 save_ifs=$IFS ; IFS=. ; set -- $make_version ; IFS=$save_ifs if [ $1 -lt 3 -o \( $1 -eq 3 -a $2 -lt 80 \) ] ; then printf "too old (%s found, 3.80 or newer needed)\n" $make_version exit 1 else printf "yes (%s found)\n" $make_version fi # # Verify sanity of --prefix and other directories. # printf "Checking installation paths:\n" for name in prefix bindir datadir mandir; do eval path="\$install_prefix\${$name}" printf "\$(install_prefix)\$(%s)=%s ... " $name "$path" test_access=y case "$path" in " "* | *" "* | *" " ) printf "incorrect (contains spaces)\n" exit 1 ;; -* ) printf "incorrect (resembles a command option)\n" exit 1 ;; *'$('* ) # It's a make expression; can't test it test_access= ;; /* ) ;; * ) printf "incorrect (must be absolute path)\n" exit 1 ;; esac if [ $test_access ] ; then test_prefix=$path while true ; do if [ -e $test_prefix ] ; then if [ ! -d $test_prefix ] ; then printf "incorrect ('%s' is not a directory)!\n" $test_prefix exit 1 fi if [ ! -w $test_prefix ] ; then printf "okay\n (but no write access to '%s'\n" $test_prefix printf " so 'make install' will require root privileges)\n" else printf "okay\n" fi break fi test_prefix=$(dirname $test_prefix) done else printf "okay\n (make variable derivation)\n" fi done # # First, we have to figure out whether we are configured straight # in the source directory, or whether we are in a separate build directory. # In the latter case, we set up a symbolic link to the Makefile. # source_dir="$(dirname $0)" # # Compute an absolute path to the source directory. # top_srcdir="$(cd "$source_dir" ; pwd -P)" printf "Checking source directory %s ..." "$top_srcdir" case "$top_srcdir" in " "* | *" "* | *" " ) printf " bad (contains spaces)\n" exit 1 ;; * ) printf " okay\n" ;; esac if [ "$source_dir" != "." ] ; then printf "Symlinking Makefile -> $source_dir/Makefile\n" ln -sf "$source_dir/Makefile" . else printf "Warning: its recommended to build in a separate directory\n" fi gen_config_make() { cat > config.make < config.h /* * Header file automatically generated by $0. * Tweaking this file may seem like a good temporary workaround * than tweak the file, but you probably should fix the script * to do the job. In any case, be aware that you will lose your * changes if you re-run $0. */ ! # # Check C compiler sanity # printf "Checking whether your C compiler can make a simple executable ... " cat > conftest.c < int main(void) { printf("Hello, world!\n"); return 0; } ! rm -f conftest if ! make conftest > conftest.err 2>&1 || ! [ -x conftest ] ; then printf "failed\n\n" printf "Errors from compilation: \n\n" cat conftest.err exit 1 fi rm -f conftest printf "okay\n" # # Check what kind of C type we have for integers wider than long, # if any. # printf "Checking what C type we have for integers wider than \"long\" ... " longlong= for try_type in int64 __int64 "long long" ; do cat > conftest.c < conftest.err 2>&1 ; then longlong=$try_type break fi done if [ -n "$longlong" ] ; then printf '"%s"\n' "$longlong" printf "#define HAVE_LONGLONG_T 1\n" >> config.h printf "typedef $longlong longlong_t;\n" >> config.h else printf "none\n" fi printf "Checking what C type we have for unsigned integers wider than \"long\" ... " ulonglong= for try_type in uint64 __uint64 "unsigned long long" ; do cat > conftest.c < conftest.err 2>&1 ; then ulonglong=$try_type break fi done if [ -n "$ulonglong" ] ; then printf '"%s"\n' "$ulonglong" printf "#define HAVE_ULONGLONG_T 1\n" >> config.h printf "typedef $ulonglong ulonglong_t;\n" >> config.h else printf "none\n" fi printf "Checking what C type we have for integers wider than \"long long\" ... " superlong= for try_type in int128 int128_t __int128 __int128_t ; do cat > conftest.c < conftest.err 2>&1 ; then superlong=$try_type break fi done if [ -n "$superlong" ] ; then printf '"%s"\n' "$superlong" printf "#define HAVE_SUPERLONG_T 1\n" >> config.h printf "typedef $superlong superlong_t;\n" >> config.h else printf "none\n" fi printf "Checking what C type we have for u. integers wider than \"long long\" ... " usuperlong= for try_type in uint128 uint128_t __uint128 __uint128_t ; do cat > conftest.c < conftest.err 2>&1 ; then usuperlong=$try_type break fi done if [ -n "$usuperlong" ] ; then printf '"%s"\n' "$usuperlong" printf "#define HAVE_USUPERLONG_T 1\n" >> config.h printf "typedef $usuperlong usuperlong_t;\n" >> config.h else printf "none\n" fi printf "Checking what C integer type can hold a pointer ... " if [ -z "$intptr" ] ; then cat > conftest.c < conftest.err 2>&1 ; then printf "failed\n\n" printf "Errors from compilation: \n\n" cat conftest.err exit 1 fi SIZEOF_PTR=0 SIZEOF_SHORT=0 SIZEOF_INT=0 SIZEOF_LONG=0 SIZEOF_LONGLONG_T=0 SIZEOF_SUPERLONG_T=0 while read symbol type offset size ; do size=$(( 0$size + 0 )) symbol=${symbol#_} if [ "$type" = "C" ] ; then size=$(( 0$offset + 0 )) fi case "$symbol" in SIZEOF* ) eval $(printf "%s=%d\n" "$symbol" "$size") printf "#define %s %s\n" "$symbol" "$size" >> config.h ;; esac done < conftest.syms rm -f conftest.syms conftest.o if [ $SIZEOF_PTR -eq 0 ] ; then printf "failed\n" exit 1 fi if [ $SIZEOF_PTR -eq $SIZEOF_SHORT ] ; then intptr="short" elif [ $SIZEOF_PTR -eq $SIZEOF_INT ] ; then intptr="int" elif [ $SIZEOF_PTR -eq $SIZEOF_LONG ] ; then intptr="long" elif [ $SIZEOF_PTR -eq $SIZEOF_LONG_LONG_T ] ; then intptr="longlong_t" fi if [ -z "$intptr" ] ; then printf "failed\n" exit 1 fi fi printf '"%s"\n' "$intptr" printf "typedef $intptr int_ptr_t;\n" >> config.h intptr_max_expr="((((($intptr) 1 << $((SIZEOF_PTR * 8 - 2))) - 1) << 1) + 1)" printf "#define INT_PTR_MAX %s\n" "$intptr_max_expr" >> config.h printf "#define INT_PTR_MIN (-INT_PTR_MAX)\n" >> config.h if [ -n "$longlong" ] && [ $SIZEOF_LONGLONG_T -eq $(( 2 * $SIZEOF_PTR )) ] then printf "#define HAVE_DOUBLE_INTPTR_T 1\n" >> config.h printf "typedef longlong_t double_intptr_t;\n" >> config.h elif [ -n "$superlong" ] && [ $SIZEOF_SUPERLONG_T -eq $(( 2 * $SIZEOF_PTR )) ] then printf "#define HAVE_DOUBLE_INTPTR_T 1\n" >> config.h printf "typedef superlong_t double_intptr_t;\n" >> config.h fi #if HAVE_LONGLONG_T && # # Alignment of wchar_t # # What we really want to know is the alignment of wide string literals # like L"wide literal". # # We make pessimistic assumption that the size of the wchar_t type is this # alignment. # # There is no easy way to get the information without running a compiled # program. # printf "Conservatively guessing the alignment of wide literals ... " if [ -z "$lit_align" ] ; then cat > conftest.c < char sizeof_wchar_t[sizeof (wchar_t)]; ! rm -f conftest.o conftest.syms if ! make conftest.syms > conftest.err 2>&1 ; then printf "failed\n\n" printf "Errors from compilation: \n\n" cat conftest.err exit 1 fi sizeof_wchar_t=0 while read symbol type offset size ; do size=$(( 0$size + 0 )) symbol=${symbol#_} if [ "$type" = "C" ] ; then size=$(( 0$offset + 0 )) fi case "$symbol" in sizeof* ) eval $(printf "%s=%d\n" "$symbol" "$size") ;; esac done < conftest.syms rm -f conftest.syms conftest.o if [ $sizeof_wchar_t -eq 0 ] ; then printf "failed\n" exit 1 fi lit_align=$sizeof_wchar_t fi printf "%d\n" "$lit_align" printf "#define LIT_ALIGN %d\n" "$lit_align" >> config.h # # Inline functions # printf "Checking how to declare inline functions ... " if [ -z "$inline" ] ; then for inline in \ "inline" "static inline" "extern inline" \ "__inline__" "static __inline__" "extern __inline__" \ "static" do cat > conftest1.c < conftest2.c < conftest.err 2>&1 ; then continue fi break done fi printf '"%s"\n' "$inline" printf "#define INLINE $inline\n" >> config.h # # Valgrind # if [ -n "$valgrind" ] ; then printf "Checking valgrind API availability ... " cat > conftest.c < #ifdef VALGRIND_DO_CLIENT_REQUEST int main(void) { return 0; } #else syntax error #endif ! rm -rf conftest if ! make conftest > conftest.err 2>&1 || ! [ -x conftest ] ; then printf "failed\n\n" printf "Errors from compilation: \n\n" cat conftest.err exit 1 fi printf "okay\n" printf "#define HAVE_VALGRIND\n" >> config.h fi # # Yacc tests # printf "Checking for yacc program ... " if [ -z "$yacc_given" -a -z "$yaccname_given" ] ; then rm -f conftest.yacc for yaccname in "yacc" "byacc" "bison -y" "" ; do yaccpath=$(make yaccname="$yaccname" conftest.yacc) if command -v $yaccpath > /dev/null ; then break; fi done if [ -z "$yaccname" ] ; then printf "not found\n" exit 1 fi printf '"%s"\n' "$yaccpath" else yaccpath=$(make conftest.yacc) case $yaccpath in *bison ) printf "error\n\n" printf "GNU Bison needs -y to behave like yacc\n\n" printf "This needs to be specified in the --yaccname or --yacc option\n\n" exit 1 ;; * ) if ! command -v $yaccpath > /dev/null ; then printf "not found\n\n" exit 1 fi printf "given\n" ;; esac fi # # sys/wait.h # printf "Checking whether we have ... " cat > conftest.c < int main(void) { return 0; } ! rm -f conftest if ! make conftest > conftest.err 2>&1 || ! [ -x conftest ] ; then printf "no\n" else printf "yes\n" printf "#define HAVE_SYS_WAIT 1\n" >> config.h fi # # environ # printf "Checking whether we have environ ... " cat > conftest.c < int main(void) { extern char **environ; puts(environ[0]); return 0; } ! rm -f conftest if ! make conftest > conftest.err 2>&1 || ! [ -x conftest ] ; then printf "no\n" else printf "yes\n" printf "#define HAVE_ENVIRON 1\n" >> config.h fi # # GetEnvironmentStrings # printf "Checking whether we have GetEnvironmentStrings ... " cat > conftest.c < int main(void) { WCHAR *ptr = GetEnvironmentStringsW(); return 0; } ! rm -f conftest if ! make conftest > conftest.err 2>&1 || ! [ -x conftest ] ; then printf "no\n" else printf "yes\n" printf "#define HAVE_GETENVIRONMENTSTRINGS 1\n" >> config.h fi # # Extra debugging. # if [ -n "$extra_debugging" ] ; then printf "Configuring extra debugging, as requested ...\n" printf "#define EXTRA_DEBUGGING 1\n" >> config.h fi # # Clean up # rm -f conftest conftest.[co] conftest.{err,syms} rm -f conftest2 conftest[12].[oc] # # What do we have for patch management. # printf "Checking for quilt ... " if ! quilt --version > /dev/null 2>&1 ; then printf "not found\n" else printf "found\n" have_quilt=y fi printf "Checking for patch ... " if ! patch --version > /dev/null 2>&1 ; then printf "not found\n" printf "\npatch tool required!\n\n" exit 1 else printf "found\n" have_patch=y fi # # Function to apply patches. # apply_patches() { if ! [ -e patches/series ] ; then echo "no patches" return 0 fi while read patch patchlevel ; do case patch in '#' ) continue ;; * ) patch ${patchlevel:--p1} < patches/$patch ;; esac done < patches/series } # # Try to extract MPI if not already. # printf "Extracting MPI ... " if [ -e $top_srcdir/mpi-${mpi_version} ] ; then printf "already extracted\n" else tar -C $top_srcdir -xzf $top_srcdir/mpi-${mpi_version}.tar.gz printf "\n" printf "Symlinking MPI patches ...\n" ln -sf ../mpi-patches \ $top_srcdir/mpi-${mpi_version}/patches printf "Applying MPI patches ...\n" if [ -n "$have_quilt" ] ; then ( cd $top_srcdir/mpi-${mpi_version}/patches ; if [ -e series ] ; then quilt push -a ; else echo "no patches" ; fi ) else ( cd $top_srcdir/mpi-${mpi_version} ; apply_patches ) fi fi # # Regenerate config.make # printf "Regenerating config.make ... " gen_config_make printf "\n" # # Save configuration in config.log # cat > config.log <