configure
author "Yann E. MORIN" <yann.morin.1998@anciens.enib.fr>
Wed Aug 19 19:52:04 2009 +0200 (2009-08-19)
changeset 1485 d031a67fc494
parent 1432 76f8feef64c4
parent 1477 232ba0dc96b1
child 1560 79a609170a83
permissions -rwxr-xr-x
Merge the bash_array branch.

For every components where it makes sense, use bash arrays (instead
of a string with space-separated values) to store the options pased
to ./configure.
     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 
    73 # This function adds a variable name to the above list of variable names.
    74 # $1: the name of the variable to add to the list
    75 add_to_var_list() {
    76     var_list="${var_list} ${1}"
    77 }
    78 
    79 # A function to test for required tools/headers/libraries
    80 # $*: [prog|inc|lib]=<name[ name...]>
    81 #     the name(s) of tool(s) to test for
    82 #     mandatory
    83 #       eg: prog=bash   prog="curl wget"
    84 # $*: var=<var_name>
    85 #     the name of the variable to test and set
    86 #     optional
    87 #       eg: var=bash    if ${bash} is set and non-null, use that,
    88 #                       else check for bash and set bash=$(which bash)
    89 # $*: ver=<regexp>
    90 #     for each 'prog', test if $(prog --version) matches 'regexp'
    91 #     optional
    92 #       eg: ver='^GNU bash, version [34]\.'
    93 # $*: err=<error_message>
    94 #     the error message to print if tool is missing
    95 #     optional, defaults to: '${prog}: none found'
    96 #       eg: err="'bash' 3.x or above was not found"
    97 has_or_abort() {
    98     local prog inc lib
    99     local var ver err
   100     local val
   101     local item
   102     local where
   103     local status
   104 
   105     for item in "${@}"; do
   106         case "${item}" in
   107             prog=*|inc=*|lib=*|var=*|ver=*|err=*)
   108                 eval ${item%%=*}="'${item#*=}'"
   109                 ;;
   110             *)  do_error "has_or_abort: incorrect parameters: '$@'";;
   111         esac
   112     done
   113 
   114     case "${prog}:${inc}:${lib}" in
   115         ?*::)
   116             for item in ${prog}; do
   117                 printf "Checking for '${item}'... "
   118                 if [ -n "${var}" ]; then
   119                     eval val="\${${var}}"
   120                     if [ -n "${val}" ]; then
   121                         printf "${val} (cached)\n"
   122                         return 0
   123                     fi
   124                 fi
   125                 where="$( which "${item}" 2>/dev/null )"
   126                 if [ -z "${where}" ]; then
   127                     printf "no\n"
   128                     continue
   129                 elif [ -n "${ver}" ]; then
   130                     str=$( "${where}" --version 2>&1 |grep -E "${ver}" |head -n 1 )
   131                     if [ -z "${str}" ]; then
   132                         printf "no\n"
   133                         unset where
   134                         continue
   135                     fi
   136                 fi
   137                 status="${where}"
   138                 break
   139             done
   140             ;;
   141         :?*:)
   142             for item in ${inc}; do
   143                 printf "Checking for '${item}'... "
   144                 if printf "#include \"${item}\"" |gcc -x c -c - -o /dev/null >/dev/null 2>&1; then
   145                     where="${item}"
   146                     status=yes
   147                     break;
   148                 fi
   149                 printf "no\n"
   150             done
   151             ;;
   152         ::?*)
   153             for item in ${lib}; do
   154                 printf "Checking for '${item}'... "
   155                 where="$( gcc -print-file-name="${item}" )"
   156                 if [ "${where}" != "${item}" ]; then
   157                     where="$( readlink -e "${where}" )"
   158                     status=yes
   159                     break;
   160                 fi
   161                 printf "no\n"
   162             done
   163             ;;
   164     esac
   165     if [ -z "${status}" ]; then
   166         printf "\n${err:-${prog}${inc}${lib}: none found}\n\n"
   167         printf "Either you are missing entirely the needed tool,\n"
   168         printf "or the version you have is too old.\n"
   169         if [ -n "${var}" ]; then
   170             printf "You can give the path to this tool using: --with-${var}=PATH\n"
   171         fi
   172         # FORCE can be set in the environment
   173         [ -z "${FORCE}" ] && do_error "Bailing out..."
   174         printf "\n"
   175         printf "<*                                          *>\n"
   176         printf "<*            FORCE in action:              *>\n"
   177         printf "<* Continuing despite missing pre-requisite *>\n"
   178         printf "<*          Prepare for breakage            *>\n"
   179         printf "<*                                          *>\n"
   180         printf "\n"
   181     else
   182         printf "${status}"
   183         if [ -n "${var}" ]; then
   184             eval ${var}='"'"${where}"'"'
   185             add_to_var_list "${var}"
   186         fi
   187         printf "\n"
   188     fi
   189 }
   190 
   191 do_help() {
   192     cat <<__EOF__
   193 \`configure' configures crosstool-NG-${VERSION} to adapt to many kind of systems.
   194 
   195 USAGE: ./configure [OPTION]...
   196 
   197 Defaults for the options are specified in brackets.
   198 
   199 Configuration:
   200   -h, --help              display this help and exit
   201       --force             force configure to continue, even in case
   202                           some pre-requisites are missing
   203 
   204 Installation directories:
   205   --prefix=PREFIX         install files in PREFIX [${PREFIX_DEFAULT}]
   206   --local                 don't install, and use current directory
   207 
   208 By default, \`make install' will install all the files in
   209 \`${PREFIX_DEFAULT}/bin', \`${PREFIX_DEFAULT}/lib' etc.  You can specify
   210 an installation prefix other than \`${PREFIX_DEFAULT}' using \`--prefix',
   211 for instance \`--prefix=\${HOME}'.
   212 
   213 For better control, use the options below.
   214 
   215 Fine tuning of the installation directories:
   216   --bindir=DIR            user executables [PREFIX/bin]
   217   --libdir=DIR            object code libraries [PREFIX/lib]
   218   --docdir=DIR            info documentation [PREFIX/share/doc]
   219   --mandir=DIR            man documentation [PREFIX/share/man]
   220 
   221 Optional Features:
   222   --with-install=PATH     Specify the full PATH to GNU install
   223   --with-make=PATH        Specify the full PATH to GNU make >= 3.80
   224   --with-grep=PATH        Specify the full PATH to GNU grep
   225   --with-sed=PATH         Specify the full PATH to GNU sed
   226   --with-bash=PATH        Specify the full PATH to bash >= 3.0
   227 __EOF__
   228 }
   229 
   230 #---------------------------------------------------------------------
   231 # Set user's options
   232 
   233 while [ $# -ne 0 ]; do
   234     case "$1" in
   235         --local)    LOCAL_set="y"; shift;;
   236         --prefix*)  set_prefix "$1" "$2" && shift || shift 2;;
   237         --bindir*)  set_bindir "$1" "$2" && shift || shift 2;;
   238         --libdir*)  set_libdir "$1" "$2" && shift || shift 2;;
   239         --docdir*)  set_docdir "$1" "$2" && shift || shift 2;;
   240         --mandir*)  set_mandir "$1" "$2" && shift || shift 2;;
   241         --with-*)   set_tool   "$1" "$2" && shift || shift 2;;
   242         --force)    FORCE=1; shift;;
   243         --help|-h)  do_help; exit 0;;
   244         *)          printf "Unrecognised option: '${1}'\n"; do_help; exit 1;;
   245     esac
   246 done
   247 
   248 # Use defaults
   249 [ -z "${PREFIX}" ] && set_prefix "" "${PREFIX_DEFAULT}"
   250 
   251 # Special case when installing locally
   252 if [ "${LOCAL_set}" = "y" ]; then
   253     set_prefix "" "$( pwd )"
   254     set_bindir "" "$( pwd )"
   255     set_libdir "" "$( pwd )"
   256     set_docdir "" "$( pwd )/docs"
   257     set_mandir "" "$( pwd )/docs"
   258 fi
   259 
   260 #---------------------------------------------------------------------
   261 # Some sanity checks, now
   262 
   263 # We check for grep and sed manually, because they are used in has_or_abort
   264 printf "Checking for 'grep'... "
   265 if [ -n "${grep}" ]; then
   266     printf "${grep} (cached)\n"
   267 else
   268     grep="$( which grep 2>/dev/null )"
   269     if [ -z "${grep}" ]; then
   270         printf "not found\n"
   271     else
   272         printf "${grep}\n"
   273         printf "Checking whether '${grep}' supports -E... "
   274         if echo 'foo' |"${grep}" -E 'foo' >/dev/null 2>&1; then
   275             printf "yes\n"
   276         else
   277             printf "no\n"
   278             grep=
   279         fi
   280     fi
   281 fi
   282 if [ -z "${grep}" ]; then
   283     printf "Either you are missing entirely the needed tool,\n"
   284     printf "or the version you have is too old.\n"
   285     printf "You can give the path to this tool using: --with-grep=PATH\n"
   286     do_error "Bailing out..."
   287 fi
   288 add_to_var_list grep
   289 
   290 printf "Checking for 'sed'... "
   291 if [ -n "${sed}" ]; then
   292     printf "${sed} (cached)\n"
   293 else
   294     sed="$( which sed 2>/dev/null )"
   295     if [ -z "${sed}" ]; then
   296         printf "not found\n"
   297     else
   298         printf "${sed}\n"
   299         printf "Checking whether '${sed}' supports -i and -e... "
   300         touch .ct-ng.sed.test
   301         if "${sed}" -r -i -e 's/foo/bar/' .ct-ng.sed.test >/dev/null 2>&1; then
   302             printf "yes\n"
   303         else
   304             printf "no\n"
   305             sed=
   306         fi
   307         rm -f .ct-ng.sed.test
   308     fi
   309 fi
   310 if [ -z "${sed}" ]; then
   311     printf "Either you are missing entirely the needed tool,\n"
   312     printf "or the version you have is too old.\n"
   313     printf "You can give the path to this tool using: --with-sed=PATH\n"
   314     do_error "Bailing out..."
   315 fi
   316 add_to_var_list sed
   317 
   318 # The regular list of tools we can now easily check for
   319 has_or_abort prog=bash                              \
   320              var=bash                               \
   321              ver='^GNU bash, version (3\.[1-9]|4)'  \
   322              err="'bash' 3.1 or above was not found"
   323 has_or_abort prog=cut
   324 has_or_abort prog=install var=install
   325 has_or_abort prog=make                                  \
   326              var=make                                   \
   327              ver='^GNU Make (3.[89][[:digit:]]|[4-9])'  \
   328              err="GNU 'make' 3.80 or above was not found"
   329 has_or_abort prog=gcc
   330 has_or_abort prog="awk gawk" ver='^GNU Awk' err="GNU 'awk' was not found"
   331 has_or_abort prog=bison
   332 has_or_abort prog=flex
   333 has_or_abort prog=makeinfo
   334 has_or_abort prog=automake                                                      \
   335              ver='\(GNU automake\) (1\.[[:digit:]]{2,}|[2-9][[:digit:]]*\.)'    \
   336              err="'automake' 1.10 or above was not found"
   337 has_or_abort prog=libtool                                                                           \
   338              ver='\(GNU libtool.*\) (2[[:digit:]]*\.|1\.6[[:digit:]]*\.|1\.5\.[2-9][[:digit:]]+)'   \
   339              err="'libtool' 1.5.26 or above was not found"
   340 has_or_abort prog=stat ver='GNU coreutils'
   341 has_or_abort prog="curl wget"
   342 has_or_abort prog=cvs
   343 has_or_abort prog=patch
   344 has_or_abort prog=tar
   345 has_or_abort prog=gzip
   346 has_or_abort prog=bzip2
   347 has_or_abort prog=lzma
   348 has_or_abort prog=readlink
   349 
   350 has_or_abort inc="ncurses/ncurses.h ncurses/curses.h ncurses.h curses.h"    \
   351              err="'ncurses' headers files were not found"
   352 
   353 ncurses_libs="$( for l in ncursesw ncurses curses; do   \
   354                      for x in so a dylib; do            \
   355                          printf "lib$l.$x ";            \
   356                      done;                              \
   357                  done                                   \
   358                )"
   359 has_or_abort lib="${ncurses_libs}"                  \
   360              err="'ncurses' library was not found"
   361 
   362 #---------------------------------------------------------------------
   363 # Compute the version string
   364 
   365 # If this version is a svn snapshot, try to get the revision number
   366 # If we can't get the revision number, use date
   367 case "${VERSION}" in
   368     *+hg|hg)
   369         has_or_abort prog=hg
   370         printf "Computing version string... "
   371         REVISION="$( hg id -n 2>/dev/null )"
   372         case "${REVISION}" in
   373             "")
   374                 VERSION="${VERSION}_unknown@$( date +%Y%m%d.%H%M%S )";;
   375             *)
   376                 VERSION="${VERSION}_$( hg id -b )@${REVISION%%+}_$( hg id -i )"
   377                 ;;
   378         esac
   379         # Arrange to have no / in the directory name, no need to create an
   380         # arbitrarily deep directory structure
   381         VERSION="$( printf "${VERSION}\n" |"${sed}" -r -e 's|/+|_|g;' )"
   382         ;;
   383 esac
   384 echo "${VERSION}"
   385 
   386 #---------------------------------------------------------------------
   387 # Compute and check install paths
   388 
   389 # Now we have the version string, we can build up the paths
   390 [ -z "${BINDIR_set}" ] && BINDIR="${PREFIX}/bin"
   391 [ -z "${LIBDIR_set}" ] && LIBDIR="${PREFIX}/lib/ct-ng-${VERSION}"
   392 [ -z "${DOCDIR_set}" ] && DOCDIR="${PREFIX}/share/doc/ct-ng-${VERSION}"
   393 [ -z "${MANDIR_set}" ] && MANDIR="${PREFIX}/share/man/man1"
   394 
   395 # Check that install PATHs are absolute
   396 for p in BIN LIB DOC MAN; do
   397     var="${p}DIR"
   398     eval v='"${'"${var}"'}"'
   399     case "${v}" in
   400         /*) ;;
   401         *)  do_error "'${var}' is not an absolute path: '${v}'"
   402     esac
   403 done
   404 
   405 #---------------------------------------------------------------------
   406 # That's all, folks!
   407 
   408 printf "Building up Makefile... "
   409 var_sed="$( for var_name in ${var_list}; do
   410                 eval echo 's,@@${var_name}@@,${'"${var_name}"'},g'
   411             done 
   412           )"
   413 "${sed}" -r -e "s,@@BINDIR@@,${BINDIR},g
   414                 s,@@LIBDIR@@,${LIBDIR},g
   415                 s,@@DOCDIR@@,${DOCDIR},g
   416                 s,@@MANDIR@@,${MANDIR},g
   417                 s,@@VERSION@@,${VERSION},g
   418                 s,@@DATE@@,${DATE},g
   419                 ${var_sed}
   420                 s,@@LOCAL@@,${LOCAL_set},g"  Makefile.in >Makefile
   421 echo "done"
   422 
   423 cat <<__EOF__
   424 
   425 crosstool-NG configured as follows:
   426   PREFIX='${PREFIX}'
   427   BINDIR='${BINDIR}'
   428   LIBDIR='${LIBDIR}'
   429   DOCDIR='${DOCDIR}'
   430   MANDIR='${MANDIR}'
   431 
   432 Now run:
   433   make
   434 __EOF__
   435 if [ "${LOCAL_set}" != "y" ]; then
   436     printf "  make install\n"
   437 fi