| # This file contains the functions common to glibc and eglibc |
| |
| # Extract the C library tarball(s) |
| do_libc_extract() { |
| local addon |
| |
| # Extract the main tarball |
| CT_Extract "${CT_LIBC}-${CT_LIBC_VERSION}" |
| CT_Pushd "${CT_SRC_DIR}/${CT_LIBC}-${CT_LIBC_VERSION}" |
| CT_Patch nochdir "${CT_LIBC}" "${CT_LIBC_VERSION}" |
| |
| # Extract the add-opns |
| for addon in $(do_libc_add_ons_list " "); do |
| # If the addon was bundled with the main archive, we do not |
| # need to extract it. Worse, if we were to try to extract |
| # it, we'd get an error. |
| if [ -d "${addon}" ]; then |
| CT_DoLog DEBUG "Add-on already present, spkipping extraction" |
| continue |
| fi |
| |
| CT_Extract nochdir "${CT_LIBC}-${addon}-${CT_LIBC_VERSION}" |
| |
| CT_TestAndAbort "Error in add-on '${addon}': both short and long names in tarball" \ |
| -d "${addon}" -a -d "${CT_LIBC}-${addon}-${CT_LIBC_VERSION}" |
| |
| # Some addons have the 'long' name, while others have the |
| # 'short' name, but patches are non-uniformly built with |
| # either the 'long' or 'short' name, whatever the addons name |
| # but we prefer the 'short' name and avoid duplicates. |
| if [ -d "${CT_LIBC}-${addon}-${CT_LIBC_VERSION}" ]; then |
| CT_DoExecLog FILE mv "${CT_LIBC}-${addon}-${CT_LIBC_VERSION}" "${addon}" |
| fi |
| |
| CT_DoExecLog FILE ln -s "${addon}" "${CT_LIBC}-${addon}-${CT_LIBC_VERSION}" |
| |
| CT_Patch nochdir "${CT_LIBC}" "${addon}-${CT_LIBC_VERSION}" |
| |
| # Remove the long name since it can confuse configure scripts to run |
| # the same source twice. |
| rm "${CT_LIBC}-${addon}-${CT_LIBC_VERSION}" |
| done |
| |
| # The configure files may be older than the configure.in files |
| # if using a snapshot (or even some tarballs). Fake them being |
| # up to date. |
| find . -type f -name configure -exec touch {} \; 2>&1 |CT_DoLog ALL |
| |
| CT_Popd |
| |
| if [ "${CT_LIBC_LOCALES}" = "y" ]; then |
| do_libc_locales_extract |
| fi |
| } |
| |
| # Build and install headers and start files |
| do_libc_start_files() { |
| # Start files and Headers should be configured the same way as the |
| # final libc, but built and installed differently. |
| do_libc_backend libc_mode=startfiles |
| } |
| |
| # This function builds and install the full C library |
| do_libc() { |
| do_libc_backend libc_mode=final |
| } |
| |
| do_libc_backend() { |
| local src_dir="${CT_SRC_DIR}/${CT_LIBC}-${CT_LIBC_VERSION}" |
| local libc_mode=final |
| local extra_cc_args |
| local -a extra_config |
| local -a extra_make_args |
| local glibc_cflags |
| |
| while [ $# -ne 0 ]; do |
| eval "${1// /\\ }" |
| shift |
| done |
| |
| if [ "${libc_mode}" = "startfiles" ]; then |
| CT_DoStep INFO "Installing C library headers & start files" |
| mkdir -p "${CT_BUILD_DIR}/build-libc-start-files" |
| cd "${CT_BUILD_DIR}/build-libc-start-files" |
| else # libc_mode = final |
| CT_DoStep INFO "Installing C library" |
| mkdir -p "${CT_BUILD_DIR}/build-libc" |
| cd "${CT_BUILD_DIR}/build-libc" |
| fi |
| |
| CT_DoLog EXTRA "Configuring C library" |
| |
| case "${CT_LIBC}" in |
| eglibc) |
| if [ "${CT_EGLIBC_CUSTOM_CONFIG}" = "y" ]; then |
| CT_DoExecLog ALL cp "${CT_CONFIG_DIR}/eglibc.config" option-groups.config |
| fi |
| if [ "${CT_EGLIBC_OPT_SIZE}" = "y" ]; then |
| OPTIMIZE=-Os |
| else |
| OPTIMIZE=-O2 |
| fi |
| ;; |
| glibc) |
| # glibc can't be built without -O2 (reference needed!) |
| OPTIMIZE=-O2 |
| # Also, if those two are missing, iconv build breaks |
| extra_config+=( --disable-debug --disable-sanity-checks ) |
| ;; |
| esac |
| |
| # Add some default glibc config options if not given by user. |
| # We don't need to be conditional on wether the user did set different |
| # values, as they CT_LIBC_GLIBC_EXTRA_CONFIG_ARRAY is passed after |
| # extra_config |
| |
| extra_config+=("$(do_libc_min_kernel_config)") |
| |
| case "${CT_THREADS}" in |
| nptl) extra_config+=("--with-__thread" "--with-tls");; |
| linuxthreads) extra_config+=("--with-__thread" "--without-tls" "--without-nptl");; |
| none) extra_config+=("--without-__thread" "--without-nptl") |
| case "${CT_LIBC_GLIBC_EXTRA_CONFIG_ARRAY[*]}" in |
| *-tls*) ;; |
| *) extra_config+=("--without-tls");; |
| esac |
| ;; |
| esac |
| |
| case "${CT_SHARED_LIBS}" in |
| y) extra_config+=("--enable-shared");; |
| *) extra_config+=("--disable-shared");; |
| esac |
| |
| case "${CT_ARCH_FLOAT_HW},${CT_ARCH_FLOAT_SW}" in |
| y,) extra_config+=("--with-fp");; |
| ,y) extra_config+=("--without-fp");; |
| esac |
| |
| if [ "${CT_LIBC_DISABLE_VERSIONING}" = "y" ]; then |
| extra_config+=("--disable-versioning") |
| fi |
| |
| if [ "${CT_LIBC_OLDEST_ABI}" != "" ]; then |
| extra_config+=("--enable-oldest-abi=${CT_LIBC_OLDEST_ABI}") |
| fi |
| |
| case "$(do_libc_add_ons_list ,)" in |
| "") extra_config+=("--enable-add-ons=no");; |
| *) extra_config+=("--enable-add-ons=$(do_libc_add_ons_list ,)");; |
| esac |
| |
| if [ "${CT_LIBC_EGLIBC_HAS_PKGVERSION_BUGURL}" = "y" ]; then |
| extra_config+=("--with-pkgversion=${CT_PKGVERSION}") |
| [ -n "${CT_TOOLCHAIN_BUGURL}" ] && extra_config+=("--with-bugurl=${CT_TOOLCHAIN_BUGURL}") |
| fi |
| |
| extra_cc_args="${extra_cc_args} ${CT_ARCH_ENDIAN_OPT}" |
| |
| touch config.cache |
| if [ "${CT_LIBC_GLIBC_FORCE_UNWIND}" = "y" ]; then |
| echo "libc_cv_forced_unwind=yes" >>config.cache |
| echo "libc_cv_c_cleanup=yes" >>config.cache |
| fi |
| |
| # Pre-seed the configparms file with values from the config option |
| printf "${CT_LIBC_GLIBC_CONFIGPARMS}\n" > configparms |
| |
| cross_cc=$(CT_Which "${CT_TARGET}-gcc") |
| |
| CT_DoLog DEBUG "Using gcc for target: '${cross_cc}'" |
| CT_DoLog DEBUG "Configuring with addons : '$(do_libc_add_ons_list ,)'" |
| CT_DoLog DEBUG "Extra config args passed: '${extra_config[*]}'" |
| CT_DoLog DEBUG "Extra CC args passed : '${extra_cc_args}'" |
| |
| glibc_cflags="${CT_TARGET_CFLAGS} ${CT_LIBC_GLIBC_EXTRA_CFLAGS} ${OPTIMIZE}" |
| case "${CT_LIBC_ENABLE_FORTIFIED_BUILD}" in |
| y) ;; |
| *) glibc_cflags+=" -U_FORTIFY_SOURCE";; |
| esac |
| |
| # ./configure is mislead by our tools override wrapper for bash |
| # so just tell it where the real bash is _on_the_target_! |
| # Notes: |
| # - ${ac_cv_path_BASH_SHELL} is only used to set BASH_SHELL |
| # - ${BASH_SHELL} is only used to set BASH |
| # - ${BASH} is only used to set the shebang |
| # in two scripts to run on the target |
| # So we can safely bypass bash detection at compile time. |
| # Should this change in a future eglibc release, we'd better |
| # directly mangle the generated scripts _after_ they get built, |
| # or even after they get installed... eglibc is such a sucker... |
| echo "ac_cv_path_BASH_SHELL=/bin/bash" >>config.cache |
| |
| # Configure with --prefix the way we want it on the target... |
| # There are a whole lot of settings here. You'll probably want |
| # to read up on what they all mean, and customize a bit, possibly by setting GLIBC_EXTRA_CONFIG_ARRAY |
| # Compare these options with the ones used when installing the glibc headers above - they're different. |
| # Adding "--without-gd" option to avoid error "memusagestat.c:36:16: gd.h: No such file or directory" |
| # See also http://sources.redhat.com/ml/libc-alpha/2000-07/msg00024.html. |
| # Set BUILD_CC, or we won't be able to build datafiles |
| # Run explicitly through CONFIG_SHELL, or the build breaks badly (loop-of-death) |
| # when the shell is not bash... Sigh... :-( |
| |
| CT_DoExecLog CFG \ |
| BUILD_CC="${CT_BUILD}-gcc" \ |
| CFLAGS="${glibc_cflags}" \ |
| CC="${CT_TARGET}-gcc ${CT_LIBC_EXTRA_CC_ARGS} ${extra_cc_args}" \ |
| AR=${CT_TARGET}-ar \ |
| RANLIB=${CT_TARGET}-ranlib \ |
| "${CONFIG_SHELL}" \ |
| "${src_dir}/configure" \ |
| --prefix=/usr \ |
| --build=${CT_BUILD} \ |
| --host=${CT_TARGET} \ |
| --cache-file="$(pwd)/config.cache" \ |
| --without-cvs \ |
| --disable-profile \ |
| --without-gd \ |
| --with-headers="${CT_HEADERS_DIR}" \ |
| "${extra_config[@]}" \ |
| "${CT_LIBC_GLIBC_EXTRA_CONFIG_ARRAY[@]}" |
| |
| # build hacks |
| case "${CT_ARCH},${CT_ARCH_CPU}" in |
| powerpc,8??) |
| # http://sourceware.org/ml/crossgcc/2008-10/msg00068.html |
| CT_DoLog DEBUG "Activating support for memset on broken ppc-8xx (CPU15 erratum)" |
| extra_make_args+=( ASFLAGS="-DBROKEN_PPC_8xx_CPU15" ) |
| ;; |
| esac |
| |
| if [ "${libc_mode}" = "startfiles" ]; then |
| CT_DoLog EXTRA "Installing C library headers" |
| |
| # use the 'install-headers' makefile target to install the |
| # headers |
| CT_DoExecLog ALL make ${JOBSFLAGS} \ |
| install_root=${CT_SYSROOT_DIR} \ |
| install-bootstrap-headers=yes \ |
| "${extra_make_args[@]}" \ |
| install-headers |
| |
| # For glibc, a few headers need to be manually installed |
| if [ "${CT_LIBC}" = "glibc" ]; then |
| # Two headers -- stubs.h and features.h -- aren't installed by install-headers, |
| # so do them by hand. We can tolerate an empty stubs.h for the moment. |
| # See e.g. http://gcc.gnu.org/ml/gcc/2002-01/msg00900.html |
| mkdir -p "${CT_HEADERS_DIR}/gnu" |
| CT_DoExecLog ALL touch "${CT_HEADERS_DIR}/gnu/stubs.h" |
| CT_DoExecLog ALL cp -v "${CT_SRC_DIR}/glibc-${CT_LIBC_VERSION}/include/features.h" \ |
| "${CT_HEADERS_DIR}/features.h" |
| |
| # Building the bootstrap gcc requires either setting inhibit_libc, or |
| # having a copy of stdio_lim.h... see |
| # http://sources.redhat.com/ml/libc-alpha/2003-11/msg00045.html |
| CT_DoExecLog ALL cp -v bits/stdio_lim.h "${CT_HEADERS_DIR}/bits/stdio_lim.h" |
| |
| # Following error building gcc-4.0.0's gcj: |
| # error: bits/syscall.h: No such file or directory |
| # solved by following copy; see http://sourceware.org/ml/crossgcc/2005-05/msg00168.html |
| # but it breaks arm, see http://sourceware.org/ml/crossgcc/2006-01/msg00091.html |
| case "${CT_ARCH}" in |
| arm) ;; |
| *) CT_DoExecLog ALL cp -v "misc/syscall-list.h" \ |
| "${CT_HEADERS_DIR}/bits/syscall.h" |
| ;; |
| esac |
| fi |
| |
| if [ "${CT_THREADS}" = "nptl" ]; then |
| CT_DoLog EXTRA "Installing C library start files" |
| |
| # there are a few object files needed to link shared libraries, |
| # which we build and install by hand |
| CT_DoExecLog ALL mkdir -p "${CT_SYSROOT_DIR}/usr/lib" |
| CT_DoExecLog ALL make ${JOBSFLAGS} \ |
| "${extra_make_args[@]}" \ |
| csu/subdir_lib |
| CT_DoExecLog ALL cp csu/crt1.o csu/crti.o csu/crtn.o \ |
| "${CT_SYSROOT_DIR}/usr/lib" |
| |
| # Finally, 'libgcc_s.so' requires a 'libc.so' to link against. |
| # However, since we will never actually execute its code, |
| # it doesn't matter what it contains. So, treating '/dev/null' |
| # as a C source file, we produce a dummy 'libc.so' in one step |
| CT_DoExecLog ALL "${cross_cc}" -nostdlib \ |
| -nostartfiles \ |
| -shared \ |
| -x c /dev/null \ |
| -o "${CT_SYSROOT_DIR}/usr/lib/libc.so" |
| fi # threads == nptl |
| else # libc_mode = final |
| CT_DoLog EXTRA "Building C library" |
| CT_DoExecLog ALL make ${JOBSFLAGS} \ |
| "${extra_make_args[@]}" \ |
| all |
| |
| CT_DoLog EXTRA "Installing C library" |
| CT_DoExecLog ALL make ${JOBSFLAGS} \ |
| "${extra_make_args[@]}" \ |
| install_root="${CT_SYSROOT_DIR}" \ |
| install |
| |
| if [ "${CT_LIBC_LOCALES}" = "y" ]; then |
| do_libc_locales |
| fi |
| fi |
| |
| CT_EndStep |
| } |
| |
| # This function finishes the C library install |
| # This is a no-op |
| do_libc_finish() { |
| : |
| } |
| |
| # Build up the addons list, separated with $1 |
| do_libc_add_ons_list() { |
| local sep="$1" |
| local addons_list="$( echo "${CT_LIBC_ADDONS_LIST}" \ |
| |sed -r -e "s/[[:space:],]/${sep}/g;" \ |
| )" |
| case "${CT_THREADS}" in |
| none) ;; |
| *) addons_list="${addons_list}${sep}${CT_THREADS}";; |
| esac |
| [ "${CT_LIBC_GLIBC_USE_PORTS}" = "y" ] && addons_list="${addons_list}${sep}ports" |
| # Remove duplicate, leading and trailing separators |
| echo "${addons_list}" |sed -r -e "s/${sep}+/${sep}/g; s/^${sep}//; s/${sep}\$//;" |
| } |
| |
| # Compute up the minimum supported Linux kernel version |
| do_libc_min_kernel_config() { |
| local min_kernel_config |
| |
| case "${CT_LIBC_GLIBC_EXTRA_CONFIG_ARRAY[*]}" in |
| *--enable-kernel*) ;; |
| *) if [ "${CT_LIBC_GLIBC_KERNEL_VERSION_AS_HEADERS}" = "y" ]; then |
| # We can't rely on the kernel version from the configuration, |
| # because it might not be available if the user uses pre-installed |
| # headers. On the other hand, both method will have the kernel |
| # version installed in "usr/include/linux/version.h" in the sysroot. |
| # Parse that instead of having two code-paths. |
| version_code_file="${CT_SYSROOT_DIR}/usr/include/linux/version.h" |
| if [ ! -f "${version_code_file}" -o ! -r "${version_code_file}" ]; then |
| CT_Abort "Linux version is unavailable in installed headers files" |
| fi |
| version_code="$( grep -E LINUX_VERSION_CODE "${version_code_file}" \ |
| |cut -d ' ' -f 3 \ |
| )" |
| version=$(((version_code>>16)&0xFF)) |
| patchlevel=$(((version_code>>8)&0xFF)) |
| sublevel=$((version_code&0xFF)) |
| min_kernel_config="${version}.${patchlevel}.${sublevel}" |
| elif [ "${CT_LIBC_GLIBC_KERNEL_VERSION_CHOSEN}" = "y" ]; then |
| # Trim the fourth part of the linux version, keeping only the first three numbers |
| min_kernel_config="$( echo "${CT_LIBC_GLIBC_MIN_KERNEL_VERSION}" \ |
| |sed -r -e 's/^([^.]+\.[^.]+\.[^.]+)(|\.[^.]+)$/\1/;' \ |
| )" |
| fi |
| echo "--enable-kernel=${min_kernel_config}" |
| ;; |
| esac |
| } |