configure
author "Benoît THÉBAUDEAU" <benoit.thebaudeau@advansee.com>
Wed Jun 08 15:47:03 2011 +0200 (2011-06-08)
changeset 2507 a5856225d851
parent 2506 2ab553e37517
child 2508 9e2761e59a75
permissions -rwxr-xr-x
configure: give check_for() the ability to test several item types at once

Currently, check_for() can only test one of prog, inc or lib at once. This patch
removes this limitation.

Signed-off-by: "Benoît THÉBAUDEAU" <benoit.thebaudeau@advansee.com>
     1 #!/bin/sh
     2 
     3 myname="${0##*/}"
     4 
     5 VERSION=$( cat .version )
     6 DATE=$( date +%Y%m%d )
     7 
     8 PREFIX_DEFAULT=/usr/local
     9 
    10 BINDIR_set=
    11 LIBDIR_set=
    12 DOCDIR_set=
    13 MANDIR_set=
    14 LOCAL_set=
    15 FORCE=
    16 
    17 do_quit=
    18 
    19 # Simply print the error message, and exit. Obvious, he?
    20 do_error() {
    21     printf "${myname}: ${@}\n"
    22     exit 1
    23 }
    24 
    25 # Given an option string and the following argument,
    26 # echoes the value of the option.
    27 # If --var=val => echoes val and returns 0, meaning second arg was not consumed
    28 # If --var val => echoes val and returns non null, meaning second arg was used
    29 get_optval(){
    30     case "$1" in
    31         --*=?*)
    32             printf "${1#*=}"
    33             return 0
    34             ;;
    35         *)
    36             printf "${2}"
    37             return 1
    38             ;;
    39     esac
    40 }
    41 
    42 # The set_xxx functions will set the corresponding configuration variable
    43 # They return 0 if second arg was not consumed, and non-zero if it was consumed.
    44 set_prefix() {
    45     PREFIX="$( get_optval "$1" "$2" )"
    46 }
    47 set_bindir() {
    48     BINDIR_set=1
    49     BINDIR="$( get_optval "$1" "$2" )"
    50 }
    51 set_libdir() {
    52     LIBDIR_set=1
    53     LIBDIR="$( get_optval "$1" "$2" )"
    54 }
    55 set_docdir() {
    56     DOCDIR_set=1
    57     DOCDIR="$( get_optval "$1" "$2" )"
    58 }
    59 set_mandir() {
    60     MANDIR_set=1
    61     MANDIR="$( get_optval "$1" "$2" )"
    62 }
    63 set_tool() {
    64     local var_name="${1%%=*}"
    65     var_name="${var_name#--with-}"
    66     eval ${var_name}="\$( get_optval "$1" "$2" )"
    67 }
    68 
    69 # var_list is a list of variables, each one holding a path to a
    70 # tool, either detected by ./configure, or specified by the user.
    71 var_list=""
    72 kconfig_list=""
    73 
    74 # This function adds a variable name to the above list of variable names.
    75 # $1: the name of the variable to add to the list
    76 add_to_var_list() {
    77     local v
    78     for v in ${var_list}; do
    79         [ "${v}" = "${1}" ] && return 0
    80     done
    81     var_list="${var_list} ${1}"
    82 }
    83 add_to_kconfig_list() {
    84     local k
    85     for k in ${kconfig_list}; do
    86         [ "${k}" = "${1}" ] && return 0
    87     done
    88     kconfig_list="${kconfig_list} ${1}"
    89 }
    90 
    91 # A function to test for required tools/headers/libraries
    92 # Return 0 (true) if found, !0 (false) if not found
    93 #
    94 # $*: [prog|inc|lib]=<name[ name...]>
    95 #     the name(s) of tool(s) to test for
    96 #     mandatory
    97 #       eg: prog=bash   prog="curl wget"
    98 # $*: var=<var_name>
    99 #     the name of the variable to test and set
   100 #     optional
   101 #       eg: var=bash    if ${bash} is set and non-null, use that,
   102 #                       else check for bash and set bash=$(which bash)
   103 # $*: ver=<regexp>
   104 #     for each 'prog', test if $(prog --version) matches 'regexp'
   105 #     optional
   106 #       eg: ver='^GNU bash, version [34]\.'
   107 # $*: err=<error_message>
   108 #     the error message to print if tool is missing
   109 #     optional, defaults to: '${prog}: none found'
   110 #       eg: err="'bash' 3.x or above was not found"
   111 #     Note: err may be printed by caller, not us
   112 # $*: kconfig=<var_name>
   113 #     the name of a variable to pass down to kconfig if
   114 #     the prog/inc/lib was found
   115 #     optional, defaults to none
   116 #       eg: kconfig=has_libncurses
   117 check_for() {
   118     local val
   119     local item
   120     local where
   121     local status
   122 
   123     # Note: prog/inc/lib and var/kconfig/ver/err are set here,
   124     # but declared by the caller (because it needs it)
   125     for item in "${@}"; do
   126         case "${item}" in
   127             prog=*|inc=*|lib=*|var=*|ver=*|err=*|kconfig=*)
   128                 eval ${item%%=*}=\"${item#*=}\"
   129                 ;;
   130             *)  do_error "check_for: incorrect parameters: '$@'";;
   131         esac
   132     done
   133 
   134     case "${prog}:${inc}:${lib}" in
   135         ?*:?*:|?*::?*|:?*:?*|?*:?*:?*)
   136             if [ -n "${var}" ]; then
   137                 do_error "check_for: the use of var is not compatible with passing several of [prog|inc|lib] at once"
   138             fi
   139             ;;
   140         ::) do_error "check_for: [prog|inc|lib] is mandatory";;
   141     esac
   142 
   143     if [ -n "${kconfig}" ]; then
   144         add_to_kconfig_list "${kconfig}"
   145     fi
   146 
   147     if [ -n "${prog}" ]; then
   148         for item in ${prog}; do
   149             printf "Checking for '${item}'... "
   150             if [ -n "${var}" ]; then
   151                 eval val="\${${var}}"
   152                 if [ -n "${val}" ]; then
   153                     printf "${val} (cached)\n"
   154                     add_to_var_list "${var}"
   155                     return 0
   156                 fi
   157             fi
   158             where="$( which "${item}" 2>/dev/null )"
   159             if [ -z "${where}" ]; then
   160                 printf "no\n"
   161                 continue
   162             elif [ -n "${ver}" ]; then
   163                 str=$( LC_ALL=C "${where}" --version 2>&1   \
   164                        |grep -E "${ver}"                    \
   165                        |head -n 1
   166                      )
   167                 if [ -z "${str}" ]; then
   168                     printf "no\n"
   169                     unset where
   170                     continue
   171                 fi
   172             fi
   173             status="${where}"
   174             break
   175         done
   176         if [ -z "${status}" ]; then
   177             return 1
   178         fi
   179         printf "${status}\n"
   180         unset status
   181     fi
   182 
   183     if [ -n "${inc}" ]; then
   184         for item in ${inc}; do
   185             printf "Checking for '${item}'... "
   186             if printf "#include \"${item}\"" |gcc -x c -c - -o /dev/null >/dev/null 2>&1; then
   187                 where="${item}"
   188                 status=yes
   189                 break;
   190             fi
   191             printf "no\n"
   192         done
   193         if [ -z "${status}" ]; then
   194             return 1
   195         fi
   196         printf "${status}\n"
   197         unset status
   198     fi
   199 
   200     if [ -n "${lib}" ]; then
   201         for item in ${lib}; do
   202             printf "Checking for '${item}'... "
   203             where="$( gcc -print-file-name="${item}" )"
   204             if [ "${where}" != "${item}" ]; then
   205                 where="$( readlink "${where}" )"
   206                 status=yes
   207                 break;
   208             fi
   209             printf "no\n"
   210         done
   211         if [ -z "${status}" ]; then
   212             return 1
   213         fi
   214         printf "${status}\n"
   215         unset status
   216     fi
   217 
   218     if [ -n "${var}" ]; then
   219         eval ${var}='"'"${where}"'"'
   220         add_to_var_list "${var}"
   221     fi
   222     if [ -n "${kconfig}" ]; then
   223         eval ${kconfig}=y
   224     fi
   225 }
   226 
   227 # This function checks for a tool, and aborts if not found
   228 # See check_for(), above, for how to call has_or_abort
   229 has_or_abort() {
   230     # We declare these 6 variables here, although they are
   231     # set in check_for(), called below
   232     local prog inc lib
   233     local var ver err kconfig
   234 
   235     if ! check_for "$@"; then
   236         printf " * A mandatory dependency is missing, or version mis-match\n"
   237         printf " * ${err:-${prog}${inc}${lib}: none found}\n"
   238         if [ -n "${var}" ]; then
   239             printf " * --> You can give the path to this tool using: --with-${var}=PATH\n"
   240         fi
   241         printf "\n"
   242         # Bail out if --force is not specified
   243         [ -z "${FORCE}" ] && do_error "Bailing out..."
   244         printf "<*                                          *>\n"
   245         printf "<*            FORCE in action:              *>\n"
   246         printf "<* Continuing despite missing pre-requisite *>\n"
   247         printf "<*          Prepare for breakage            *>\n"
   248         printf "<*                                          *>\n"
   249         printf "\n"
   250     fi
   251 }
   252 
   253 # This function checks for a tool, and warns if not found
   254 # See check_for(), above, for how to call has_or_abort
   255 # Note: if err is not set, then no error message is printed
   256 has_or_warn() {
   257     # We declare these 6 variables here, although they are
   258     # set in check_for(), called below
   259     local prog inc lib
   260     local var ver err kconfig
   261 
   262     if ! check_for "$@"; then
   263         printf " * An optional dependency is missing, some features will be disabled\n"
   264         printf "${err:+ * ${err}\n}"
   265         if [ -n "${var}" ]; then
   266             printf " * --> You can give the path to this tool using: --with-${var}=PATH\n"
   267         fi
   268     fi
   269 }
   270 
   271 do_help() {
   272     cat <<__EOF__
   273 \`configure' configures crosstool-NG-${VERSION} to adapt to many kind of systems.
   274 
   275 USAGE: ./configure [OPTION]...
   276 
   277 Defaults for the options are specified in brackets.
   278 
   279 Configuration:
   280   -h, --help              display this help and exit
   281       --force             force configure to continue, even in case
   282                           some pre-requisites are missing
   283 
   284 Installation directories:
   285   --prefix=PREFIX         install files in PREFIX [${PREFIX_DEFAULT}]
   286   --local                 don't install, and use current directory
   287 
   288 By default, \`make install' will install all the files in
   289 \`${PREFIX_DEFAULT}/bin', \`${PREFIX_DEFAULT}/lib' etc.  You can specify
   290 an installation prefix other than \`${PREFIX_DEFAULT}' using \`--prefix',
   291 for instance \`--prefix=\${HOME}'.
   292 
   293 For better control, use the options below.
   294 
   295 Fine tuning of the installation directories:
   296   --bindir=DIR            user executables [PREFIX/bin]
   297   --libdir=DIR            object code libraries [PREFIX/lib]
   298   --docdir=DIR            info documentation [PREFIX/share/doc]
   299   --mandir=DIR            man documentation [PREFIX/share/man]
   300 
   301 Optional Features:
   302   --with-install=PATH     Specify the full PATH to GNU install
   303   --with-make=PATH        Specify the full PATH to GNU make >= 3.80
   304   --with-grep=PATH        Specify the full PATH to GNU grep
   305   --with-sed=PATH         Specify the full PATH to GNU sed
   306   --with-bash=PATH        Specify the full PATH to bash >= 3.0
   307 __EOF__
   308 }
   309 
   310 #---------------------------------------------------------------------
   311 # Set user's options
   312 
   313 while [ $# -ne 0 ]; do
   314     case "$1" in
   315         --local)    LOCAL_set="y"; shift;;
   316         --prefix*)  set_prefix "$1" "$2" && shift || shift 2;;
   317         --bindir*)  set_bindir "$1" "$2" && shift || shift 2;;
   318         --libdir*)  set_libdir "$1" "$2" && shift || shift 2;;
   319         --docdir*)  set_docdir "$1" "$2" && shift || shift 2;;
   320         --mandir*)  set_mandir "$1" "$2" && shift || shift 2;;
   321         --with-*)   set_tool   "$1" "$2" && shift || shift 2;;
   322         --force)    FORCE=1; shift;;
   323         --help|-h)  do_help; exit 0;;
   324         # Skip, auto-stuff compatibility
   325         --build=*|--host=*|--infodir=*|--datadir=*|--sysconfdir=*|--localstatedir=*) shift;;
   326         --build|--host|--infodir|--datadir|--sysconfdir|--localstatedir)             shift 2;;
   327         *)          printf "Unrecognised option: '${1}'\n"; do_help; exit 1;;
   328     esac
   329 done
   330 
   331 # Use defaults
   332 [ -z "${PREFIX}" ] && set_prefix "" "${PREFIX_DEFAULT}"
   333 
   334 # Special case when installing locally
   335 if [ "${LOCAL_set}" = "y" ]; then
   336     set_prefix "" "$( pwd )"
   337     set_bindir "" "$( pwd )"
   338     set_libdir "" "$( pwd )"
   339     set_docdir "" "$( pwd )/docs"
   340     set_mandir "" "$( pwd )/docs"
   341 fi
   342 
   343 #---------------------------------------------------------------------
   344 # Some sanity checks, now
   345 
   346 # We check for grep and sed manually, because they are used in check_for()
   347 printf "Checking for 'grep'... "
   348 if [ -n "${grep}" ]; then
   349     printf "${grep} (cached)\n"
   350 else
   351     grep="$( which grep 2>/dev/null )"
   352     if [ -z "${grep}" ]; then
   353         printf "not found\n"
   354     else
   355         printf "${grep}\n"
   356         printf "Checking whether '${grep}' supports -E... "
   357         if echo 'foo' |"${grep}" -E 'foo' >/dev/null 2>&1; then
   358             printf "yes\n"
   359         else
   360             printf "no\n"
   361             grep=
   362         fi
   363     fi
   364 fi
   365 if [ -z "${grep}" ]; then
   366     printf "Either you are missing entirely the needed tool,\n"
   367     printf "or the version you have is too old.\n"
   368     printf "You can give the path to this tool using: --with-grep=PATH\n"
   369     do_error "Bailing out..."
   370 fi
   371 add_to_var_list grep
   372 
   373 printf "Checking for 'sed'... "
   374 if [ -n "${sed}" ]; then
   375     printf "${sed} (cached)\n"
   376 else
   377     sed="$( which sed 2>/dev/null )"
   378     if [ -z "${sed}" ]; then
   379         printf "not found\n"
   380     else
   381         printf "${sed}\n"
   382         printf "Checking whether '${sed}' supports -i and -e... "
   383         touch .ct-ng.sed.test
   384         if "${sed}" -r -i -e 's/foo/bar/' .ct-ng.sed.test >/dev/null 2>&1; then
   385             printf "yes\n"
   386         else
   387             printf "no\n"
   388             sed=
   389         fi
   390         rm -f .ct-ng.sed.test
   391     fi
   392 fi
   393 if [ -z "${sed}" ]; then
   394     printf "Either you are missing entirely the needed tool,\n"
   395     printf "or the version you have is too old.\n"
   396     printf "You can give the path to this tool using: --with-sed=PATH\n"
   397     do_error "Bailing out..."
   398 fi
   399 add_to_var_list sed
   400 
   401 # The regular list of tools we can now easily check for
   402 has_or_abort prog=bash                              \
   403              var=bash                               \
   404              ver='^GNU bash, version (3\.[1-9]|4)'  \
   405              err="'bash' 3.1 or above was not found"
   406 has_or_abort prog=cut
   407 has_or_abort prog=install var=install
   408 has_or_abort prog=make                                  \
   409              var=make                                   \
   410              ver='^GNU Make (3.[89][[:digit:]]|[4-9])'  \
   411              err="GNU 'make' 3.80 or above was not found"
   412 has_or_abort prog=gcc
   413 has_or_abort prog="awk gawk" ver='^GNU Awk' err="GNU 'awk' was not found"
   414 has_or_abort prog=bison
   415 has_or_abort prog=flex
   416 has_or_abort prog=makeinfo
   417 has_or_abort prog=automake                                                      \
   418              ver='\(GNU automake\) (1\.[[:digit:]]{2,}|[2-9][[:digit:]]*\.)'    \
   419              err="'automake' 1.10 or above was not found"
   420 has_or_abort prog=libtool                                                                           \
   421              var=libtool                                                                            \
   422              ver='\(GNU libtool.*\) (2[[:digit:]]*\.|1\.6[[:digit:]]*\.|1\.5\.[2-9][[:digit:]]+)'   \
   423              err="'libtool' 1.5.26 or above was not found"
   424 has_or_abort prog=stat
   425 has_or_abort prog="curl wget"
   426 has_or_abort prog=cvs
   427 has_or_abort prog=patch
   428 has_or_abort prog=tar
   429 has_or_abort prog=gzip
   430 has_or_abort prog=bzip2
   431 has_or_abort prog=lzma
   432 has_or_abort prog=readlink
   433 has_or_abort prog=objcopy var=objcopy
   434 has_or_abort prog=objdump var=objdump
   435 has_or_abort prog=readelf var=readelf
   436 has_or_abort prog=patch var=patch
   437 
   438 has_or_abort inc="ncurses/ncurses.h ncurses/curses.h ncurses.h curses.h"    \
   439              err="'ncurses' headers files were not found"
   440 
   441 ncurses_libs="$( for l in ncursesw ncurses curses; do   \
   442                      for x in so a dylib; do            \
   443                          printf "lib$l.$x ";            \
   444                      done;                              \
   445                  done                                   \
   446                )"
   447 has_or_abort lib="${ncurses_libs}"                  \
   448              err="The 'ncurses' library is needed fo the menuconfig frontend"
   449 
   450 stdcxx_libs="$( for x in so dylib a; do \
   451                    printf "libstdc++.$x "; \
   452                done \
   453              )"
   454 has_or_abort lib="${stdcxx_libs}" \
   455              err="The 'libstdc++' library is needed to build gcc"
   456 
   457 # Yes, we may be checking twice for libstdc++.a
   458 # The first is because we need one instance of libstdc++ (shared or static)
   459 # because it is needed for PPL; the second is because the static version is
   460 # required for static-linking, and if missing, the option is removed.
   461 has_or_warn  lib="libstdc++.a" \
   462              err="static 'libstdc++' is needed to statically link the toolchain's executables" \
   463              kconfig=has_static_libstdcxx
   464 
   465 #---------------------------------------------------------------------
   466 # Compute the version string
   467 
   468 # If this version is n hg clone, try to get the revision number
   469 # If we can't get the revision number, use date
   470 printf "\nComputing version string... "
   471 case "${VERSION}" in
   472     *+hg|hg)
   473         REVISION="$( hg id -n 2>/dev/null || true )"
   474         case "${REVISION}" in
   475             "")
   476                 VERSION="${VERSION}_unknown@$( date +%Y%m%d.%H%M%S )";;
   477             *)
   478                 VERSION="${VERSION}_$( hg id -b )@${REVISION%%+}_$( hg id -i )"
   479                 ;;
   480         esac
   481         # Arrange to have no / in the directory name, no need to create an
   482         # arbitrarily deep directory structure
   483         VERSION="$( printf "${VERSION}\n" |"${sed}" -r -e 's|/+|_|g;' )"
   484         ;;
   485 esac
   486 printf "${VERSION}\n"
   487 
   488 #---------------------------------------------------------------------
   489 # Compute and check install paths
   490 
   491 # Now we have the version string, we can build up the paths
   492 [ -z "${BINDIR_set}" ] && BINDIR="${PREFIX}/bin"
   493 [ -z "${LIBDIR_set}" ] && LIBDIR="${PREFIX}/lib"
   494 [ -z "${DOCDIR_set}" ] && DOCDIR="${PREFIX}/share/doc"
   495 [ -z "${MANDIR_set}" ] && MANDIR="${PREFIX}/share/man"
   496 
   497 # Install support files in our own sub-dir, so as not to mangle (system)
   498 # files and dirs, but only if not --local
   499 if [ -z "${LOCAL_set}" ]; then
   500     LIBDIR="${LIBDIR}/ct-ng-${VERSION}"
   501     DOCDIR="${DOCDIR}/ct-ng-${VERSION}"
   502 fi
   503 
   504 # Check that install PATHs are absolute
   505 for p in BIN LIB DOC MAN; do
   506     var="${p}DIR"
   507     eval v='"${'"${var}"'}"'
   508     case "${v}" in
   509         /*) ;;
   510         *)  do_error "'${var}' is not an absolute path: '${v}'"
   511     esac
   512 done
   513 
   514 #---------------------------------------------------------------------
   515 # That's all, folks!
   516 
   517 printf "Building up Makefile... "
   518 var_sed="$( for var_name in ${var_list}; do
   519                 eval echo 's,@@${var_name}@@,${'"${var_name}"'},g'
   520             done
   521           )"
   522 kconfig_sed="s/@@KCONFIG@@/$( for k_name in ${kconfig_list}; do
   523                                   eval printf \"${k_name}=\${${k_name}} \"
   524                               done
   525                             )/"
   526 "${sed}" -r -e "s,@@BINDIR@@,${BINDIR},g"       \
   527             -e "s,@@LIBDIR@@,${LIBDIR},g"       \
   528             -e "s,@@DOCDIR@@,${DOCDIR},g"       \
   529             -e "s,@@MANDIR@@,${MANDIR},g"       \
   530             -e "s,@@VERSION@@,${VERSION},g"     \
   531             -e "s,@@DATE@@,${DATE},g"           \
   532             -e "s,@@LOCAL@@,${LOCAL_set},g"     \
   533             -e "${var_sed}"                     \
   534             -e "${kconfig_sed}"                 \
   535          Makefile.in                            \
   536          >Makefile
   537 echo "done"
   538 
   539 cat <<__EOF__
   540 
   541 crosstool-NG configured as follows:
   542   PREFIX='${PREFIX}'
   543   BINDIR='${BINDIR}'
   544   LIBDIR='${LIBDIR}'
   545   DOCDIR='${DOCDIR}'
   546   MANDIR='${MANDIR}'
   547 
   548 Now run:
   549   make
   550 __EOF__
   551 if [ "${LOCAL_set}" != "y" ]; then
   552     printf "  make install\n"
   553 fi