configure
author "Yann E. MORIN" <yann.morin.1998@anciens.enib.fr>
Thu Jun 02 19:58:05 2011 +0200 (2011-06-02)
changeset 2497 ac4c006c48e4
parent 2481 30644208c955
child 2498 6b479665a053
permissions -rwxr-xr-x
configure: maintain single quotes in error messages

Signed-off-by: "Yann E. MORIN" <yann.morin.1998@anciens.enib.fr>
     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 "has_or_abort: incorrect parameters: '$@'";;
   131         esac
   132     done
   133 
   134     if [ -n "${kconfig}" ]; then
   135         add_to_kconfig_list "${kconfig}"
   136     fi
   137 
   138     case "${prog}:${inc}:${lib}" in
   139         ?*::)
   140             for item in ${prog}; do
   141                 printf "Checking for '${item}'... "
   142                 if [ -n "${var}" ]; then
   143                     eval val="\${${var}}"
   144                     if [ -n "${val}" ]; then
   145                         printf "${val} (cached)\n"
   146                         add_to_var_list "${var}"
   147                         return 0
   148                     fi
   149                 fi
   150                 where="$( which "${item}" 2>/dev/null )"
   151                 if [ -z "${where}" ]; then
   152                     printf "no\n"
   153                     continue
   154                 elif [ -n "${ver}" ]; then
   155                     str=$( LC_ALL=C "${where}" --version 2>&1   \
   156                            |grep -E "${ver}"                    \
   157                            |head -n 1
   158                          )
   159                     if [ -z "${str}" ]; then
   160                         printf "no\n"
   161                         unset where
   162                         continue
   163                     fi
   164                 fi
   165                 status="${where}"
   166                 break
   167             done
   168             ;;
   169         :?*:)
   170             for item in ${inc}; do
   171                 printf "Checking for '${item}'... "
   172                 if printf "#include \"${item}\"" |gcc -x c -c - -o /dev/null >/dev/null 2>&1; then
   173                     where="${item}"
   174                     status=yes
   175                     break;
   176                 fi
   177                 printf "no\n"
   178             done
   179             ;;
   180         ::?*)
   181             for item in ${lib}; do
   182                 printf "Checking for '${item}'... "
   183                 where="$( gcc -print-file-name="${item}" )"
   184                 if [ "${where}" != "${item}" ]; then
   185                     where="$( readlink "${where}" )"
   186                     status=yes
   187                     break;
   188                 fi
   189                 printf "no\n"
   190             done
   191             ;;
   192     esac
   193 
   194     if [ -z "${status}" ]; then
   195         return 1
   196     fi
   197 
   198     printf "${status}"
   199     if [ -n "${var}" ]; then
   200         eval ${var}='"'"${where}"'"'
   201         add_to_var_list "${var}"
   202     fi
   203     if [ -n "${kconfig}" ]; then
   204         eval ${kconfig}=y
   205     fi
   206     printf "\n"
   207 }
   208 
   209 # This function checks for a tool, and aborts if not found
   210 # See check_for(), above, for how to call has_or_abort
   211 has_or_abort() {
   212     # We declare these 6 variables here, although they are
   213     # set in check_for(), called below
   214     local prog inc lib
   215     local var ver err kconfig
   216 
   217     if ! check_for "$@"; then
   218         printf "\n${err:-${prog}${inc}${lib}: none found}\n\n"
   219         printf "Either you are missing entirely the needed tool,\n"
   220         printf "or the version you have is too old.\n"
   221         if [ -n "${var}" ]; then
   222             printf "You can give the path to this tool using: --with-${var}=PATH\n"
   223         fi
   224         printf "\n"
   225         # Bail out if --force is not specified
   226         [ -z "${FORCE}" ] && do_error "Bailing out..."
   227         printf "<*                                          *>\n"
   228         printf "<*            FORCE in action:              *>\n"
   229         printf "<* Continuing despite missing pre-requisite *>\n"
   230         printf "<*          Prepare for breakage            *>\n"
   231         printf "<*                                          *>\n"
   232         printf "\n"
   233     fi
   234 }
   235 
   236 # This function checks for a tool, and warns if not found
   237 # See check_for(), above, for how to call has_or_abort
   238 # Note: if err is not set, then no error message is printed
   239 has_or_warn() {
   240     # We declare these 6 variables here, although they are
   241     # set in check_for(), called below
   242     local prog inc lib
   243     local var ver err kconfig
   244 
   245     if ! check_for "$@"; then
   246         printf "${err:+${err}\n}"
   247         if [ -n "${var}" ]; then
   248             printf -- "--> You can give the path to this tool using: --with-${var}=PATH\n"
   249         fi
   250     fi
   251 }
   252 
   253 do_help() {
   254     cat <<__EOF__
   255 \`configure' configures crosstool-NG-${VERSION} to adapt to many kind of systems.
   256 
   257 USAGE: ./configure [OPTION]...
   258 
   259 Defaults for the options are specified in brackets.
   260 
   261 Configuration:
   262   -h, --help              display this help and exit
   263       --force             force configure to continue, even in case
   264                           some pre-requisites are missing
   265 
   266 Installation directories:
   267   --prefix=PREFIX         install files in PREFIX [${PREFIX_DEFAULT}]
   268   --local                 don't install, and use current directory
   269 
   270 By default, \`make install' will install all the files in
   271 \`${PREFIX_DEFAULT}/bin', \`${PREFIX_DEFAULT}/lib' etc.  You can specify
   272 an installation prefix other than \`${PREFIX_DEFAULT}' using \`--prefix',
   273 for instance \`--prefix=\${HOME}'.
   274 
   275 For better control, use the options below.
   276 
   277 Fine tuning of the installation directories:
   278   --bindir=DIR            user executables [PREFIX/bin]
   279   --libdir=DIR            object code libraries [PREFIX/lib]
   280   --docdir=DIR            info documentation [PREFIX/share/doc]
   281   --mandir=DIR            man documentation [PREFIX/share/man]
   282 
   283 Optional Features:
   284   --with-install=PATH     Specify the full PATH to GNU install
   285   --with-make=PATH        Specify the full PATH to GNU make >= 3.80
   286   --with-grep=PATH        Specify the full PATH to GNU grep
   287   --with-sed=PATH         Specify the full PATH to GNU sed
   288   --with-bash=PATH        Specify the full PATH to bash >= 3.0
   289 __EOF__
   290 }
   291 
   292 #---------------------------------------------------------------------
   293 # Set user's options
   294 
   295 while [ $# -ne 0 ]; do
   296     case "$1" in
   297         --local)    LOCAL_set="y"; shift;;
   298         --prefix*)  set_prefix "$1" "$2" && shift || shift 2;;
   299         --bindir*)  set_bindir "$1" "$2" && shift || shift 2;;
   300         --libdir*)  set_libdir "$1" "$2" && shift || shift 2;;
   301         --docdir*)  set_docdir "$1" "$2" && shift || shift 2;;
   302         --mandir*)  set_mandir "$1" "$2" && shift || shift 2;;
   303         --with-*)   set_tool   "$1" "$2" && shift || shift 2;;
   304         --force)    FORCE=1; shift;;
   305         --help|-h)  do_help; exit 0;;
   306         # Skip, auto-stuff compatibility
   307         --build=*|--host=*|--infodir=*|--datadir=*|--sysconfdir=*|--localstatedir=*) shift;;
   308         --build|--host|--infodir|--datadir|--sysconfdir|--localstatedir)             shift 2;;
   309         *)          printf "Unrecognised option: '${1}'\n"; do_help; exit 1;;
   310     esac
   311 done
   312 
   313 # Use defaults
   314 [ -z "${PREFIX}" ] && set_prefix "" "${PREFIX_DEFAULT}"
   315 
   316 # Special case when installing locally
   317 if [ "${LOCAL_set}" = "y" ]; then
   318     set_prefix "" "$( pwd )"
   319     set_bindir "" "$( pwd )"
   320     set_libdir "" "$( pwd )"
   321     set_docdir "" "$( pwd )/docs"
   322     set_mandir "" "$( pwd )/docs"
   323 fi
   324 
   325 #---------------------------------------------------------------------
   326 # Some sanity checks, now
   327 
   328 # We check for grep and sed manually, because they are used in check_for()
   329 printf "Checking for 'grep'... "
   330 if [ -n "${grep}" ]; then
   331     printf "${grep} (cached)\n"
   332 else
   333     grep="$( which grep 2>/dev/null )"
   334     if [ -z "${grep}" ]; then
   335         printf "not found\n"
   336     else
   337         printf "${grep}\n"
   338         printf "Checking whether '${grep}' supports -E... "
   339         if echo 'foo' |"${grep}" -E 'foo' >/dev/null 2>&1; then
   340             printf "yes\n"
   341         else
   342             printf "no\n"
   343             grep=
   344         fi
   345     fi
   346 fi
   347 if [ -z "${grep}" ]; then
   348     printf "Either you are missing entirely the needed tool,\n"
   349     printf "or the version you have is too old.\n"
   350     printf "You can give the path to this tool using: --with-grep=PATH\n"
   351     do_error "Bailing out..."
   352 fi
   353 add_to_var_list grep
   354 
   355 printf "Checking for 'sed'... "
   356 if [ -n "${sed}" ]; then
   357     printf "${sed} (cached)\n"
   358 else
   359     sed="$( which sed 2>/dev/null )"
   360     if [ -z "${sed}" ]; then
   361         printf "not found\n"
   362     else
   363         printf "${sed}\n"
   364         printf "Checking whether '${sed}' supports -i and -e... "
   365         touch .ct-ng.sed.test
   366         if "${sed}" -r -i -e 's/foo/bar/' .ct-ng.sed.test >/dev/null 2>&1; then
   367             printf "yes\n"
   368         else
   369             printf "no\n"
   370             sed=
   371         fi
   372         rm -f .ct-ng.sed.test
   373     fi
   374 fi
   375 if [ -z "${sed}" ]; then
   376     printf "Either you are missing entirely the needed tool,\n"
   377     printf "or the version you have is too old.\n"
   378     printf "You can give the path to this tool using: --with-sed=PATH\n"
   379     do_error "Bailing out..."
   380 fi
   381 add_to_var_list sed
   382 
   383 # The regular list of tools we can now easily check for
   384 has_or_abort prog=bash                              \
   385              var=bash                               \
   386              ver='^GNU bash, version (3\.[1-9]|4)'  \
   387              err="'bash' 3.1 or above was not found"
   388 has_or_abort prog=cut
   389 has_or_abort prog=install var=install
   390 has_or_abort prog=make                                  \
   391              var=make                                   \
   392              ver='^GNU Make (3.[89][[:digit:]]|[4-9])'  \
   393              err="GNU 'make' 3.80 or above was not found"
   394 has_or_abort prog=gcc
   395 has_or_abort prog="awk gawk" ver='^GNU Awk' err="GNU 'awk' was not found"
   396 has_or_abort prog=bison
   397 has_or_abort prog=flex
   398 has_or_abort prog=makeinfo
   399 has_or_abort prog=automake                                                      \
   400              ver='\(GNU automake\) (1\.[[:digit:]]{2,}|[2-9][[:digit:]]*\.)'    \
   401              err="'automake' 1.10 or above was not found"
   402 has_or_abort prog=libtool                                                                           \
   403              var=libtool                                                                            \
   404              ver='\(GNU libtool.*\) (2[[:digit:]]*\.|1\.6[[:digit:]]*\.|1\.5\.[2-9][[:digit:]]+)'   \
   405              err="'libtool' 1.5.26 or above was not found"
   406 has_or_abort prog=stat
   407 has_or_abort prog="curl wget"
   408 has_or_abort prog=cvs
   409 has_or_abort prog=patch
   410 has_or_abort prog=tar
   411 has_or_abort prog=gzip
   412 has_or_abort prog=bzip2
   413 has_or_abort prog=lzma
   414 has_or_abort prog=readlink
   415 has_or_abort prog=objcopy var=objcopy
   416 has_or_abort prog=objdump var=objdump
   417 has_or_abort prog=readelf var=readelf
   418 has_or_abort prog=patch var=patch
   419 
   420 has_or_abort inc="ncurses/ncurses.h ncurses/curses.h ncurses.h curses.h"    \
   421              err="'ncurses' headers files were not found"
   422 
   423 ncurses_libs="$( for l in ncursesw ncurses curses; do   \
   424                      for x in so a dylib; do            \
   425                          printf "lib$l.$x ";            \
   426                      done;                              \
   427                  done                                   \
   428                )"
   429 has_or_abort lib="${ncurses_libs}"                  \
   430              err="'ncurses' library was not found"
   431 
   432 #---------------------------------------------------------------------
   433 # Compute the version string
   434 
   435 # If this version is n hg clone, try to get the revision number
   436 # If we can't get the revision number, use date
   437 printf "Computing version string... "
   438 case "${VERSION}" in
   439     *+hg|hg)
   440         REVISION="$( hg id -n 2>/dev/null || true )"
   441         case "${REVISION}" in
   442             "")
   443                 VERSION="${VERSION}_unknown@$( date +%Y%m%d.%H%M%S )";;
   444             *)
   445                 VERSION="${VERSION}_$( hg id -b )@${REVISION%%+}_$( hg id -i )"
   446                 ;;
   447         esac
   448         # Arrange to have no / in the directory name, no need to create an
   449         # arbitrarily deep directory structure
   450         VERSION="$( printf "${VERSION}\n" |"${sed}" -r -e 's|/+|_|g;' )"
   451         ;;
   452 esac
   453 printf "${VERSION}\n"
   454 
   455 #---------------------------------------------------------------------
   456 # Compute and check install paths
   457 
   458 # Now we have the version string, we can build up the paths
   459 [ -z "${BINDIR_set}" ] && BINDIR="${PREFIX}/bin"
   460 [ -z "${LIBDIR_set}" ] && LIBDIR="${PREFIX}/lib"
   461 [ -z "${DOCDIR_set}" ] && DOCDIR="${PREFIX}/share/doc"
   462 [ -z "${MANDIR_set}" ] && MANDIR="${PREFIX}/share/man"
   463 
   464 # Install support files in our own sub-dir, so as not to mangle (system)
   465 # files and dirs, but only if not --local
   466 if [ -z "${LOCAL_set}" ]; then
   467     LIBDIR="${LIBDIR}/ct-ng-${VERSION}"
   468     DOCDIR="${DOCDIR}/ct-ng-${VERSION}"
   469 fi
   470 
   471 # Check that install PATHs are absolute
   472 for p in BIN LIB DOC MAN; do
   473     var="${p}DIR"
   474     eval v='"${'"${var}"'}"'
   475     case "${v}" in
   476         /*) ;;
   477         *)  do_error "'${var}' is not an absolute path: '${v}'"
   478     esac
   479 done
   480 
   481 #---------------------------------------------------------------------
   482 # That's all, folks!
   483 
   484 printf "Building up Makefile... "
   485 var_sed="$( for var_name in ${var_list}; do
   486                 eval echo 's,@@${var_name}@@,${'"${var_name}"'},g'
   487             done
   488           )"
   489 kconfig_sed="s/@@KCONFIG@@/$( for k_name in ${kconfig_list}; do
   490                                   eval printf \"${k_name}=\${${k_name}} \"
   491                               done
   492                             )/"
   493 "${sed}" -r -e "s,@@BINDIR@@,${BINDIR},g"       \
   494             -e "s,@@LIBDIR@@,${LIBDIR},g"       \
   495             -e "s,@@DOCDIR@@,${DOCDIR},g"       \
   496             -e "s,@@MANDIR@@,${MANDIR},g"       \
   497             -e "s,@@VERSION@@,${VERSION},g"     \
   498             -e "s,@@DATE@@,${DATE},g"           \
   499             -e "s,@@LOCAL@@,${LOCAL_set},g"     \
   500             -e "${var_sed}"                     \
   501             -e "${kconfig_sed}"                 \
   502          Makefile.in                            \
   503          >Makefile
   504 echo "done"
   505 
   506 cat <<__EOF__
   507 
   508 crosstool-NG configured as follows:
   509   PREFIX='${PREFIX}'
   510   BINDIR='${BINDIR}'
   511   LIBDIR='${LIBDIR}'
   512   DOCDIR='${DOCDIR}'
   513   MANDIR='${MANDIR}'
   514 
   515 Now run:
   516   make
   517 __EOF__
   518 if [ "${LOCAL_set}" != "y" ]; then
   519     printf "  make install\n"
   520 fi