scripts/build/libc/glibc-eglibc.sh-common
author Daniel Price <daniel.price@gmail.com>
Tue Nov 20 16:59:17 2012 -0800 (2012-11-20)
changeset 3126 333d3e40cbd1
parent 3102 75c2df0f7a12
child 3143 d06a9462cc20
permissions -rw-r--r--
scripts: refine static linking check to better guide the user

The current mechanism to check if static linking is possible, and the mesage
displayed on failure, can be puzzling to the unsuspecting user.

Also, the current implementation is not using the existing infrastructure,
and is thus difficult to enhance with new tests.

So, switch to using the standard CT_DoExecLog infra, and use four tests to
check for the host compiler:
- check we can run it
- check it can build a trivial program
- check it can statically link that program
- check if it statically link with libstdc++

That should cover most of the problems. Hopefully.

(At the same time, fix a typo in a comment)

Signed-off-by: Daniel Price <daniel.price@gmail.com>
[yann.morin.1998@free.fr: split original patch for self-contained changes]
[yann.morin.1998@free.fr: use steps to better see gcc's output]
[yann.morin.1998@free.fr: commit log]
Signed-off-by: "Yann E. MORIN" <yann.morin.1998@free.fr>
Message-Id: <163f86b5216fc08c672a.1353459722@nipigon.dssd.com>
Patchwork-Id: 200536
     1 # This file contains the functions common to glibc and eglibc
     2 
     3 # Extract the C library tarball(s)
     4 do_libc_extract() {
     5     local addon
     6 
     7     # Extract the main tarball
     8     CT_Extract "${CT_LIBC}-${CT_LIBC_VERSION}"
     9     CT_Pushd "${CT_SRC_DIR}/${CT_LIBC}-${CT_LIBC_VERSION}"
    10     CT_Patch nochdir "${CT_LIBC}" "${CT_LIBC_VERSION}"
    11 
    12     # Extract the add-opns
    13     for addon in $(do_libc_add_ons_list " "); do
    14         # If the addon was bundled with the main archive, we do not
    15         # need to extract it. Worse, if we were to try to extract
    16         # it, we'd get an error.
    17         if [ -d "${addon}" ]; then
    18             CT_DoLog DEBUG "Add-on already present, spkipping extraction"
    19             continue
    20         fi
    21 
    22         CT_Extract nochdir "${CT_LIBC}-${addon}-${CT_LIBC_VERSION}"
    23 
    24         CT_TestAndAbort "Error in add-on '${addon}': both short and long names in tarball" \
    25             -d "${addon}" -a -d "${CT_LIBC}-${addon}-${CT_LIBC_VERSION}"
    26 
    27         # Some addons have the 'long' name, while others have the
    28         # 'short' name, but patches are non-uniformly built with
    29         # either the 'long' or 'short' name, whatever the addons name
    30         # but we prefer the 'short' name and avoid duplicates.
    31         if [ -d "${CT_LIBC}-${addon}-${CT_LIBC_VERSION}" ]; then
    32             CT_DoExecLog FILE mv "${CT_LIBC}-${addon}-${CT_LIBC_VERSION}" "${addon}"
    33         fi
    34 
    35         CT_DoExecLog FILE ln -s "${addon}" "${CT_LIBC}-${addon}-${CT_LIBC_VERSION}"
    36 
    37         CT_Patch nochdir "${CT_LIBC}" "${addon}-${CT_LIBC_VERSION}"
    38 
    39         # Remove the long name since it can confuse configure scripts to run
    40         # the same source twice.
    41         rm "${CT_LIBC}-${addon}-${CT_LIBC_VERSION}"
    42     done
    43 
    44     # The configure files may be older than the configure.in files
    45     # if using a snapshot (or even some tarballs). Fake them being
    46     # up to date.
    47     find . -type f -name configure -exec touch {} \; 2>&1 |CT_DoLog ALL
    48 
    49     CT_Popd
    50 
    51     if [ "${CT_LIBC_LOCALES}" = "y" ]; then
    52         do_libc_locales_extract
    53     fi
    54 }
    55 
    56 # Build and install headers and start files
    57 do_libc_start_files() {
    58     # Start files and Headers should be configured the same way as the
    59     # final libc, but built and installed differently.
    60     do_libc_backend libc_mode=startfiles
    61 }
    62 
    63 # This function builds and install the full C library
    64 do_libc() {
    65     do_libc_backend libc_mode=final
    66 }
    67 
    68 # This backend builds the C library once for each multilib
    69 # variant the compiler gives us
    70 # Usage: do_libc_backend param=value [...]
    71 #   Parameter           : Definition                            : Type      : Default
    72 #   libc_mode           : 'startfiles' or 'final'               : string    : (none)
    73 do_libc_backend() {
    74     local libc_mode
    75     local -a multilibs
    76     local multilib
    77     local multi_dir
    78     local multi_flags
    79     local extra_dir
    80     local libc_headers libc_startfiles libc_full
    81     local hdr
    82     local arg
    83 
    84     for arg in "$@"; do
    85         eval "${arg// /\\ }"
    86     done
    87 
    88     case "${libc_mode}" in
    89         startfiles)
    90             CT_DoStep INFO "Installing C library headers & start files"
    91             hdr=y
    92             libc_startfiles=y
    93             libc_full=
    94             ;;
    95         final)
    96             CT_DoStep INFO "Installing C library"
    97             hdr=
    98             libc_startfiles=
    99             libc_full=y
   100             ;;
   101         *)  CT_Abort "Unsupported (or unset) libc_mode='${libc_mode}'";;
   102     esac
   103 
   104     # If gcc is not configured for multilib, it still prints
   105     # a single line for the default settings
   106     multilibs=( $("${CT_TARGET}-gcc" -print-multi-lib 2>/dev/null) )
   107     for multilib in "${multilibs[@]}"; do
   108         multi_dir="${multilib%%;*}"
   109         if [ "${multi_dir}" != "." ]; then
   110             CT_DoStep INFO "Building for multilib subdir='${multi_dir}'"
   111 
   112             extra_flags="$( echo "${multilib#*;}"       \
   113                             |${sed} -r -e 's/@/ -/g;'   \
   114                           )"
   115             extra_dir="/${multi_dir}"
   116 
   117             # glibc install its files in ${extra_dir}/{usr/,}lib
   118             # while gcc expects them in {,usr/}lib/${extra_dir}.
   119             # Prepare some symlinks so glibc installs in fact in
   120             # the proper place
   121             # We do it in the start-files step, so it is not needed
   122             # to do it in the final step, as the symlinks will
   123             # already exist
   124             if [ "${libc_mode}" = "startfiles" ]; then
   125                 CT_Pushd "${CT_SYSROOT_DIR}"
   126                 CT_DoExecLog ALL mkdir -p "lib/${multi_dir}"        \
   127                                           "usr/lib/${multi_dir}"    \
   128                                           "${multi_dir}"            \
   129                                           "${multi_dir}/usr"
   130                 CT_DoExecLog ALL ln -sf "../lib/${multi_dir}" "${multi_dir}/lib"
   131                 CT_DoExecLog ALL ln -sf "../../usr/lib/${multi_dir}" "${multi_dir}/usr/lib"
   132                 CT_Popd
   133             fi
   134             libc_headers=
   135         else
   136             extra_dir=
   137             extra_flags=
   138             libc_headers="${hdr}"
   139         fi
   140 
   141         CT_mkdir_pushd "${CT_BUILD_DIR}/build-libc-${libc_mode}${extra_dir//\//_}"
   142 
   143         do_libc_backend_once extra_dir="${extra_dir}"               \
   144                              extra_flags="${extra_flags}"           \
   145                              libc_headers="${libc_headers}"         \
   146                              libc_startfiles="${libc_startfiles}"   \
   147                              libc_full="${libc_full}"
   148 
   149         CT_Popd
   150 
   151         if [ "${multi_dir}" != "." ]; then
   152             if [ "${libc_mode}" = "final" ]; then
   153                 CT_DoLog EXTRA "Fixing up multilib location"
   154 
   155                 # rewrite the library multiplexers
   156                 for d in "lib/${multi_dir}" "usr/lib/${multi_dir}"; do
   157                     for l in libc libpthread libgcc_s; do
   158                         if [    -f "${CT_SYSROOT_DIR}/${d}/${l}.so"    \
   159                              -a ! -L ${CT_SYSROOT_DIR}/${d}/${l}.so    ]
   160                         then
   161                             CT_DoExecLog DEBUG ${sed} -r -i                                 \
   162                                                       -e "s:/lib/:/lib/${multi_dir}/:g;"    \
   163                                                       "${CT_SYSROOT_DIR}/${d}/${l}.so"
   164                         fi
   165                     done
   166                 done
   167                 # Remove the multi_dir now it is no longer useful
   168                 CT_DoExecLog DEBUG rm -rf "${CT_SYSROOT_DIR}/${multi_dir}"
   169             fi # libc_mode == final
   170 
   171             CT_EndStep
   172         fi
   173     done
   174 
   175     CT_EndStep
   176 }
   177 
   178 # This backend builds the C library once
   179 # Usage: do_libc_backend_once param=value [...]
   180 #   Parameter           : Definition                            : Type      : Default
   181 #   libc_headers        : Build libc headers                    : bool      : n
   182 #   libc_startfiles     : Build libc start-files                : bool      : n
   183 #   libc_full           : Build full libc                       : bool      : n
   184 #   extra_flags         : Extra CFLAGS to use (for multilib)    : string    : (empty)
   185 #   extra_dir           : Extra subdir for multilib             : string    : (empty)
   186 do_libc_backend_once() {
   187     local libc_headers
   188     local libc_startfiles
   189     local libc_full
   190     local extra_flags
   191     local extra_dir
   192     local src_dir="${CT_SRC_DIR}/${CT_LIBC}-${CT_LIBC_VERSION}"
   193     local extra_cc_args
   194     local -a extra_config
   195     local -a extra_make_args
   196     local glibc_cflags
   197     local float_extra
   198     local endian_extra
   199     local arg
   200 
   201     for arg in "$@"; do
   202         eval "${arg// /\\ }"
   203     done
   204 
   205     CT_DoLog EXTRA "Configuring C library"
   206 
   207     case "${CT_LIBC}" in
   208         eglibc)
   209             if [ "${CT_EGLIBC_CUSTOM_CONFIG}" = "y" ]; then
   210                 CT_DoExecLog ALL cp "${CT_CONFIG_DIR}/eglibc.config" option-groups.config
   211             fi
   212             if [ "${CT_EGLIBC_OPT_SIZE}" = "y" ]; then
   213                 OPTIMIZE=-Os
   214             else
   215                 OPTIMIZE=-O2
   216             fi
   217             if [ "${CT_LIBC_EGLIBC_2_16_or_later}" = "y" ]; then
   218                 # always include rpc, the user can still override it with TI-RPC
   219                 extra_config+=( --enable-obsolete-rpc )
   220             fi
   221             ;;
   222         glibc)
   223             # glibc can't be built without -O2 (reference needed!)
   224             OPTIMIZE=-O2
   225             # Also, if those two are missing, iconv build breaks
   226             extra_config+=( --disable-debug --disable-sanity-checks )
   227             ;;
   228     esac
   229 
   230     # Add some default glibc config options if not given by user.
   231     # We don't need to be conditional on wether the user did set different
   232     # values, as they CT_LIBC_GLIBC_EXTRA_CONFIG_ARRAY is passed after
   233     # extra_config
   234 
   235     extra_config+=("$(do_libc_min_kernel_config)")
   236 
   237     case "${CT_THREADS}" in
   238         nptl)           extra_config+=("--with-__thread" "--with-tls");;
   239         linuxthreads)   extra_config+=("--with-__thread" "--without-tls" "--without-nptl");;
   240         none)           extra_config+=("--without-__thread" "--without-nptl")
   241                         case "${CT_LIBC_GLIBC_EXTRA_CONFIG_ARRAY[*]}" in
   242                             *-tls*) ;;
   243                             *) extra_config+=("--without-tls");;
   244                         esac
   245                         ;;
   246     esac
   247 
   248     case "${CT_SHARED_LIBS}" in
   249         y) extra_config+=("--enable-shared");;
   250         *) extra_config+=("--disable-shared");;
   251     esac
   252 
   253     float_extra="$( echo "${extra_flags}"       \
   254                     |${sed} -r -e '/^(.*[[:space:]])?-m(hard|soft)-float([[:space:]].*)?$/!d;'  \
   255                                -e 's//\2/;'     \
   256                   )"
   257     case "${float_extra}" in
   258         hard)   extra_config+=("--with-fp");;
   259         soft)   extra_config+=("--without-fp");;
   260         "")
   261             case "${CT_ARCH_FLOAT}" in
   262                 hard|softfp)    extra_config+=("--with-fp");;
   263                 soft)           extra_config+=("--without-fp");;
   264             esac
   265             ;;
   266     esac
   267 
   268     if [ "${CT_LIBC_DISABLE_VERSIONING}" = "y" ]; then
   269         extra_config+=("--disable-versioning")
   270     fi
   271 
   272     if [ "${CT_LIBC_OLDEST_ABI}" != "" ]; then
   273         extra_config+=("--enable-oldest-abi=${CT_LIBC_OLDEST_ABI}")
   274     fi
   275 
   276     case "$(do_libc_add_ons_list ,)" in
   277         "") extra_config+=("--enable-add-ons=no");;
   278         *)  extra_config+=("--enable-add-ons=$(do_libc_add_ons_list ,)");;
   279     esac
   280 
   281     if [ "${CT_LIBC_EGLIBC_HAS_PKGVERSION_BUGURL}" = "y" ]; then
   282         extra_config+=("--with-pkgversion=${CT_PKGVERSION}")
   283         [ -n "${CT_TOOLCHAIN_BUGURL}" ] && extra_config+=("--with-bugurl=${CT_TOOLCHAIN_BUGURL}")
   284     fi
   285 
   286     # Extract the endianness options if any
   287     # This should cover all possible endianness options
   288     # in gcc, but it is prone to bit-rot... :-(
   289     endian_extra="$( echo "${extra_flags}"      \
   290                      |${sed} -r -e '/^(.*[[:space:]])?-(E[BL]|m((big|little)(-endian)?|e?[bl]))([[:space:]].*)?$/!d;' \
   291                                 -e 's//\2/;'    \
   292                    )"
   293     case "${endian_extra}" in
   294         EB|mbig-endian|mbig|meb|mb)
   295             extra_cc_args="${extra_cc_args} ${endian_extra}"
   296             ;;
   297         EL|mlittle-endian|mlittle|mel|ml)
   298             extra_cc_args="${extra_cc_args} ${endian_extra}"
   299             ;;
   300         "") extra_cc_args="${extra_cc_args} ${CT_ARCH_ENDIAN_OPT}"
   301             ;;
   302     esac
   303 
   304     touch config.cache
   305     if [ "${CT_LIBC_GLIBC_FORCE_UNWIND}" = "y" ]; then
   306         echo "libc_cv_forced_unwind=yes" >>config.cache
   307         echo "libc_cv_c_cleanup=yes" >>config.cache
   308     fi
   309 
   310     # Pre-seed the configparms file with values from the config option
   311     printf "${CT_LIBC_GLIBC_CONFIGPARMS}\n" > configparms
   312 
   313     cross_cc=$(CT_Which "${CT_TARGET}-gcc")
   314     extra_cc_args+=" ${extra_flags}"
   315 
   316     case "${CT_LIBC_ENABLE_FORTIFIED_BUILD}" in
   317         y)  ;;
   318         *)  glibc_cflags+=" -U_FORTIFY_SOURCE";;
   319     esac
   320     glibc_cflags+=" ${CT_TARGET_CFLAGS} ${OPTIMIZE} ${CT_LIBC_GLIBC_EXTRA_CFLAGS}"
   321 
   322     # ./configure is mislead by our tools override wrapper for bash
   323     # so just tell it where the real bash is _on_the_target_!
   324     # Notes:
   325     # - ${ac_cv_path_BASH_SHELL} is only used to set BASH_SHELL
   326     # - ${BASH_SHELL}            is only used to set BASH
   327     # - ${BASH}                  is only used to set the shebang
   328     #                            in two scripts to run on the target
   329     # So we can safely bypass bash detection at compile time.
   330     # Should this change in a future eglibc release, we'd better
   331     # directly mangle the generated scripts _after_ they get built,
   332     # or even after they get installed...
   333     echo "ac_cv_path_BASH_SHELL=/bin/bash" >>config.cache
   334 
   335     # Configure with --prefix the way we want it on the target...
   336     # There are a whole lot of settings here.  You'll probably want
   337     # to read up on what they all mean, and customize a bit, possibly by setting GLIBC_EXTRA_CONFIG_ARRAY
   338     # Compare these options with the ones used when installing the glibc headers above - they're different.
   339     # Adding "--without-gd" option to avoid error "memusagestat.c:36:16: gd.h: No such file or directory"
   340     # See also http://sources.redhat.com/ml/libc-alpha/2000-07/msg00024.html.
   341     # Set BUILD_CC, or we won't be able to build datafiles
   342     # Run explicitly through CONFIG_SHELL, or the build breaks badly (loop-of-death)
   343     # when the shell is not bash... Sigh... :-(
   344 
   345     CT_DoLog DEBUG "Using gcc for target    : '${cross_cc}'"
   346     CT_DoLog DEBUG "Configuring with addons : '$(do_libc_add_ons_list ,)'"
   347     CT_DoLog DEBUG "Extra config args passed: '${extra_config[*]}'"
   348     CT_DoLog DEBUG "Extra CC args passed    : '${glibc_cflags}'"
   349     CT_DoLog DEBUG "Extra flags (multilib)  : '${extra_flags}'"
   350 
   351     CT_DoExecLog CFG                                                \
   352     BUILD_CC="${CT_BUILD}-gcc"                                      \
   353     CFLAGS="${glibc_cflags}"                                        \
   354     CC="${CT_TARGET}-gcc ${CT_LIBC_EXTRA_CC_ARGS} ${extra_cc_args}" \
   355     AR=${CT_TARGET}-ar                                              \
   356     RANLIB=${CT_TARGET}-ranlib                                      \
   357     "${CONFIG_SHELL}"                                               \
   358     "${src_dir}/configure"                                          \
   359         --prefix=/usr                                               \
   360         --build=${CT_BUILD}                                         \
   361         --host=${CT_TARGET}                                         \
   362         --cache-file="$(pwd)/config.cache"                          \
   363         --without-cvs                                               \
   364         --disable-profile                                           \
   365         --without-gd                                                \
   366         --with-headers="${CT_HEADERS_DIR}"                          \
   367         "${extra_config[@]}"                                        \
   368         "${CT_LIBC_GLIBC_EXTRA_CONFIG_ARRAY[@]}"
   369 
   370     # build hacks
   371     case "${CT_ARCH},${CT_ARCH_CPU}" in
   372         powerpc,8??)
   373             # http://sourceware.org/ml/crossgcc/2008-10/msg00068.html
   374             CT_DoLog DEBUG "Activating support for memset on broken ppc-8xx (CPU15 erratum)"
   375             extra_make_args+=( ASFLAGS="-DBROKEN_PPC_8xx_CPU15" )
   376             ;;
   377     esac
   378 
   379     if [ "${libc_headers}" = "y" ]; then
   380         CT_DoLog EXTRA "Installing C library headers"
   381 
   382         # use the 'install-headers' makefile target to install the
   383         # headers
   384         CT_DoExecLog ALL make ${JOBSFLAGS}                          \
   385                          install_root=${CT_SYSROOT_DIR}${extra_dir} \
   386                          install-bootstrap-headers=yes              \
   387                          "${extra_make_args[@]}"                    \
   388                          install-headers
   389 
   390         # For glibc, a few headers need to be manually installed
   391         if [ "${CT_LIBC}" = "glibc" ]; then
   392             # Two headers -- stubs.h and features.h -- aren't installed by install-headers,
   393             # so do them by hand.  We can tolerate an empty stubs.h for the moment.
   394             # See e.g. http://gcc.gnu.org/ml/gcc/2002-01/msg00900.html
   395             mkdir -p "${CT_HEADERS_DIR}/gnu"
   396             CT_DoExecLog ALL touch "${CT_HEADERS_DIR}/gnu/stubs.h"
   397             CT_DoExecLog ALL cp -v "${CT_SRC_DIR}/glibc-${CT_LIBC_VERSION}/include/features.h"  \
   398                                    "${CT_HEADERS_DIR}/features.h"
   399 
   400             # Building the bootstrap gcc requires either setting inhibit_libc, or
   401             # having a copy of stdio_lim.h... see
   402             # http://sources.redhat.com/ml/libc-alpha/2003-11/msg00045.html
   403             CT_DoExecLog ALL cp -v bits/stdio_lim.h "${CT_HEADERS_DIR}/bits/stdio_lim.h"
   404 
   405             # Following error building gcc-4.0.0's gcj:
   406             #  error: bits/syscall.h: No such file or directory
   407             # solved by following copy; see http://sourceware.org/ml/crossgcc/2005-05/msg00168.html
   408             # but it breaks arm, see http://sourceware.org/ml/crossgcc/2006-01/msg00091.html
   409             case "${CT_ARCH}" in
   410                 arm)    ;;
   411                 *)  CT_DoExecLog ALL cp -v "misc/syscall-list.h"            \
   412                                            "${CT_HEADERS_DIR}/bits/syscall.h"
   413                     ;;
   414             esac
   415         fi
   416     fi # libc_headers == y
   417 
   418     if [ "${libc_startfiles}" = "y" ]; then
   419         if [ "${CT_THREADS}" = "nptl" ]; then
   420             CT_DoLog EXTRA "Installing C library start files"
   421 
   422             # there are a few object files needed to link shared libraries,
   423             # which we build and install by hand
   424             CT_DoExecLog ALL mkdir -p "${CT_SYSROOT_DIR}${extra_dir}/usr/lib"
   425             CT_DoExecLog ALL make ${JOBSFLAGS}  \
   426                         "${extra_make_args[@]}" \
   427                         csu/subdir_lib
   428             CT_DoExecLog ALL cp csu/crt1.o csu/crti.o csu/crtn.o    \
   429                                 "${CT_SYSROOT_DIR}${extra_dir}/usr/lib"
   430 
   431             # Finally, 'libgcc_s.so' requires a 'libc.so' to link against.
   432             # However, since we will never actually execute its code,
   433             # it doesn't matter what it contains.  So, treating '/dev/null'
   434             # as a C source file, we produce a dummy 'libc.so' in one step
   435             CT_DoExecLog ALL "${cross_cc}" -nostdlib        \
   436                                            -nostartfiles    \
   437                                            -shared          \
   438                                            -x c /dev/null   \
   439                                            -o "${CT_SYSROOT_DIR}${extra_dir}/usr/lib/libc.so"
   440         fi # threads == nptl
   441     fi # libc_headers == y
   442 
   443     if [ "${libc_full}" = "y" ]; then
   444         CT_DoLog EXTRA "Building C library"
   445         CT_DoExecLog ALL make ${JOBSFLAGS}              \
   446                               "${extra_make_args[@]}"   \
   447                               all
   448 
   449         CT_DoLog EXTRA "Installing C library"
   450         CT_DoExecLog ALL make ${JOBSFLAGS}                                  \
   451                               "${extra_make_args[@]}"                       \
   452                               install_root="${CT_SYSROOT_DIR}${extra_dir}"  \
   453                               install
   454 
   455         if [ "${CT_BUILD_MANUALS}" = "y" ]; then
   456             CT_DoLog EXTRA "Building and installing the C library manual"
   457             # Omit JOBSFLAGS as GLIBC has problems building the
   458             # manuals in parallel
   459             CT_DoExecLog ALL make pdf html
   460             # EGLIBC doesn't have a install-{pdf.html}, and older
   461             # versions leave the manuals in the source directory
   462             CT_DoExecLog ALL mkdir -p ${CT_PREFIX_DIR}/share/doc
   463             if [ "${CT_LIBC_EGLIBC_2_16_or_later}" = "y" ]; then
   464                 CT_DoExecLog ALL cp -av manual/*.pdf manual/libc \
   465                     ${CT_PREFIX_DIR}/share/doc
   466             else
   467                 CT_DoExecLog ALL cp -av ${src_dir}/manual/*.pdf ${src_dir}/manual/libc \
   468                     ${CT_PREFIX_DIR}/share/doc
   469             fi
   470         fi
   471 
   472         if [ "${CT_LIBC_LOCALES}" = "y" ]; then
   473             do_libc_locales
   474         fi
   475     fi # libc_full == y
   476 }
   477 
   478 # This function finishes the C library install
   479 # This is a no-op
   480 do_libc_finish() {
   481     :
   482 }
   483 
   484 # Build up the addons list, separated with $1
   485 do_libc_add_ons_list() {
   486     local sep="$1"
   487     local addons_list="$( echo "${CT_LIBC_ADDONS_LIST}"         \
   488                           |sed -r -e "s/[[:space:],]/${sep}/g;" \
   489                         )"
   490     case "${CT_THREADS}" in
   491         none)   ;;
   492         *)      addons_list="${addons_list}${sep}${CT_THREADS}";;
   493     esac
   494     [ "${CT_LIBC_GLIBC_USE_PORTS}" = "y" ] && addons_list="${addons_list}${sep}ports"
   495     # Remove duplicate, leading and trailing separators
   496     echo "${addons_list}" |sed -r -e "s/${sep}+/${sep}/g; s/^${sep}//; s/${sep}\$//;"
   497 }
   498 
   499 # Compute up the minimum supported Linux kernel version
   500 do_libc_min_kernel_config() {
   501     local min_kernel_config
   502 
   503     case "${CT_LIBC_GLIBC_EXTRA_CONFIG_ARRAY[*]}" in
   504         *--enable-kernel*) ;;
   505         *)  if [ "${CT_LIBC_GLIBC_KERNEL_VERSION_AS_HEADERS}" = "y" ]; then
   506                 # We can't rely on the kernel version from the configuration,
   507                 # because it might not be available if the user uses pre-installed
   508                 # headers. On the other hand, both method will have the kernel
   509                 # version installed in "usr/include/linux/version.h" in the sysroot.
   510                 # Parse that instead of having two code-paths.
   511                 version_code_file="${CT_SYSROOT_DIR}/usr/include/linux/version.h"
   512                 if [ ! -f "${version_code_file}" -o ! -r "${version_code_file}" ]; then
   513                     CT_Abort "Linux version is unavailable in installed headers files"
   514                 fi
   515                 version_code="$( grep -E LINUX_VERSION_CODE "${version_code_file}"  \
   516                                  |cut -d ' ' -f 3                                   \
   517                                )"
   518                 version=$(((version_code>>16)&0xFF))
   519                 patchlevel=$(((version_code>>8)&0xFF))
   520                 sublevel=$((version_code&0xFF))
   521                 min_kernel_config="${version}.${patchlevel}.${sublevel}"
   522             elif [ "${CT_LIBC_GLIBC_KERNEL_VERSION_CHOSEN}" = "y" ]; then
   523                 # Trim the fourth part of the linux version, keeping only the first three numbers
   524                 min_kernel_config="$( echo "${CT_LIBC_GLIBC_MIN_KERNEL_VERSION}"            \
   525                                       |sed -r -e 's/^([^.]+\.[^.]+\.[^.]+)(|\.[^.]+)$/\1/;' \
   526                                     )"
   527             fi
   528             echo "--enable-kernel=${min_kernel_config}"
   529             ;;
   530     esac
   531 }