#!/bin/sh myname="${0##*/}" VERSION=$( cat .version ) DATE=$( date +%Y%m%d ) PREFIX_DEFAULT=/usr/local BINDIR_set= LIBDIR_set= DOCDIR_set= MANDIR_set= LOCAL_set= FORCE= do_quit= # Simply print the error message, and exit. Obvious, he? do_error() { printf "${myname}: ${@}\n" exit 1 } # Given an option string and the following argument, # echoes the value of the option. # If --var=val => echoes val and returns 0, meaning second arg was not consumed # If --var val => echoes val and returns non null, meaning second arg was used get_optval(){ case "$1" in --*=?*) printf "${1#*=}" return 0 ;; *) printf "${2}" return 1 ;; esac } # The set_xxx functions will set the corresponding configuration variable # They return 0 if second arg was not consumed, and non-zero if it was consumed. set_prefix() { PREFIX="$( get_optval "$1" "$2" )" } set_bindir() { BINDIR_set=1 BINDIR="$( get_optval "$1" "$2" )" } set_libdir() { LIBDIR_set=1 LIBDIR="$( get_optval "$1" "$2" )" } set_docdir() { DOCDIR_set=1 DOCDIR="$( get_optval "$1" "$2" )" } set_mandir() { MANDIR_set=1 MANDIR="$( get_optval "$1" "$2" )" } set_tool() { local var_name="${1%%=*}" var_name="${var_name#--with-}" eval ${var_name}="\$( get_optval "$1" "$2" )" } # var_list is a list of variables, each one holding a path to a # tool, either detected by ./configure, or specified by the user. var_list="" kconfig_list="" # This function adds a variable name to the above list of variable names. # $1: the name of the variable to add to the list add_to_var_list() { local v for v in ${var_list}; do [ "${v}" = "${1}" ] && return 0 done var_list="${var_list} ${1}" } add_to_kconfig_list() { local k for k in ${kconfig_list}; do [ "${k}" = "${1}" ] && return 0 done kconfig_list="${kconfig_list} ${1}" } # A function to test for required tools/headers/libraries # Return 0 (true) if found, !0 (false) if not found # # $*: [prog|inc|lib]= # the name(s) of tool(s) to test for # mandatory # eg: prog=bash prog="curl wget" # $*: var= # the name of the variable to test and set # optional # eg: var=bash if ${bash} is set and non-null, use that, # else check for bash and set bash=$(which bash) # $*: ver= # for each 'prog', test if $(prog --version) matches 'regexp' # optional # eg: ver='^GNU bash, version [34]\.' # $*: lib_exts= # the list of allowed library extension # mandatory # eg: lib_exts="so dylib" lib_exts="so dylib a" # $*: err= # the error message to print if tool is missing # optional, defaults to: '${prog}: none found' # eg: err="'bash' 3.x or above was not found" # Note: err may be printed by caller, not us # $*: kconfig= # the name of a variable to pass down to kconfig if # the prog/inc/lib was found # optional, defaults to none # eg: kconfig=has_libncurses # $*: skip=[y|n|] # if set to 'y', skip the test, but still register the # kconfig and var variables; if 'n' or empty, do the # test. # optional, default to 'n' # eg: skip="${static_link_ko}" check_for() { local lib_exts local skip local val local item local where local status local ext # Note: prog/inc/lib and var/kconfig/ver/err are set here, # but declared by the caller (because it needs it) for item in "${@}"; do case "${item}" in prog=*|inc=*|lib=*|var=*|ver=*|err=*|kconfig=*|lib_exts=*|skip=*) eval ${item%%=*}=\"${item#*=}\" ;; *) do_error "check_for: incorrect parameters: '${item}'";; esac done case "${prog}:${inc}:${lib}" in ?*:?*:|?*::?*|:?*:?*|?*:?*:?*) if [ -n "${var}" ]; then do_error "check_for: the use of var is not compatible with passing several of [prog|inc|lib] at once" fi ;; ::) do_error "check_for: [prog|inc|lib] is mandatory";; esac if [ -n "${var}" ]; then add_to_var_list "${var}" fi if [ -n "${kconfig}" ]; then add_to_kconfig_list "${kconfig}" fi if [ "${skip}" = "y" ]; then return 0 fi if [ -n "${prog}" ]; then for item in ${prog}; do printf "Checking for '${item}'... " if [ -n "${var}" ]; then eval val="\${${var}}" if [ -n "${val}" ]; then status="${val} (cached)\n" where="${val}" break fi fi where="$( which "${item}" 2>/dev/null )" if [ -z "${where}" ]; then printf "no\n" continue elif [ -n "${ver}" ]; then str=$( LC_ALL=C "${where}" --version 2>&1 \ |grep -E "${ver}" \ |head -n 1 ) if [ -z "${str}" ]; then printf "no\n" unset where continue fi fi status="${where}" break done if [ -z "${status}" ]; then return 1 fi printf "${status}\n" unset status fi if [ -n "${inc}" ]; then for item in ${inc}; do printf "Checking for '${item}'... " if printf "#include \"${item}\"" |gcc -x c -c - -o /dev/null >/dev/null 2>&1; then where="${item}" status=yes break; fi printf "no\n" done if [ -z "${status}" ]; then return 1 fi printf "${status}\n" unset status fi if [ -n "${lib}" ]; then if [ -z "${lib_exts}" ]; then do_error "check_for: no library extension specified for '${lib}'" fi for item in ${lib}; do for ext in ${lib_exts}; do printf "Checking for '${item}.${ext}'... " where="$( gcc -print-file-name="${item}.${ext}" )" if [ "${where}" != "${item}.${ext}" ]; then where="$( readlink "${where}" )" status=yes break 2; fi printf "no\n" done done if [ -z "${status}" ]; then return 1 fi printf "${status}\n" unset status fi if [ -n "${var}" ]; then eval ${var}='"'"${where}"'"' fi if [ -n "${kconfig}" ]; then eval ${kconfig}=y fi } # This function checks for a tool, and aborts if not found # See check_for(), above, for how to call has_or_abort has_or_abort() { # We declare these 6 variables here, although they are # set in check_for(), called below local prog inc lib local var ver err kconfig if ! check_for "$@"; then printf " * A mandatory dependency is missing, or version mis-match:\n" printf " * - ${err:-${prog}${inc}${lib}: none found}\n" if [ -n "${var}" ]; then printf " * --> You can give the path to this tool using: --with-${var}=PATH\n" fi printf "\n" # Bail out if --force is not specified [ -z "${FORCE}" ] && do_error "Bailing out..." printf "<* *>\n" printf "<* FORCE in action: *>\n" printf "<* Continuing despite missing pre-requisite *>\n" printf "<* Prepare for breakage *>\n" printf "<* *>\n" printf "\n" fi } # This function checks for a tool, and warns if not found # See check_for(), above, for how to call has_or_abort # Note: if err is not set, then no error message is printed has_or_warn() { # We declare these 6 variables here, although they are # set in check_for(), called below local prog inc lib local var ver err kconfig if ! check_for "$@"; then printf " * An optional dependency is missing, some features will be disabled" printf "${err:+:\n * - ${err}}\n" if [ -n "${var}" ]; then printf " * --> You can give the path to this tool using: --with-${var}=PATH\n" fi fi } do_help() { cat <<__EOF__ \`configure' configures crosstool-NG-${VERSION} to adapt to many kind of systems. USAGE: ./configure [OPTION]... Defaults for the options are specified in brackets. Configuration: -h, --help display this help and exit --force force configure to continue, even in case some pre-requisites are missing Installation directories: --prefix=PREFIX install files in PREFIX [${PREFIX_DEFAULT}] --local don't install, and use current directory By default, \`make install' will install all the files in \`${PREFIX_DEFAULT}/bin', \`${PREFIX_DEFAULT}/lib' etc. You can specify an installation prefix other than \`${PREFIX_DEFAULT}' using \`--prefix', for instance \`--prefix=\${HOME}'. For better control, use the options below. Fine tuning of the installation directories: --bindir=DIR user executables [PREFIX/bin] --libdir=DIR object code libraries [PREFIX/lib] --docdir=DIR info documentation [PREFIX/share/doc] --mandir=DIR man documentation [PREFIX/share/man] Optional Features: --with-install=PATH Specify the full PATH to GNU install --with-make=PATH Specify the full PATH to GNU make >= 3.80 --with-grep=PATH Specify the full PATH to GNU grep --with-sed=PATH Specify the full PATH to GNU sed --with-bash=PATH Specify the full PATH to bash >= 3.0 __EOF__ } #--------------------------------------------------------------------- # Set user's options while [ $# -ne 0 ]; do case "$1" in --local) LOCAL_set="y"; shift;; --prefix*) set_prefix "$1" "$2" && shift || shift 2;; --bindir*) set_bindir "$1" "$2" && shift || shift 2;; --libdir*) set_libdir "$1" "$2" && shift || shift 2;; --docdir*) set_docdir "$1" "$2" && shift || shift 2;; --mandir*) set_mandir "$1" "$2" && shift || shift 2;; --with-*) set_tool "$1" "$2" && shift || shift 2;; --force) FORCE=1; shift;; --help|-h) do_help; exit 0;; # Skip, auto-stuff compatibility --build=*|--host=*|--infodir=*|--datadir=*|--sysconfdir=*|--localstatedir=*) shift;; --build|--host|--infodir|--datadir|--sysconfdir|--localstatedir) shift 2;; --enable-shared|--disable-shared|--enable-static|--disable-static) shift;; --program-prefix=*) shift;; --program-prefix) shift 2;; *) printf "Unrecognised option: '${1}'\n"; do_help; exit 1;; esac done # Use defaults [ -z "${PREFIX}" ] && set_prefix "" "${PREFIX_DEFAULT}" # Special case when installing locally if [ "${LOCAL_set}" = "y" ]; then set_prefix "" "$( pwd )" set_bindir "" "$( pwd )" set_libdir "" "$( pwd )" set_docdir "" "$( pwd )/docs" set_mandir "" "$( pwd )/docs" fi #--------------------------------------------------------------------- # Some sanity checks, now # We check for grep and sed manually, because they are used in check_for() printf "Checking for 'grep'... " if [ -n "${grep}" ]; then printf "${grep} (cached)\n" else grep="$( which grep 2>/dev/null )" if [ -z "${grep}" ]; then printf "not found\n" else printf "${grep}\n" printf "Checking whether '${grep}' supports -E... " if echo 'foo' |"${grep}" -E 'foo' >/dev/null 2>&1; then printf "yes\n" else printf "no\n" grep= fi fi fi if [ -z "${grep}" ]; then printf "Either you are missing entirely the needed tool,\n" printf "or the version you have is too old.\n" printf "You can give the path to this tool using: --with-grep=PATH\n" do_error "Bailing out..." fi add_to_var_list grep printf "Checking for 'sed'... " if [ -n "${sed}" ]; then printf "${sed} (cached)\n" else sed="$( which sed 2>/dev/null )" if [ -z "${sed}" ]; then printf "not found\n" else printf "${sed}\n" printf "Checking whether '${sed}' supports -i and -e... " touch .ct-ng.sed.test if "${sed}" -r -i -e 's/foo/bar/' .ct-ng.sed.test >/dev/null 2>&1; then printf "yes\n" else printf "no\n" sed= fi rm -f .ct-ng.sed.test fi fi if [ -z "${sed}" ]; then printf "Either you are missing entirely the needed tool,\n" printf "or the version you have is too old.\n" printf "You can give the path to this tool using: --with-sed=PATH\n" do_error "Bailing out..." fi add_to_var_list sed # The regular list of tools we can now easily check for has_or_abort prog=bash \ var=bash \ ver='^GNU bash, version (3\.[1-9]|4)' \ err="'bash' 3.1 or above was not found" has_or_abort prog=cut has_or_abort prog=install var=install has_or_abort prog=make \ var=make \ ver='^GNU Make (3.[89][[:digit:]]|[4-9])' \ err="GNU 'make' 3.80 or above was not found" has_or_abort prog=gcc has_or_abort prog="awk gawk" ver='^GNU Awk' err="GNU 'awk' was not found" has_or_abort prog=bison has_or_abort prog=flex has_or_abort prog=makeinfo has_or_abort prog=automake \ ver='\(GNU automake\) (1\.[[:digit:]]{2,}|[2-9][[:digit:]]*\.)' \ err="'automake' 1.10 or above was not found" has_or_abort prog=libtool \ var=libtool \ ver='\(GNU libtool.*\) (2[[:digit:]]*\.|1\.6[[:digit:]]*\.|1\.5\.[2-9][[:digit:]]+)' \ err="'libtool' 1.5.26 or above was not found" has_or_abort prog=libtoolize \ var=libtoolize \ ver='\(GNU libtool.*\) (2[[:digit:]]*\.|1\.6[[:digit:]]*\.|1\.5\.[2-9][[:digit:]]+)' \ err="'libtoolize' 1.5.26 or above was not found" has_or_abort prog=stat has_or_abort prog="curl wget" has_or_abort prog=patch has_or_abort prog=tar has_or_abort prog=gzip has_or_abort prog=bzip2 has_or_abort prog=lzma has_or_abort prog=readlink has_or_abort prog=objcopy var=objcopy has_or_abort prog=objdump var=objdump has_or_abort prog=readelf var=readelf has_or_abort prog=patch var=patch has_or_warn prog=cvs \ kconfig=has_cvs \ err="it will not be possible to use newlib cvs snapshots" has_or_abort prog=svn \ kconfig=has_svn \ err="subversion is required to download eglibc" # Host system checks printf "Checking for host system... " host="$( uname -s )" printf "%s\n" "${host}" case "${host}" in Linux) ;; Cygwin) ;; *) printf " * Runing under %s is not fully tested\n" "${host}" printf " * You may encounter some weird behavior\n" ;; esac printf "Checking if static linking is possible... " static_link_ok="" case "${host}" in Darwin) ;; *) tmp=.static.tmp if gcc -xc - -static -o "${tmp}" >/dev/null 2>&1 <<-_EOF_ int main() { return 0; } _EOF_ then static_link_ok="y" fi rm -f "${tmp}" ;; esac if [ "${static_link_ok}" = "y" ]; then static_link_ko="" printf "yes\n" else static_link_ko="y" printf "no\n" printf " * An optional host feature is missing, some features will be disabled:\n" printf " * - It will not be possible to statically link toolchain's binaries\n" fi add_to_kconfig_list static_link_ok # Library checks libs_exts="so dylib" if [ "${static_link_ok}" = "y" ]; then libs_exts="${libs_exts} a" fi ncurses_hdrs="ncurses/ncurses.h ncurses/curses.h ncurses.h curses.h" ncurses_libs="libncursesw libncurses libcurses" has_or_abort lib="${ncurses_libs}" \ lib_exts="${libs_exts}" \ inc="${ncurses_hdrs}" \ err="The 'ncurses' library is needed fo the menuconfig frontend" has_or_abort lib="libstdc++" \ lib_exts="${libs_exts}" \ err="The 'libstdc++' library is needed to build gcc" # Yes, we may be checking twice for libstdc++.a # The first is because we need one instance of libstdc++ (shared or static) # because it is needed for PPL; the second is because the static version is # required for static-linking, and if missing, the option is removed. has_or_warn lib="libstdc++" \ lib_exts="a" \ err="static 'libstdc++' is needed to statically link the toolchain's executables" \ kconfig=has_static_libstdcxx \ skip="${static_link_ko}" has_or_warn inc="expat.h" \ lib="libexpat" \ lib_exts="${libs_exts}" \ err="The 'expat' header file and library are needed to link cross-gdb's executables" \ kconfig=has_expat # Yes, we may be checking twice for libexpat.a # The first is because we need one instance of libexpat (shared or static) # because it is needed for cross-gdb; the second is because the static version # is required for static-linking, and if missing, the option is removed. has_or_warn lib="libexpat" \ lib_exts="a" \ err="static 'expat' is needed to statically link cross-gdb's executables" \ kconfig=has_static_expat \ skip="${static_link_ko}" for v in 7 6 5 4; do python_incs="${python_incs} python2.${v}/Python.h" python_libs="${python_libs} libpython2.${v}" done has_or_warn inc="${python_incs}" \ lib="${python_libs}" \ lib_exts="${libs_exts}" \ err="The 'python' header file and library are needed for some features of cross-gdb" #--------------------------------------------------------------------- # Compute the version string # If this version is n hg clone, try to get the revision number # If we can't get the revision number, use date printf "\nComputing version string... " case "${VERSION}" in *+hg|hg) REVISION="$( hg id -n 2>/dev/null || true )" case "${REVISION}" in "") VERSION="${VERSION}_unknown@$( date +%Y%m%d.%H%M%S )";; *) VERSION="${VERSION}_$( hg id -b )@${REVISION%%+}_$( hg id -i )" ;; esac # Arrange to have no / in the directory name, no need to create an # arbitrarily deep directory structure VERSION="$( printf "${VERSION}\n" |"${sed}" -r -e 's|/+|_|g;' )" ;; esac printf "${VERSION}\n" #--------------------------------------------------------------------- # Compute and check install paths # Now we have the version string, we can build up the paths [ -z "${BINDIR_set}" ] && BINDIR="${PREFIX}/bin" [ -z "${LIBDIR_set}" ] && LIBDIR="${PREFIX}/lib" [ -z "${DOCDIR_set}" ] && DOCDIR="${PREFIX}/share/doc" [ -z "${MANDIR_set}" ] && MANDIR="${PREFIX}/share/man" # Install support files in our own sub-dir, so as not to mangle (system) # files and dirs, but only if not --local if [ -z "${LOCAL_set}" ]; then LIBDIR="${LIBDIR}/ct-ng-${VERSION}" DOCDIR="${DOCDIR}/ct-ng-${VERSION}" fi # Check that install PATHs are absolute for p in BIN LIB DOC MAN; do var="${p}DIR" eval v='"${'"${var}"'}"' case "${v}" in /*) ;; *) do_error "'${var}' is not an absolute path: '${v}'" esac done #--------------------------------------------------------------------- # That's all, folks! printf "Building up Makefile... " var_sed="$( for var_name in ${var_list}; do eval echo 's,@@${var_name}@@,${'"${var_name}"'},g' done )" kconfig_sed="s/@@KCONFIG@@/$( for k_name in ${kconfig_list}; do eval printf \"${k_name}=\${${k_name}} \" done )/" "${sed}" -r -e "s,@@BINDIR@@,${BINDIR},g" \ -e "s,@@LIBDIR@@,${LIBDIR},g" \ -e "s,@@DOCDIR@@,${DOCDIR},g" \ -e "s,@@MANDIR@@,${MANDIR},g" \ -e "s,@@VERSION@@,${VERSION},g" \ -e "s,@@DATE@@,${DATE},g" \ -e "s,@@LOCAL@@,${LOCAL_set},g" \ -e "${var_sed}" \ -e "${kconfig_sed}" \ Makefile.in \ >Makefile echo "done" cat <<__EOF__ crosstool-NG configured as follows: PREFIX='${PREFIX}' BINDIR='${BINDIR}' LIBDIR='${LIBDIR}' DOCDIR='${DOCDIR}' MANDIR='${MANDIR}' Now run: make __EOF__ if [ "${LOCAL_set}" != "y" ]; then printf " make install\n" fi