configure
author "Yann E. MORIN" <yann.morin.1998@anciens.enib.fr>
Mon Dec 22 18:21:51 2008 +0000 (2008-12-22)
changeset 1105 3ba2a43353df
parent 1103 fab1755d2998
child 1106 2051ee3d1b75
permissions -rwxr-xr-x
Rationalise ./configure
- borrow a lot of ideas from Michael ABBOTT ( http://sourceware.org/ml/crossgcc/2008-12/msg00030.html )
- should be conforming to POSIX 1003.1-2008, non compliance due to bashsims is to be considered a bug
- as a result, it now works with dash
- make a little easier to read in some places
- enforce 4-space indentation
- get rid of futile 'return $?'
- quote all variables assignments
- save and restore IFS prior to and after using alternate values
- simplify the TOOLS_TO_CHECK listing

What's left:
- provide a mean to actually _compare_ version numbers
- change the TOOLS_TO_CHECK pattern style to be able to use '|' in regexp

/trunk/configure | 243 127 116 0 ++++++++++++++++++++++++++++++++------------------------------
1 file changed, 127 insertions(+), 116 deletions(-)
     1 #!/bin/sh
     2 
     3 VERSION=$( cat .version )
     4 DATE=$( date +%Y%m%d )
     5 
     6 # All absolutely required tools, one per line to ease diff.
     7 # See function 'has_or_abort, below, for syntax
     8 #  - Hopefully, if gcc is present, then all associated tools will be
     9 #  - awk must be GNU awk
    10 #  - makeinfo for building docs, even if discarded later on
    11 #  - others obvious... :-/
    12 #
    13 # Format of a pattern to check for, one per line:
    14 #   pattern := tool_test  OR  pattern|tool_test
    15 #   tool_test := tool=regexp OR tool
    16 #   tool := basename of the tool  OR  absolute pathname to the tool
    17 #   regexp := valid grep(1) extended regular expression, $( tool --version)
    18 #             will be matched against this regexp.
    19 #
    20 # In case a pattern list is given (eg foo|bar|buz), then tests are performed
    21 # from left to right, stopping at the first matching test (like the shell
    22 # would parse 'foo || bar || buz' ).
    23 #
    24 # Examples:
    25 #    /bin/bash=^GNU bash, version 3\.
    26 #       will ensure that /bin/bash exists, and that $( /bin/bash --version )
    27 #       matches the regexp '^GNU bash, version 3\.'
    28 #    autoconf=(GNU Autoconf)|autoconf2.50
    29 #       will ensure that:
    30 #         - 'autoconf' is to be found in the PATH, and that $( autoconf --version )
    31 #           matches the regexp '(GNU Autoconf)' (which btw is the signature of
    32 #           autoconf >= 2.50),
    33 #       OR that:
    34 #         - 'autoconf2.50' is to be found in the PATH
    35 #
    36 TOOLS_TO_CHECK='
    37 /bin/bash=^GNU bash, version 3\.
    38 make=^GNU Make
    39 gcc
    40 gawk=^GNU Awk
    41 sed
    42 bison
    43 flex
    44 makeinfo
    45 automake=\(GNU automake\) [[:digit:]]+\.[[:digit:]]{2,}|automake=\(GNU automake\) [2-9][[:digit:]]*\.
    46 libtool
    47 curl|wget
    48 patch
    49 tar
    50 gzip
    51 bzip2
    52 '
    53 
    54 PREFIX_DEFAULT=/usr/local
    55 
    56 BINDIR_set=
    57 LIBDIR_set=
    58 DOCDIR_set=
    59 MANDIR_set=
    60 LOCAL_set=
    61 
    62 FORCE=0
    63 
    64 do_quit=
    65 CONTRIB_list=
    66 
    67 # Simply print the error message, and exit. Obvious, he?
    68 do_error() {
    69     echo "${@}"
    70     exit 1
    71 }
    72 
    73 # A small function to test for existence of various tools
    74 # Usage: has_or_abort test_pattern (see top of file, TOOLS_TO_CHECK, for
    75 #                                   complete pattern format)
    76 has_or_abort() {
    77     save_IFS="${IFS}"
    78     IFS="|"
    79     for item in ${1}; do
    80         case "${item}" in
    81             *=*)
    82                 tool="${item%%=*}"
    83                 regexp="${item#*=}"
    84                 ;;
    85             *)  tool="${item}"
    86                 regexp=
    87                 ;;
    88         esac
    89         printf "Checking for '${tool}'... "
    90         where=$( which "${tool}" 2>/dev/null )
    91         if [ -z "${where}" ]; then
    92             echo "not found"
    93             where=
    94             continue
    95         else
    96             if [ -n "${regexp}" ]; then
    97                 tool_version=$( ${tool} --version 2>&1 )
    98                 str=$( echo "${tool_version}" |grep -E "${regexp}" |head -n 1 )
    99                 if [ -z "${str}" ]; then
   100                     echo "${where}: wrong version string: expecting regexp '${regexp}'"
   101                     where=""
   102                     continue
   103                 fi
   104             fi
   105             echo "${where}"
   106             break
   107         fi
   108     done;
   109     IFS="${save_IFS}"
   110     [ -z "${where}" -a ${FORCE} -eq 0 ] && do_error "Bailing out..."
   111     return 0
   112 }
   113 
   114 # Given an option string and the following argument,
   115 # echoes the value of the option.
   116 # If --var=val => echoes val and returns 0, meaning second arg was not consumed
   117 # If --var val => echoes val and returns non null, meaning second arg was used
   118 get_optval(){
   119     case "$1" in
   120         --*=?*)
   121             echo "${1}" |cut -d '=' -f 2-
   122             return 0
   123             ;;
   124         *)
   125             echo "${2}"
   126             return 1
   127             ;;
   128     esac
   129 }
   130 
   131 # The set_xxx functions will set the corresponding configuration variable
   132 # They return 0 if second arg was not consumed, and non-zero if it was consumed.
   133 set_prefix() {
   134     PREFIX="$( get_optval "$1" "$2" )"
   135 }
   136 set_bindir() {
   137     BINDIR_set=1
   138     BINDIR="$( get_optval "$1" "$2" )"
   139 }
   140 set_libdir() {
   141     LIBDIR_set=1
   142     LIBDIR="$( get_optval "$1" "$2" )"
   143 }
   144 set_docdir() {
   145     DOCDIR_set=1
   146     DOCDIR="$( get_optval "$1" "$2" )"
   147 }
   148 set_mandir() {
   149     MANDIR_set=1
   150     MANDIR="$( get_optval "$1" "$2" )"
   151 }
   152 
   153 # The set_contrib function is different in that it will work like the others,
   154 # except in two cases:
   155 # If all => replaces all with the list of all available contribs
   156 # If list => just echoes the list of all available contribs, and instructs
   157 # caller to quit immediately by setting do_quit to non null.
   158 # (can't use the return code, see above).
   159 set_contrib() {
   160     opt_val="$( get_optval "$1" "$2" )"
   161     ret=$?
   162     case "${opt_val}" in
   163         all)
   164             CONTRIB_list="$( LC_ALL=C ls -1 contrib/*.patch.lzma            \
   165                                       |xargs -I {} basename {} .patch.lzma  \
   166                                       |sed -r -e ':a; /$/N; s/\n/,/; ta;'   \
   167                            )"
   168             ;;
   169         list)
   170             do_quit=1
   171             echo "Available contributions:"
   172             LC_ALL=C ls -1 contrib/*.patch.lzma             \
   173                      |xargs -I {} basename {} .patch.lzma   \
   174                      |sed -r -e 's/^/  /;'
   175             ;;
   176         *)  CONTRIB_list="${CONTRIB_list},${opt_val}";;
   177     esac
   178     return $ret
   179 }
   180 
   181 do_help() {
   182     cat <<__EOF__
   183 \`configure' configures crosstool-NG ${VERSION} to adapt to many kind of systems.
   184 
   185 USAGE: ./configure [OPTION]...
   186 
   187 Defaults for the options are specified in brackets.
   188 
   189 Configuration:
   190   -h, --help              display this help and exit
   191       --force             force ./configure to complete, even if one or more
   192                           tools were not found. Use at your own risk, only if
   193                           you know what you are doing!
   194 
   195 Installation directories:
   196   --prefix=PREFIX         install files in PREFIX [${PREFIX_DEFAULT}]
   197   --local                 don't install, and use current directory
   198 
   199 By default, \`make install' will install all the files in
   200 \`${PREFIX_DEFAULT}/bin', \`${PREFIX_DEFAULT}/lib' etc.  You can specify
   201 an installation prefix other than \`${PREFIX_DEFAULT}' using \`--prefix',
   202 for instance \`--prefix=\${HOME}'.
   203 
   204 For better control, use the options below.
   205 
   206 Fine tuning of the installation directories:
   207   --bindir=DIR            user executables [PREFIX/bin]
   208   --libdir=DIR            object code libraries [PREFIX/lib]
   209   --docdir=DIR            info documentation [PREFIX/share/doc]
   210   --mandir=DIR            man documentation [PREFIX/share/man]
   211 
   212 Optional Features:
   213   --with-contrib=XXX      Include externally contributed features found in the
   214                           contrib/ sub-directory. Set to a comma-separated list
   215                           of features. Use 'all' to use all contributions, and
   216                           'list' to see which are available.
   217 __EOF__
   218 }
   219 
   220 #---------------------------------------------------------------------
   221 # Set user's options
   222 
   223 while [ $# -ne 0 ]; do
   224     case "$1" in
   225         --prefix*)  set_prefix "$1" "$2" && shift || shift 2;;
   226         --bindir*)  set_bindir "$1" "$2" && shift || shift 2;;
   227         --libdir*)  set_libdir "$1" "$2" && shift || shift 2;;
   228         --docdir*)  set_docdir "$1" "$2" && shift || shift 2;;
   229         --mandir*)  set_mandir "$1" "$2" && shift || shift 2;;
   230         --local)    LOCAL_set=1; shift;;
   231         --force)    FORCE=1; shift;;
   232         --with-contrib*)
   233                     set_contrib "$1" "$2" && shift || shift 2
   234                     [ "${do_quit}" = "1" ] && exit 0
   235                     ;;
   236         --help|-h)  do_help; exit 0;;
   237         *)          do_help; exit 1;;
   238     esac
   239 done
   240 
   241 # Use defaults
   242 [ -z "${PREFIX}" ] && set_prefix "" "${PREFIX_DEFAULT}"
   243 
   244 # Special case when installing locally
   245 if [ "${LOCAL_set}" = "1" ]; then
   246     set_prefix "" "$( pwd )"
   247     set_bindir "" "$( pwd )"
   248     set_libdir "" "$( pwd )"
   249     set_docdir "" "$( pwd )/docs"
   250     set_mandir "" "$( pwd )/docs"
   251 fi
   252 
   253 #---------------------------------------------------------------------
   254 # Some sanity checks, now
   255 
   256 # If this version is a svn snapshot, try to get the revision number
   257 # If we can't get the revision number, use date
   258 printf "Computing version string... "
   259 case "${VERSION}" in
   260     *+svn|svn)
   261         REVISION="$( LC_ALL=C svnversion )"
   262         case "${REVISION}" in
   263             exported)
   264                 VERSION="${VERSION}_unknown@$( date +%Y%m%d.%H%M%S )";;
   265             *)
   266                 URL="$( LC_ALL=C svn info 2>/dev/null   \
   267                                  |egrep 'URL: '         \
   268                                  |cut -d ' ' -f 2-      \
   269                       )"
   270                 ROOT="$( LC_ALL=C svn info 2>/dev/null  \
   271                          |egrep 'Repository Root: '     \
   272                          |cut -d ' ' -f 3-              \
   273                        )"
   274                 VERSION="${VERSION}${URL#${ROOT}}@${REVISION}"
   275                 ;;
   276         esac
   277         # Arrange to have no / in the directory name, no need to create an
   278         # arbitrarily deep directory structure
   279         VERSION="$( echo "${VERSION}" |sed -r -e 's|/+|_|g;' )"
   280         ;;
   281 esac
   282 echo "${VERSION}"
   283 
   284 # Now we have the version string, we can build up the paths
   285 [ -z "${BINDIR_set}" ] && BINDIR="${PREFIX}/bin"
   286 [ -z "${LIBDIR_set}" ] && LIBDIR="${PREFIX}/lib/ct-ng-${VERSION}"
   287 [ -z "${DOCDIR_set}" ] && DOCDIR="${PREFIX}/share/doc/ct-ng-${VERSION}"
   288 [ -z "${MANDIR_set}" ] && MANDIR="${PREFIX}/share/man/man1"
   289 
   290 # Check that install PATHs are absolute
   291 for p in BIN LIB DOC MAN; do
   292     var="${p}DIR"
   293     eval v='"${'"${var}"'}"'
   294     case "${v}" in
   295         /*) ;;
   296         *)  do_error "'${var}' is not an absolute path: '${v}'"
   297     esac
   298 done
   299 
   300 # Check the existence of absolutely required tools
   301 save_IFS="${IFS}"
   302 IFS='
   303 '
   304 for tool in ${TOOLS_TO_CHECK}; do
   305     has_or_abort "${tool}"
   306 done
   307 IFS="${save_IFS}"
   308 
   309 # It's safer to change all ',' to spaces rather than setting IFS
   310 CONTRIB_list="$( echo "${CONTRIB_list}"                             \
   311                  |sed -r -e 's/,+/ /g; s/ +/ /g; s/^ //g; s/ $//g;' \
   312                )"
   313 if [ -n "${CONTRIB_list}" ]; then
   314     has_or_abort 'lzcat'
   315     printf "Applying contributed code: "
   316     for c in ${CONTRIB_list}; do
   317         printf "${c}, "
   318         if [ ! -f "contrib/${c}.patch.lzma" ]; then
   319             do_error "Contribution '${c}' does not exist"
   320         fi
   321         lzcat "contrib/${c}.patch.lzma" |patch -p1 >/dev/null 2>&1
   322     done
   323     echo "done"
   324 fi
   325 
   326 printf "Building up Makefile... "
   327 sed -r -e "s,@@BINDIR@@,${BINDIR},g
   328            s,@@LIBDIR@@,${LIBDIR},g
   329            s,@@DOCDIR@@,${DOCDIR},g
   330            s,@@MANDIR@@,${MANDIR},g
   331            s,@@VERSION@@,${VERSION},g
   332            s,@@DATE@@,${DATE},g
   333            s,@@LOCAL@@,${LOCAL_set},g"  Makefile.in >Makefile
   334 echo "done"
   335 
   336 cat <<__EOF__
   337 
   338 crosstool-NG configured as follows:
   339   PREFIX='${PREFIX}'
   340   BINDIR='${BINDIR}'
   341   LIBDIR='${LIBDIR}'
   342   DOCDIR='${DOCDIR}'
   343   MANDIR='${MANDIR}'
   344   CONTRIB='${CONTRIB_list}'
   345 __EOF__