From 4c8b0d602539a053b2d3406fb7ed37abd7a8fbc9 Mon Sep 17 00:00:00 2001 From: Quoc Truong Date: Mon, 11 Nov 2024 11:02:14 -0800 Subject: [PATCH] Create a new ML Build container for ARM64. The new container will leverage the hermetic Python and hermetic cuda requirements to reduce its size by removing unneeded softwares. PiperOrigin-RevId: 695410924 --- .../containers/ml_build_arm64/Dockerfile | 65 + .../containers/ml_build_arm64/apt.conf | 15 + .../containers/ml_build_arm64/build.sh | 76 ++ .../builder.devtoolset/build_devtoolset.sh | 157 +++ .../builder.devtoolset/fixlinks_aarch64.sh | 28 + .../builder.devtoolset/gcc9-fixups.patch | 270 ++++ .../builder.devtoolset/rpm-patch.sh | 28 + .../builder.devtoolset/stringop_trunc.patch | 1204 +++++++++++++++++ .../ml_build_arm64/builder.packages.txt | 47 + .../containers/ml_build_arm64/devel.bashrc | 26 + .../containers/ml_build_arm64/ld.so.conf | 18 + .../ml_build_arm64/requirements.txt | 4 + .../ml_build_arm64/setup.packages.sh | 28 + .../containers/ml_build_arm64/setup.python.sh | 67 + .../ml_build_arm64/setup.sources.sh | 45 + 15 files changed, 2078 insertions(+) create mode 100644 ci/official/containers/ml_build_arm64/Dockerfile create mode 100644 ci/official/containers/ml_build_arm64/apt.conf create mode 100755 ci/official/containers/ml_build_arm64/build.sh create mode 100755 ci/official/containers/ml_build_arm64/builder.devtoolset/build_devtoolset.sh create mode 100755 ci/official/containers/ml_build_arm64/builder.devtoolset/fixlinks_aarch64.sh create mode 100644 ci/official/containers/ml_build_arm64/builder.devtoolset/gcc9-fixups.patch create mode 100755 ci/official/containers/ml_build_arm64/builder.devtoolset/rpm-patch.sh create mode 100644 ci/official/containers/ml_build_arm64/builder.devtoolset/stringop_trunc.patch create mode 100644 ci/official/containers/ml_build_arm64/builder.packages.txt create mode 100644 ci/official/containers/ml_build_arm64/devel.bashrc create mode 100644 ci/official/containers/ml_build_arm64/ld.so.conf create mode 100644 ci/official/containers/ml_build_arm64/requirements.txt create mode 100755 ci/official/containers/ml_build_arm64/setup.packages.sh create mode 100755 ci/official/containers/ml_build_arm64/setup.python.sh create mode 100755 ci/official/containers/ml_build_arm64/setup.sources.sh diff --git a/ci/official/containers/ml_build_arm64/Dockerfile b/ci/official/containers/ml_build_arm64/Dockerfile new file mode 100644 index 00000000000..dc943dc2728 --- /dev/null +++ b/ci/official/containers/ml_build_arm64/Dockerfile @@ -0,0 +1,65 @@ +################################################################################ +FROM ubuntu:20.04@sha256:8e5c4f0285ecbb4ead070431d29b576a530d3166df73ec44affc1cd27555141b as devel +################################################################################ + +# Install devtoolset build dependencies +RUN echo "Installing devtoolset build dependencies" +COPY setup.sources.sh /setup.sources.sh +COPY setup.packages.sh /setup.packages.sh +COPY builder.packages.txt /builder.packages.txt + +RUN /setup.sources.sh && /setup.packages.sh /builder.packages.txt + +RUN update-ca-certificates +# Install devtoolset-9 in /dt10 with glibc 2.17 and libstdc++ 4.8, for building +# manylinux2014-compatible packages. +COPY builder.devtoolset/fixlinks_aarch64.sh /fixlinks.sh +COPY builder.devtoolset/rpm-patch.sh /rpm-patch.sh +COPY builder.devtoolset/build_devtoolset.sh /build_devtoolset.sh +COPY builder.devtoolset/gcc9-fixups.patch /gcc9-fixups.patch +COPY builder.devtoolset/stringop_trunc.patch /stringop_trunc.patch + +RUN /build_devtoolset.sh devtoolset-10 /dt10 + +# Build later version of patchelf that is not so buggy +RUN wget https://github.com/NixOS/patchelf/releases/download/0.18.0/patchelf-0.18.0-aarch64.tar.gz && tar -zxvf patchelf-0.18.0-aarch64.tar.gz -C /usr && rm -rf patchelf-0.18.0-aarch64.tar.gz + +# Install various tools. +# - bats: bash unit testing framework +# NOTE: v1.6.0 seems to have a bug that made "git" in setup_file break +# - bazelisk: always use the correct bazel version +# - buildifier: clean bazel build depshttps://github.com/bazelbuild/buildtools/releases/download/v7.3.1/buildifier-linux-arm64 +# - buildozer: clean bazel build deps +RUN git clone --branch v1.11.0 https://github.com/bats-core/bats-core.git && bats-core/install.sh /usr/local && rm -rf bats-core +RUN wget https://github.com/bazelbuild/bazelisk/releases/download/v1.21.0/bazelisk-linux-arm64 -O /usr/local/bin/bazel && chmod +x /usr/local/bin/bazel +RUN wget https://github.com/bazelbuild/buildtools/releases/download/v7.3.1/buildifier-linux-arm64 -O /usr/local/bin/buildifier && chmod +x /usr/local/bin/buildifier +RUN wget https://github.com/bazelbuild/buildtools/releases/download/v7.3.1/buildozer-linux-arm64 -O /usr/local/bin/buildozer && chmod +x /usr/local/bin/buildozer + +RUN groupadd -g 1001 buildslave && useradd -m -u 1001 -g buildslave buildslave +RUN mkdir -p /tf/venv +RUN chown -R buildslave:buildslave /tf + +# All lines past this point are reset when $CACHEBUSTER is set. We need this +# for Python specifically because we install some nightly packages which are +# likely to change daily. +ARG CACHEBUSTER=0 +RUN echo $CACHEBUSTER + +# Setup build and environment +COPY devel.bashrc /root/.bashrc +COPY ld.so.conf /dt10/etc/ + +# Make sure clang is on the path +RUN ln -s /usr/lib/llvm-18/bin/clang /usr/bin/clang + +# Setup JAX Python environment. +COPY requirements.txt /requirements.txt +COPY setup.python.sh /setup.python.sh +RUN /setup.python.sh python3.9 requirements.txt +RUN /setup.python.sh python3.10 requirements.txt +RUN /setup.python.sh python3.11 requirements.txt +RUN /setup.python.sh python3.12 requirements.txt +RUN /setup.python.sh python3.13 requirements.txt + +# "python3" commands by default run under 3.10 +RUN update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.10 1 diff --git a/ci/official/containers/ml_build_arm64/apt.conf b/ci/official/containers/ml_build_arm64/apt.conf new file mode 100644 index 00000000000..ea7b56091e5 --- /dev/null +++ b/ci/official/containers/ml_build_arm64/apt.conf @@ -0,0 +1,15 @@ +/* Copyright 2023 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +APT::Default-Release "focal"; diff --git a/ci/official/containers/ml_build_arm64/build.sh b/ci/official/containers/ml_build_arm64/build.sh new file mode 100755 index 00000000000..0421d3c18c9 --- /dev/null +++ b/ci/official/containers/ml_build_arm64/build.sh @@ -0,0 +1,76 @@ +#!/bin/bash +# Copyright 2023 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== + +# Builds the following Docker images for Linux ARM64. See the accompanying +# Dockerfile for more details: +# - us-central1-docker.pkg.dev/tensorflow-sigs/build-arm64:jax-latest-multi-python +# - us-central1-docker.pkg.dev/tensorflow-sigs/build-arm64:tf-latest-multi-python + +set -exo pipefail + +function is_continuous_or_release() { + [[ "$KOKORO_JOB_TYPE" == "CONTINUOUS_INTEGRATION" ]] || [[ "$KOKORO_JOB_TYPE" == "RELEASE" ]] +} + +# Move into the directory of the script +cd "$(dirname "$0")" + +if is_continuous_or_release || [[ -z "$KOKORO_BUILD_ID" ]]; then + # A continuous job is the only one to publish to latest + TAG="latest-multi-python" +else + # If it is a change, grab a good tag for iterative builds + if [[ -z "${KOKORO_GITHUB_PULL_REQUEST_NUMBER}" ]]; then + TAG=$(head -n 1 "$KOKORO_PIPER_DIR/presubmit_request.txt" | cut -d" " -f2) + else + TAG="pr-${KOKORO_GITHUB_PULL_REQUEST_NUMBER}" + fi +fi + +AR_IMAGE_PATH="us-central1-docker.pkg.dev/tensorflow-sigs/tensorflow/ml-build-arm64" + +# Build for both JAX and TF usage. We do these in one place because they share +# almost all of the same cache layers +export DOCKER_BUILDKIT=1 +for target in jax tf; do + AR_IMAGE="$AR_IMAGE_PATH:$target-$TAG" + docker pull "$AR_IMAGE" || true + # Due to some flakiness of resources pulled in the build, allow the docker + # command to reattempt build a few times in the case of failure (b/302558736) + set +e + for i in $(seq 1 5) + do + docker build \ + --build-arg REQUIREMENTS_FILE=jax.requirements.txt \ + --target=$target \ + --cache-from "$AR_IMAGE" \ + -t "$AR_IMAGE" . && break + done + final=$? + if [ $final -ne 0 ]; then + exit $final + fi + set -e + + INFRA_PUBLIC_TAG=infrastructure-public-image-$(docker images "$AR_IMAGE" --quiet) + AR_IMAGE_INFRA_PUBLIC="$AR_IMAGE_PATH:$INFRA_PUBLIC_TAG" + docker image tag "$AR_IMAGE" "$AR_IMAGE_INFRA_PUBLIC" + + if [[ -n "$KOKORO_BUILD_ID" ]]; then + gcloud auth configure-docker us-central1-docker.pkg.dev + docker push "$AR_IMAGE_PATH" --all-tags + fi +done diff --git a/ci/official/containers/ml_build_arm64/builder.devtoolset/build_devtoolset.sh b/ci/official/containers/ml_build_arm64/builder.devtoolset/build_devtoolset.sh new file mode 100755 index 00000000000..d59923d405a --- /dev/null +++ b/ci/official/containers/ml_build_arm64/builder.devtoolset/build_devtoolset.sh @@ -0,0 +1,157 @@ +#!/bin/bash -eu +# Copyright 2016 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +# +# Builds a devtoolset cross-compiler targeting manylinux2014 (glibc 2.17 / libstdc++ 4.8). + +VERSION="$1" +TARGET="$2" + +case "${VERSION}" in +devtoolset-9) + LIBSTDCXX_VERSION="6.0.28" + LIBSTDCXX_ABI="new" + ;; +devtoolset-10) + LIBSTDCXX_VERSION="6.0.28" + LIBSTDCXX_ABI="new" + ;; +*) + echo "Usage: $0 {devtoolset-9|devtoolset-10} " + echo "Use 'devtoolset-9' to build a manylinux2014 compatible toolchain" + exit 1 + ;; +esac + +mkdir -p "${TARGET}" + +mkdir -p ${TARGET}/usr/include + +# Put the current kernel headers from ubuntu in place. +ln -s "/usr/include/linux" "${TARGET}/usr/include/linux" +ln -s "/usr/include/asm-generic" "${TARGET}/usr/include/asm-generic" +ln -s "/usr/include/aarch64-linux-gnu/asm" "${TARGET}/usr/include/asm" + +# Download glibc's shared and development libraries based on the value of the +# `VERSION` parameter. +# Note: 'Templatizing' this and the other conditional branches would require +# defining several variables (version, os, path) making it difficult to maintain +# and extend for future modifications. +mkdir -p glibc-src +mkdir -p glibc-build +cd glibc-src +wget --retry-connrefused --waitretry=1 --read-timeout=20 --timeout=15 --tries=5 "https://vault.centos.org/centos/7/os/Source/SPackages/glibc-2.17-317.el7.src.rpm" +rpm2cpio "glibc-2.17-317.el7.src.rpm" |cpio -idmv +tar -xvzf "glibc-2.17-c758a686.tar.gz" --strip 1 +tar -xvzf "glibc-2.17-c758a686-releng.tar.gz" --strip 1 +sed -i '/patch0060/d' glibc.spec +/rpm-patch.sh "glibc.spec" +rm -f "glibc-2.17-317.el7.src.rpm" "glibc-2.17-c758a686.tar.gz" "glibc-2.17-c758a686-releng.tar.gz" +patch -p1 < /gcc9-fixups.patch +patch -p1 < /stringop_trunc.patch +cd ../glibc-build +../glibc-src/configure --prefix=/usr --disable-werror --enable-obsolete-rpc --disable-profile +make -j$(nproc) +make install DESTDIR=${TARGET} +cd .. + +# Symlinks in the binary distribution are set up for installation in /usr, we +# need to fix up all the links to stay within /${TARGET}. +/fixlinks.sh "/${TARGET}" + +# Patch to allow non-glibc 2.12 compatible builds to work. +sed -i '54i#define TCP_USER_TIMEOUT 18' "/${TARGET}/usr/include/netinet/tcp.h" + +# Download specific version of libstdc++ shared library based on the value of +# the `VERSION` parameter + # Download binary libstdc++ 4.8 shared library release +wget --retry-connrefused --waitretry=1 --read-timeout=20 --timeout=15 --tries=5 "http://old-releases.ubuntu.com/ubuntu/pool/main/g/gcc-4.8/libstdc++6_4.8.1-10ubuntu8_arm64.deb" && \ + unar "libstdc++6_4.8.1-10ubuntu8_arm64.deb" && \ + tar -C "${TARGET}" -xvzf "libstdc++6_4.8.1-10ubuntu8_arm64/data.tar.gz" "./usr/lib/aarch64-linux-gnu/libstdc++.so.6.0.18" && \ + rm -rf "libstdc++6_4.8.1-10ubuntu8_arm64.deb" "libstdc++6_4.8.1-10ubuntu8_arm64" + +mkdir -p "${TARGET}-src" +cd "${TARGET}-src" + +# Build a devtoolset cross-compiler based on our glibc 2.12/glibc 2.17 sysroot setup. +case "${VERSION}" in +devtoolset-9) + wget --retry-connrefused --waitretry=1 --read-timeout=20 --timeout=15 --tries=5 "https://vault.centos.org/centos/7/sclo/Source/rh/devtoolset-9-gcc-9.3.1-2.2.el7.src.rpm" + rpm2cpio "devtoolset-9-gcc-9.3.1-2.2.el7.src.rpm" |cpio -idmv + tar -xvf "gcc-9.3.1-20200408.tar.xz" --strip 1 + ;; +devtoolset-10) + wget --retry-connrefused --waitretry=1 --read-timeout=20 --timeout=15 --tries=5 "https://vault.centos.org/centos/7/sclo/Source/rh/devtoolset-10-gcc-10.2.1-11.2.el7.src.rpm" + rpm2cpio "devtoolset-10-gcc-10.2.1-11.2.el7.src.rpm" |cpio -idmv + tar -xvf "gcc-10.2.1-20210130.tar.xz" --strip 1 + ;; +esac + +# Apply the devtoolset patches to gcc. +/rpm-patch.sh "gcc.spec" + +./contrib/download_prerequisites + +mkdir -p "${TARGET}-build" +cd "${TARGET}-build" + +"${TARGET}-src/configure" \ + --prefix="${TARGET}/usr" \ + --with-sysroot="/${TARGET}" \ + --disable-bootstrap \ + --disable-libmpx \ + --enable-libsanitizer \ + --disable-libunwind-exceptions \ + --disable-libunwind-exceptions \ + --disable-lto \ + --disable-multilib \ + --enable-__cxa_atexit \ + --enable-gnu-indirect-function \ + --enable-gnu-unique-object \ + --enable-initfini-array \ + --enable-languages="c,c++" \ + --enable-linker-build-id \ + --enable-plugin \ + --enable-shared \ + --enable-threads=posix \ + --with-default-libstdcxx-abi=${LIBSTDCXX_ABI} \ + --with-gcc-major-version-only \ + --with-linker-hash-style="gnu" \ + && \ + make -j$(nproc) && \ + make install + + +# Create the devtoolset libstdc++ linkerscript that links dynamically against +# the system libstdc++ 4.4 and provides all other symbols statically. +# Note that the installation path for libstdc++ here is ${TARGET}/usr/lib64/ +mv "${TARGET}/usr/lib64/libstdc++.so.${LIBSTDCXX_VERSION}" \ + "${TARGET}/usr/lib64/libstdc++.so.${LIBSTDCXX_VERSION}.backup" +echo -e "OUTPUT_FORMAT(elf64-littleaarch64)\nINPUT ( libstdc++.so.6.0.18 -lstdc++_nonshared44 )" \ + > "${TARGET}/usr/lib64/libstdc++.so.${LIBSTDCXX_VERSION}" +cp "./aarch64-unknown-linux-gnu/libstdc++-v3/src/.libs/libstdc++_nonshared44.a" \ + "${TARGET}/usr/lib64" + + +# Link in architecture specific includes from the system; note that we cannot +# link in the whole aarch64-linux-gnu folder, as otherwise we're overlaying +# system gcc paths that we do not want to find. +# TODO(klimek): Automate linking in all non-gcc / non-kernel include +# directories. +mkdir -p "${TARGET}/usr/include/aarch64-linux-gnu" +PYTHON_VERSIONS=("python3.9" "python3.10" "python3.11" "python3.12") +for v in "${PYTHON_VERSIONS[@]}"; do + ln -s "/usr/local/include/${v}" "${TARGET}/usr/include/aarch64-linux-gnu/${v}" +done diff --git a/ci/official/containers/ml_build_arm64/builder.devtoolset/fixlinks_aarch64.sh b/ci/official/containers/ml_build_arm64/builder.devtoolset/fixlinks_aarch64.sh new file mode 100755 index 00000000000..09a5f9854d4 --- /dev/null +++ b/ci/official/containers/ml_build_arm64/builder.devtoolset/fixlinks_aarch64.sh @@ -0,0 +1,28 @@ +#!/bin/bash +# Copyright 2016 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +# +# Re-direct all links in $1 that are relative to be canonical + +BASE="$1" +find "${BASE}" -type l | \ + while read l ; do + if [[ "$(readlink "$l")" == \.\./* ]]; then + CANONICAL="$(readlink "$l")"; + rm "$l"; + ln -s "${CANONICAL}" "$l" + fi + done + diff --git a/ci/official/containers/ml_build_arm64/builder.devtoolset/gcc9-fixups.patch b/ci/official/containers/ml_build_arm64/builder.devtoolset/gcc9-fixups.patch new file mode 100644 index 00000000000..7b9bbf358ad --- /dev/null +++ b/ci/official/containers/ml_build_arm64/builder.devtoolset/gcc9-fixups.patch @@ -0,0 +1,270 @@ +diff --git a/iconv/gconv.h b/iconv/gconv.h +index 3f9112e..8e60197 100644 +--- a/iconv/gconv.h ++++ b/iconv/gconv.h +@@ -174,7 +174,7 @@ typedef struct __gconv_info + { + size_t __nsteps; + struct __gconv_step *__steps; +- __extension__ struct __gconv_step_data __data __flexarr; ++ __extension__ struct __gconv_step_data __data[0]; + } *__gconv_t; + + #endif /* gconv.h */ +diff --git a/include/libc-symbols.h b/include/libc-symbols.h +index c555bf2..143b26d 100644 +--- a/include/libc-symbols.h ++++ b/include/libc-symbols.h +@@ -107,6 +107,11 @@ + # endif + #endif + ++#ifndef __attribute_copy__ ++/* Provide an empty definition when cdefs.h is not included. */ ++# define __attribute_copy__(arg) ++#endif ++ + #ifndef __ASSEMBLER__ + /* GCC understands weak symbols and aliases; use its interface where + possible, instead of embedded assembly language. */ +@@ -114,7 +119,8 @@ + /* Define ALIASNAME as a strong alias for NAME. */ + # define strong_alias(name, aliasname) _strong_alias(name, aliasname) + # define _strong_alias(name, aliasname) \ +- extern __typeof (name) aliasname __attribute__ ((alias (#name))); ++ extern __typeof (name) aliasname __attribute__ ((alias (#name))) \ ++ __attribute_copy__ (name); + + /* This comes between the return type and function name in + a function definition to make that definition weak. */ +@@ -125,14 +131,16 @@ + If weak aliases are not available, this defines a strong alias. */ + # define weak_alias(name, aliasname) _weak_alias (name, aliasname) + # define _weak_alias(name, aliasname) \ +- extern __typeof (name) aliasname __attribute__ ((weak, alias (#name))); ++ extern __typeof (name) aliasname __attribute__ ((weak, alias (#name))) \ ++ __attribute_copy__ (name); + + /* Same as WEAK_ALIAS, but mark symbol as hidden. */ + # define weak_hidden_alias(name, aliasname) \ + _weak_hidden_alias (name, aliasname) + # define _weak_hidden_alias(name, aliasname) \ + extern __typeof (name) aliasname \ +- __attribute__ ((weak, alias (#name), __visibility__ ("hidden"))); ++ __attribute__ ((weak, alias (#name), __visibility__ ("hidden"))) \ ++ __attribute_copy__ (name); + + /* Declare SYMBOL as weak undefined symbol (resolved to 0 if not defined). */ + # define weak_extern(symbol) _weak_extern (weak symbol) +@@ -528,7 +536,8 @@ for linking") + # define __hidden_ver1(local, internal, name) \ + extern __typeof (name) __EI_##name __asm__(__hidden_asmname (#internal)); \ + extern __typeof (name) __EI_##name \ +- __attribute__((alias (__hidden_asmname (#local)))) ++ __attribute__((alias (__hidden_asmname (#local)))) \ ++ __attribute_copy__ (name) + # define hidden_ver(local, name) __hidden_ver1(local, __GI_##name, name); + # define hidden_data_ver(local, name) hidden_ver(local, name) + # define hidden_def(name) __hidden_ver1(__GI_##name, name, name); +@@ -541,7 +550,8 @@ for linking") + # define __hidden_nolink1(local, internal, name, version) \ + __hidden_nolink2 (local, internal, name, version) + # define __hidden_nolink2(local, internal, name, version) \ +- extern __typeof (name) internal __attribute__ ((alias (#local))); \ ++ extern __typeof (name) internal __attribute__ ((alias (#local))) \ ++ __attribute_copy__ (name); \ + __hidden_nolink3 (local, internal, #name "@" #version) + # define __hidden_nolink3(local, internal, vername) \ + __asm__ (".symver " #internal ", " vername); +diff --git a/locale/weightwc.h b/locale/weightwc.h +index e966c03..22ab790 100644 +--- a/locale/weightwc.h ++++ b/locale/weightwc.h +@@ -79,19 +79,19 @@ findidx (const wint_t **cpp, size_t len) + if (cp[cnt] != usrc[cnt]) + break; + +- if (cnt < nhere - 1) ++ if (cnt < nhere - 1 || cnt == len) + { + cp += 2 * nhere; + continue; + } + +- if (cp[nhere - 1] > usrc[nhere -1]) ++ if (cp[nhere - 1] > usrc[nhere - 1]) + { + cp += 2 * nhere; + continue; + } + +- if (cp[2 * nhere - 1] < usrc[nhere -1]) ++ if (cp[2 * nhere - 1] < usrc[nhere - 1]) + { + cp += 2 * nhere; + continue; +diff --git a/locale/xlocale.h b/locale/xlocale.h +index 98c080b..843bd45 100644 +--- a/locale/xlocale.h ++++ b/locale/xlocale.h +@@ -20,6 +20,9 @@ + #ifndef _XLOCALE_H + #define _XLOCALE_H 1 + ++#ifndef _BITS_TYPES___LOCALE_T_H ++#define _BITS_TYPES___LOCALE_T_H 1 ++ + /* Structure for reentrant locale using functions. This is an + (almost) opaque type for the user level programs. The file and + this data structure is not standardized. Don't rely on it. It can +@@ -41,4 +44,6 @@ typedef struct __locale_struct + /* POSIX 2008 makes locale_t official. */ + typedef __locale_t locale_t; + ++#endif /* bits/types/__locale_t.h */ ++ + #endif /* xlocale.h */ +diff --git a/misc/sys/cdefs.h b/misc/sys/cdefs.h +index d1cb3dd..30482a1 100644 +--- a/misc/sys/cdefs.h ++++ b/misc/sys/cdefs.h +@@ -423,4 +423,14 @@ + # endif + #endif + ++/* Undefine (also defined in libc-symbols.h). */ ++#undef __attribute_copy__ ++#if __GNUC_PREREQ (9, 0) ++/* Copies attributes from the declaration or type referenced by ++ the argument. */ ++# define __attribute_copy__(arg) __attribute__ ((__copy__ (arg))) ++#else ++# define __attribute_copy__(arg) ++#endif ++ + #endif /* sys/cdefs.h */ +diff --git a/stdlib/setenv.c b/stdlib/setenv.c +index 45efe2e..06bfab0 100644 +--- a/stdlib/setenv.c ++++ b/stdlib/setenv.c +@@ -319,6 +319,7 @@ unsetenv (const char *name) + + ep = __environ; + if (ep != NULL) ++ { + while (*ep != NULL) + if (!strncmp (*ep, name, len) && (*ep)[len] == '=') + { +@@ -332,6 +333,7 @@ unsetenv (const char *name) + } + else + ++ep; ++ } + + UNLOCK; + +diff --git a/support/Makefile b/support/Makefile +index a253698..2f4e2a9 100644 +--- a/support/Makefile ++++ b/support/Makefile +@@ -167,13 +167,6 @@ CFLAGS-support_paths.c = \ + -DINSTDIR_PATH=\"$(prefix)\" \ + -DLIBDIR_PATH=\"$(libdir)\" + +-ifeq (,$(CXX)) +-LINKS_DSO_PROGRAM = links-dso-program-c +-else +-LINKS_DSO_PROGRAM = links-dso-program +-LDLIBS-links-dso-program = -lstdc++ -lgcc -lgcc_s $(libunwind) +-endif +- + LDLIBS-test-container = $(libsupport) + + others += test-container +@@ -182,9 +175,6 @@ others-noinstall += test-container + others += shell-container echo-container true-container + others-noinstall += shell-container echo-container true-container + +-others += $(LINKS_DSO_PROGRAM) +-others-noinstall += $(LINKS_DSO_PROGRAM) +- + $(objpfx)test-container : $(libsupport) + $(objpfx)shell-container : $(libsupport) + $(objpfx)echo-container : $(libsupport) +diff --git a/support/links-dso-program.cc b/support/links-dso-program.cc +index 8ff3155..f9d2b77 100644 +--- a/support/links-dso-program.cc ++++ b/support/links-dso-program.cc +@@ -3,6 +3,11 @@ + backported. */ + #define _ISOMAC 1 + ++#define __GLIBC_USE(F) __GLIBC_USE_ ## F ++ ++# define __attribute_alloc_size__(params) \ ++ __attribute__ ((__alloc_size__ params)) ++ + #include + + using namespace std; +diff --git a/sysdeps/aarch64/dl-machine.h b/sysdeps/aarch64/dl-machine.h +index 185402f..bbdeae0 100644 +--- a/sysdeps/aarch64/dl-machine.h ++++ b/sysdeps/aarch64/dl-machine.h +@@ -49,23 +49,11 @@ elf_machine_load_address (void) + /* To figure out the load address we use the definition that for any symbol: + dynamic_addr(symbol) = static_addr(symbol) + load_addr + +- The choice of symbol is arbitrary. The static address we obtain +- by constructing a non GOT reference to the symbol, the dynamic +- address of the symbol we compute using adrp/add to compute the +- symbol's address relative to the PC. */ +- +- ElfW(Addr) static_addr; +- ElfW(Addr) dynamic_addr; +- +- asm (" \n\ +- adrp %1, _dl_start; \n\ +- add %1, %1, #:lo12:_dl_start \n\ +- ldr %w0, 1f \n\ +- b 2f \n\ +-1: .word _dl_start \n\ +-2: \n\ +- " : "=r" (static_addr), "=r" (dynamic_addr)); +- return dynamic_addr - static_addr; ++ _DYNAMIC sysmbol is used here as its link-time address stored in ++ the special unrelocated first GOT entry. */ ++ ++ extern ElfW(Dyn) _DYNAMIC[] attribute_hidden; ++ return (ElfW(Addr)) &_DYNAMIC - elf_machine_dynamic (); + } + + /* Set up the loaded object described by L so its unrelocated PLT +diff --git a/sysdeps/ieee754/dbl-64/k_rem_pio2.c b/sysdeps/ieee754/dbl-64/k_rem_pio2.c +index fcf956a..e2c5d29 100644 +--- a/sysdeps/ieee754/dbl-64/k_rem_pio2.c ++++ b/sysdeps/ieee754/dbl-64/k_rem_pio2.c +@@ -172,7 +172,8 @@ int __kernel_rem_pio2(double *x, double *y, int e0, int nx, int prec, const int3 + + /* compute q[0],q[1],...q[jk] */ + for (i=0;i<=jk;i++) { +- for(j=0,fw=0.0;j<=jx;j++) fw += x[j]*f[jx+i-j]; q[i] = fw; ++ for(j=0,fw=0.0;j<=jx;j++) fw += x[j]*f[jx+i-j]; ++ q[i] = fw; + } + + jz = jk; +diff --git a/sysdeps/ieee754/flt-32/k_rem_pio2f.c b/sysdeps/ieee754/flt-32/k_rem_pio2f.c +index e54a067..215b0e0 100644 +--- a/sysdeps/ieee754/flt-32/k_rem_pio2f.c ++++ b/sysdeps/ieee754/flt-32/k_rem_pio2f.c +@@ -65,7 +65,8 @@ int __kernel_rem_pio2f(float *x, float *y, int e0, int nx, int prec, const int32 + + /* compute q[0],q[1],...q[jk] */ + for (i=0;i<=jk;i++) { +- for(j=0,fw=0.0;j<=jx;j++) fw += x[j]*f[jx+i-j]; q[i] = fw; ++ for(j=0,fw=0.0;j<=jx;j++) fw += x[j]*f[jx+i-j]; ++ q[i] = fw; + } + + jz = jk; diff --git a/ci/official/containers/ml_build_arm64/builder.devtoolset/rpm-patch.sh b/ci/official/containers/ml_build_arm64/builder.devtoolset/rpm-patch.sh new file mode 100755 index 00000000000..892ae2af86a --- /dev/null +++ b/ci/official/containers/ml_build_arm64/builder.devtoolset/rpm-patch.sh @@ -0,0 +1,28 @@ +#!/bin/bash -eu +# Copyright 2016 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +# +# Given an RPM spec file $1, apply its patches. + +SPEC="$1" +grep '%patch' "${SPEC}" |while read cmd ; do + N=$(echo "${cmd}" |sed 's,%patch\([0-9]\+\).*,\1,') + file=$(grep "Patch$N:" "${SPEC}" |sed 's,.*: ,,') + parg=$(echo "${cmd}" |sed 's,.*\(-p[0-9]\).*,\1,') + if [[ ! "${file}" =~ doxygen && "${cmd}" != \#* ]]; then + echo "patch ${parg} -s < ${file}" + patch ${parg} -s < "${file}" + fi +done diff --git a/ci/official/containers/ml_build_arm64/builder.devtoolset/stringop_trunc.patch b/ci/official/containers/ml_build_arm64/builder.devtoolset/stringop_trunc.patch new file mode 100644 index 00000000000..bd9e5533118 --- /dev/null +++ b/ci/official/containers/ml_build_arm64/builder.devtoolset/stringop_trunc.patch @@ -0,0 +1,1204 @@ +diff --git a/bits/utmp.h b/bits/utmp.h +index 775123d..bf28c6d 100644 +--- a/bits/utmp.h ++++ b/bits/utmp.h +@@ -1,5 +1,5 @@ +-/* The `struct utmp' type, describing entries in the utmp file. Generic/BSDish +- Copyright (C) 1993, 1996, 1997 Free Software Foundation, Inc. ++/* The `struct utmp' type, describing entries in the utmp file. ++ Copyright (C) 1993-2022 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or +@@ -14,7 +14,7 @@ + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see +- . */ ++ . */ + + #ifndef _UTMP_H + # error "Never include directly; use instead." +@@ -24,11 +24,13 @@ + #include + + +-#define UT_NAMESIZE 8 +-#define UT_LINESIZE 8 +-#define UT_HOSTSIZE 16 ++#define UT_LINESIZE 32 ++#define UT_NAMESIZE 32 ++#define UT_HOSTSIZE 256 + + ++/* The structure describing an entry in the database of ++ previous logins. */ + struct lastlog + { + time_t ll_time; +@@ -36,12 +38,16 @@ struct lastlog + char ll_host[UT_HOSTSIZE]; + }; + ++/* The structure describing an entry in the user accounting database. */ + struct utmp + { +- char ut_line[UT_LINESIZE]; +- char ut_user[UT_NAMESIZE]; ++ char ut_line[UT_LINESIZE] ++ __attribute_nonstring__; /* Devicename. */ ++ char ut_user[UT_NAMESIZE] ++ __attribute_nonstring__; /* Username. */ + #define ut_name ut_user +- char ut_host[UT_HOSTSIZE]; ++ char ut_host[UT_HOSTSIZE] ++ __attribute_nonstring__; /* Hostname for remote login. */ + long int ut_time; + }; + +diff --git a/misc/sys/cdefs.h b/misc/sys/cdefs.h +index 30482a1..551d5fd 100644 +--- a/misc/sys/cdefs.h ++++ b/misc/sys/cdefs.h +@@ -391,6 +391,15 @@ + + #include + ++#if __GNUC_PREREQ (8, 0) ++/* Describes a char array whose address can safely be passed as the first ++ argument to strncpy and strncat, as the char array is not necessarily ++ a NUL-terminated string. */ ++# define __attribute_nonstring__ __attribute__ ((__nonstring__)) ++#else ++# define __attribute_nonstring__ ++#endif ++ + #if defined __LONG_DOUBLE_MATH_OPTIONAL && defined __NO_LONG_DOUBLE_MATH + # define __LDBL_COMPAT 1 + # ifdef __REDIRECT +diff --git a/nis/nss_nisplus/nisplus-parser.c b/nis/nss_nisplus/nisplus-parser.c +index a4d76fb..41600f0 100644 +--- a/nis/nss_nisplus/nisplus-parser.c ++++ b/nis/nss_nisplus/nisplus-parser.c +@@ -82,7 +82,7 @@ _nss_nisplus_parse_pwent (nis_result *result, struct passwd *pw, + + char *numstr = NISOBJVAL (2, obj); + len = NISOBJLEN (2, obj); +- if (len == 0 && numstr[len - 1] != '\0') ++ if (len == 0 || numstr[len - 1] != '\0') + { + if (len >= room_left) + goto no_more_room; +@@ -98,7 +98,7 @@ _nss_nisplus_parse_pwent (nis_result *result, struct passwd *pw, + + numstr = NISOBJVAL (3, obj); + len = NISOBJLEN (3, obj); +- if (len == 0 && numstr[len - 1] != '\0') ++ if (len == 0 || numstr[len - 1] != '\0') + { + if (len >= room_left) + goto no_more_room; +diff --git a/string/bits/string2.h b/string/bits/string2.h +index c9bf593..f461fc1 100644 +--- a/string/bits/string2.h ++++ b/string/bits/string2.h +@@ -47,29 +47,7 @@ + #endif + + #if _STRING_ARCH_unaligned +-/* If we can do unaligned memory accesses we must know the endianess. */ +-# include + # include +- +-# if __BYTE_ORDER == __LITTLE_ENDIAN +-# define __STRING2_SMALL_GET16(src, idx) \ +- (((const unsigned char *) (const char *) (src))[idx + 1] << 8 \ +- | ((const unsigned char *) (const char *) (src))[idx]) +-# define __STRING2_SMALL_GET32(src, idx) \ +- (((((const unsigned char *) (const char *) (src))[idx + 3] << 8 \ +- | ((const unsigned char *) (const char *) (src))[idx + 2]) << 8 \ +- | ((const unsigned char *) (const char *) (src))[idx + 1]) << 8 \ +- | ((const unsigned char *) (const char *) (src))[idx]) +-# else +-# define __STRING2_SMALL_GET16(src, idx) \ +- (((const unsigned char *) (const char *) (src))[idx] << 8 \ +- | ((const unsigned char *) (const char *) (src))[idx + 1]) +-# define __STRING2_SMALL_GET32(src, idx) \ +- (((((const unsigned char *) (const char *) (src))[idx] << 8 \ +- | ((const unsigned char *) (const char *) (src))[idx + 1]) << 8 \ +- | ((const unsigned char *) (const char *) (src))[idx + 2]) << 8 \ +- | ((const unsigned char *) (const char *) (src))[idx + 3]) +-# endif + #else + /* These are a few types we need for the optimizations if we cannot + use unaligned memory accesses. */ +@@ -94,148 +72,11 @@ __STRING2_COPY_TYPE (8); + + /* Set N bytes of S to C. */ + #if !defined _HAVE_STRING_ARCH_memset +-# if !__GNUC_PREREQ (3, 0) +-# if _STRING_ARCH_unaligned +-# define memset(s, c, n) \ +- (__extension__ (__builtin_constant_p (n) && (n) <= 16 \ +- ? ((n) == 1 \ +- ? __memset_1 (s, c) \ +- : __memset_gc (s, c, n)) \ +- : (__builtin_constant_p (c) && (c) == '\0' \ +- ? ({ void *__s = (s); __bzero (__s, n); __s; }) \ +- : memset (s, c, n)))) +- +-# define __memset_1(s, c) ({ void *__s = (s); \ +- *((__uint8_t *) __s) = (__uint8_t) c; __s; }) +- +-# define __memset_gc(s, c, n) \ +- ({ void *__s = (s); \ +- union { \ +- unsigned int __ui; \ +- unsigned short int __usi; \ +- unsigned char __uc; \ +- } *__u = __s; \ +- __uint8_t __c = (__uint8_t) (c); \ +- \ +- /* This `switch' statement will be removed at compile-time. */ \ +- switch ((unsigned int) (n)) \ +- { \ +- case 15: \ +- __u->__ui = __c * 0x01010101; \ +- __u = __extension__ ((void *) __u + 4); \ +- case 11: \ +- __u->__ui = __c * 0x01010101; \ +- __u = __extension__ ((void *) __u + 4); \ +- case 7: \ +- __u->__ui = __c * 0x01010101; \ +- __u = __extension__ ((void *) __u + 4); \ +- case 3: \ +- __u->__usi = (unsigned short int) __c * 0x0101; \ +- __u = __extension__ ((void *) __u + 2); \ +- __u->__uc = (unsigned char) __c; \ +- break; \ +- \ +- case 14: \ +- __u->__ui = __c * 0x01010101; \ +- __u = __extension__ ((void *) __u + 4); \ +- case 10: \ +- __u->__ui = __c * 0x01010101; \ +- __u = __extension__ ((void *) __u + 4); \ +- case 6: \ +- __u->__ui = __c * 0x01010101; \ +- __u = __extension__ ((void *) __u + 4); \ +- case 2: \ +- __u->__usi = (unsigned short int) __c * 0x0101; \ +- break; \ +- \ +- case 13: \ +- __u->__ui = __c * 0x01010101; \ +- __u = __extension__ ((void *) __u + 4); \ +- case 9: \ +- __u->__ui = __c * 0x01010101; \ +- __u = __extension__ ((void *) __u + 4); \ +- case 5: \ +- __u->__ui = __c * 0x01010101; \ +- __u = __extension__ ((void *) __u + 4); \ +- case 1: \ +- __u->__uc = (unsigned char) __c; \ +- break; \ +- \ +- case 16: \ +- __u->__ui = __c * 0x01010101; \ +- __u = __extension__ ((void *) __u + 4); \ +- case 12: \ +- __u->__ui = __c * 0x01010101; \ +- __u = __extension__ ((void *) __u + 4); \ +- case 8: \ +- __u->__ui = __c * 0x01010101; \ +- __u = __extension__ ((void *) __u + 4); \ +- case 4: \ +- __u->__ui = __c * 0x01010101; \ +- case 0: \ +- break; \ +- } \ +- \ +- __s; }) +-# else +-# define memset(s, c, n) \ +- (__extension__ (__builtin_constant_p (c) && (c) == '\0' \ +- ? ({ void *__s = (s); __bzero (__s, n); __s; }) \ +- : memset (s, c, n))) +-# endif +-# endif +- +-/* GCC < 3.0 optimizes memset(s, 0, n) but not bzero(s, n). +- The optimization is broken before EGCS 1.1. +- GCC 3.0+ has __builtin_bzero as well, but at least till GCC 3.4 +- if it decides to call the library function, it calls memset +- and not bzero. */ +-# if __GNUC_PREREQ (2, 91) +-# define __bzero(s, n) __builtin_memset (s, '\0', n) +-# endif +- ++# define __bzero(s, n) __builtin_memset (s, '\0', n) + #endif + +- +-/* Copy N bytes from SRC to DEST, returning pointer to byte following the +- last copied. */ +-#ifdef __USE_GNU +-# if !defined _HAVE_STRING_ARCH_mempcpy || defined _FORCE_INLINES +-# ifndef _HAVE_STRING_ARCH_mempcpy +-# if __GNUC_PREREQ (3, 4) +-# define __mempcpy(dest, src, n) __builtin_mempcpy (dest, src, n) +-# elif __GNUC_PREREQ (3, 0) +-# define __mempcpy(dest, src, n) \ +- (__extension__ (__builtin_constant_p (src) && __builtin_constant_p (n) \ +- && __string2_1bptr_p (src) && n <= 8 \ +- ? __builtin_memcpy (dest, src, n) + (n) \ +- : __mempcpy (dest, src, n))) +-# else +-# define __mempcpy(dest, src, n) \ +- (__extension__ (__builtin_constant_p (src) && __builtin_constant_p (n) \ +- && __string2_1bptr_p (src) && n <= 8 \ +- ? __mempcpy_small (dest, __mempcpy_args (src), n) \ +- : __mempcpy (dest, src, n))) +-# endif +-/* In glibc we use this function frequently but for namespace reasons +- we have to use the name `__mempcpy'. */ +-# define mempcpy(dest, src, n) __mempcpy (dest, src, n) +-# endif +- +-# if !__GNUC_PREREQ (3, 0) || defined _FORCE_INLINES +-# if _STRING_ARCH_unaligned +-# ifndef _FORCE_INLINES +-# define __mempcpy_args(src) \ +- ((const char *) (src))[0], ((const char *) (src))[2], \ +- ((const char *) (src))[4], ((const char *) (src))[6], \ +- __extension__ __STRING2_SMALL_GET16 (src, 0), \ +- __extension__ __STRING2_SMALL_GET16 (src, 4), \ +- __extension__ __STRING2_SMALL_GET32 (src, 0), \ +- __extension__ __STRING2_SMALL_GET32 (src, 4) +-# endif +-__STRING_INLINE void *__mempcpy_small (void *, char, char, char, char, +- __uint16_t, __uint16_t, __uint32_t, +- __uint32_t, size_t); ++#if defined _FORCE_INLINES ++# if _STRING_ARCH_unaligned + __STRING_INLINE void * + __mempcpy_small (void *__dest1, + char __src0_1, char __src2_1, char __src4_1, char __src6_1, +@@ -298,44 +139,7 @@ __mempcpy_small (void *__dest1, + } + return (void *) __u; + } +-# else +-# ifndef _FORCE_INLINES +-# define __mempcpy_args(src) \ +- ((const char *) (src))[0], \ +- __extension__ ((__STRING2_COPY_ARR2) \ +- { { ((const char *) (src))[0], ((const char *) (src))[1] } }), \ +- __extension__ ((__STRING2_COPY_ARR3) \ +- { { ((const char *) (src))[0], ((const char *) (src))[1], \ +- ((const char *) (src))[2] } }), \ +- __extension__ ((__STRING2_COPY_ARR4) \ +- { { ((const char *) (src))[0], ((const char *) (src))[1], \ +- ((const char *) (src))[2], ((const char *) (src))[3] } }), \ +- __extension__ ((__STRING2_COPY_ARR5) \ +- { { ((const char *) (src))[0], ((const char *) (src))[1], \ +- ((const char *) (src))[2], ((const char *) (src))[3], \ +- ((const char *) (src))[4] } }), \ +- __extension__ ((__STRING2_COPY_ARR6) \ +- { { ((const char *) (src))[0], ((const char *) (src))[1], \ +- ((const char *) (src))[2], ((const char *) (src))[3], \ +- ((const char *) (src))[4], ((const char *) (src))[5] } }), \ +- __extension__ ((__STRING2_COPY_ARR7) \ +- { { ((const char *) (src))[0], ((const char *) (src))[1], \ +- ((const char *) (src))[2], ((const char *) (src))[3], \ +- ((const char *) (src))[4], ((const char *) (src))[5], \ +- ((const char *) (src))[6] } }), \ +- __extension__ ((__STRING2_COPY_ARR8) \ +- { { ((const char *) (src))[0], ((const char *) (src))[1], \ +- ((const char *) (src))[2], ((const char *) (src))[3], \ +- ((const char *) (src))[4], ((const char *) (src))[5], \ +- ((const char *) (src))[6], ((const char *) (src))[7] } }) +-# endif +-__STRING_INLINE void *__mempcpy_small (void *, char, __STRING2_COPY_ARR2, +- __STRING2_COPY_ARR3, +- __STRING2_COPY_ARR4, +- __STRING2_COPY_ARR5, +- __STRING2_COPY_ARR6, +- __STRING2_COPY_ARR7, +- __STRING2_COPY_ARR8, size_t); ++# else + __STRING_INLINE void * + __mempcpy_small (void *__dest, char __src1, + __STRING2_COPY_ARR2 __src2, __STRING2_COPY_ARR3 __src3, +@@ -382,8 +186,6 @@ __mempcpy_small (void *__dest, char __src1, + } + return __extension__ ((void *) __u + __srclen); + } +-# endif +-# endif + # endif + #endif + +@@ -391,44 +193,17 @@ __mempcpy_small (void *__dest, char __src1, + /* Return pointer to C in S. */ + #ifndef _HAVE_STRING_ARCH_strchr + extern void *__rawmemchr (const void *__s, int __c); +-# if __GNUC_PREREQ (3, 2) + # define strchr(s, c) \ + (__extension__ (__builtin_constant_p (c) && !__builtin_constant_p (s) \ + && (c) == '\0' \ + ? (char *) __rawmemchr (s, c) \ + : __builtin_strchr (s, c))) +-# else +-# define strchr(s, c) \ +- (__extension__ (__builtin_constant_p (c) && (c) == '\0' \ +- ? (char *) __rawmemchr (s, c) \ +- : strchr (s, c))) +-# endif + #endif + + + /* Copy SRC to DEST. */ +-#if (!defined _HAVE_STRING_ARCH_strcpy && !__GNUC_PREREQ (3, 0)) \ +- || defined _FORCE_INLINES +-# if !defined _HAVE_STRING_ARCH_strcpy && !__GNUC_PREREQ (3, 0) +-# define strcpy(dest, src) \ +- (__extension__ (__builtin_constant_p (src) \ +- ? (__string2_1bptr_p (src) && strlen (src) + 1 <= 8 \ +- ? __strcpy_small (dest, __strcpy_args (src), \ +- strlen (src) + 1) \ +- : (char *) memcpy (dest, src, strlen (src) + 1)) \ +- : strcpy (dest, src))) +-# endif +- ++#if defined _FORCE_INLINES + # if _STRING_ARCH_unaligned +-# ifndef _FORCE_INLINES +-# define __strcpy_args(src) \ +- __extension__ __STRING2_SMALL_GET16 (src, 0), \ +- __extension__ __STRING2_SMALL_GET16 (src, 4), \ +- __extension__ __STRING2_SMALL_GET32 (src, 0), \ +- __extension__ __STRING2_SMALL_GET32 (src, 4) +-# endif +-__STRING_INLINE char *__strcpy_small (char *, __uint16_t, __uint16_t, +- __uint32_t, __uint32_t, size_t); + __STRING_INLINE char * + __strcpy_small (char *__dest, + __uint16_t __src0_2, __uint16_t __src4_2, +@@ -482,42 +257,6 @@ __strcpy_small (char *__dest, + return __dest; + } + # else +-# ifndef _FORCE_INLINES +-# define __strcpy_args(src) \ +- __extension__ ((__STRING2_COPY_ARR2) \ +- { { ((const char *) (src))[0], '\0' } }), \ +- __extension__ ((__STRING2_COPY_ARR3) \ +- { { ((const char *) (src))[0], ((const char *) (src))[1], \ +- '\0' } }), \ +- __extension__ ((__STRING2_COPY_ARR4) \ +- { { ((const char *) (src))[0], ((const char *) (src))[1], \ +- ((const char *) (src))[2], '\0' } }), \ +- __extension__ ((__STRING2_COPY_ARR5) \ +- { { ((const char *) (src))[0], ((const char *) (src))[1], \ +- ((const char *) (src))[2], ((const char *) (src))[3], \ +- '\0' } }), \ +- __extension__ ((__STRING2_COPY_ARR6) \ +- { { ((const char *) (src))[0], ((const char *) (src))[1], \ +- ((const char *) (src))[2], ((const char *) (src))[3], \ +- ((const char *) (src))[4], '\0' } }), \ +- __extension__ ((__STRING2_COPY_ARR7) \ +- { { ((const char *) (src))[0], ((const char *) (src))[1], \ +- ((const char *) (src))[2], ((const char *) (src))[3], \ +- ((const char *) (src))[4], ((const char *) (src))[5], \ +- '\0' } }), \ +- __extension__ ((__STRING2_COPY_ARR8) \ +- { { ((const char *) (src))[0], ((const char *) (src))[1], \ +- ((const char *) (src))[2], ((const char *) (src))[3], \ +- ((const char *) (src))[4], ((const char *) (src))[5], \ +- ((const char *) (src))[6], '\0' } }) +-# endif +-__STRING_INLINE char *__strcpy_small (char *, __STRING2_COPY_ARR2, +- __STRING2_COPY_ARR3, +- __STRING2_COPY_ARR4, +- __STRING2_COPY_ARR5, +- __STRING2_COPY_ARR6, +- __STRING2_COPY_ARR7, +- __STRING2_COPY_ARR8, size_t); + __STRING_INLINE char * + __strcpy_small (char *__dest, + __STRING2_COPY_ARR2 __src2, __STRING2_COPY_ARR3 __src3, +@@ -570,44 +309,15 @@ __strcpy_small (char *__dest, + + /* Copy SRC to DEST, returning pointer to final NUL byte. */ + #ifdef __USE_GNU +-# if !defined _HAVE_STRING_ARCH_stpcpy || defined _FORCE_INLINES +-# ifndef _HAVE_STRING_ARCH_stpcpy +-# if __GNUC_PREREQ (3, 4) +-# define __stpcpy(dest, src) __builtin_stpcpy (dest, src) +-# elif __GNUC_PREREQ (3, 0) +-# define __stpcpy(dest, src) \ +- (__extension__ (__builtin_constant_p (src) \ +- ? (__string2_1bptr_p (src) && strlen (src) + 1 <= 8 \ +- ? __builtin_strcpy (dest, src) + strlen (src) \ +- : ((char *) (__mempcpy) (dest, src, strlen (src) + 1) \ +- - 1)) \ +- : __stpcpy (dest, src))) +-# else +-# define __stpcpy(dest, src) \ +- (__extension__ (__builtin_constant_p (src) \ +- ? (__string2_1bptr_p (src) && strlen (src) + 1 <= 8 \ +- ? __stpcpy_small (dest, __stpcpy_args (src), \ +- strlen (src) + 1) \ +- : ((char *) (__mempcpy) (dest, src, strlen (src) + 1) \ +- - 1)) \ +- : __stpcpy (dest, src))) +-# endif ++# ifndef _HAVE_STRING_ARCH_stpcpy ++# define __stpcpy(dest, src) __builtin_stpcpy (dest, src) + /* In glibc we use this function frequently but for namespace reasons + we have to use the name `__stpcpy'. */ +-# define stpcpy(dest, src) __stpcpy (dest, src) +-# endif ++# define stpcpy(dest, src) __stpcpy (dest, src) ++# endif + +-# if !__GNUC_PREREQ (3, 0) || defined _FORCE_INLINES +-# if _STRING_ARCH_unaligned +-# ifndef _FORCE_INLINES +-# define __stpcpy_args(src) \ +- __extension__ __STRING2_SMALL_GET16 (src, 0), \ +- __extension__ __STRING2_SMALL_GET16 (src, 4), \ +- __extension__ __STRING2_SMALL_GET32 (src, 0), \ +- __extension__ __STRING2_SMALL_GET32 (src, 4) +-# endif +-__STRING_INLINE char *__stpcpy_small (char *, __uint16_t, __uint16_t, +- __uint32_t, __uint32_t, size_t); ++# ifndef _FORCE_INLINES ++# if _STRING_ARCH_unaligned + __STRING_INLINE char * + __stpcpy_small (char *__dest, + __uint16_t __src0_2, __uint16_t __src4_2, +@@ -665,43 +375,7 @@ __stpcpy_small (char *__dest, + } + return &__u->__c; + } +-# else +-# ifndef _FORCE_INLINES +-# define __stpcpy_args(src) \ +- __extension__ ((__STRING2_COPY_ARR2) \ +- { { ((const char *) (src))[0], '\0' } }), \ +- __extension__ ((__STRING2_COPY_ARR3) \ +- { { ((const char *) (src))[0], ((const char *) (src))[1], \ +- '\0' } }), \ +- __extension__ ((__STRING2_COPY_ARR4) \ +- { { ((const char *) (src))[0], ((const char *) (src))[1], \ +- ((const char *) (src))[2], '\0' } }), \ +- __extension__ ((__STRING2_COPY_ARR5) \ +- { { ((const char *) (src))[0], ((const char *) (src))[1], \ +- ((const char *) (src))[2], ((const char *) (src))[3], \ +- '\0' } }), \ +- __extension__ ((__STRING2_COPY_ARR6) \ +- { { ((const char *) (src))[0], ((const char *) (src))[1], \ +- ((const char *) (src))[2], ((const char *) (src))[3], \ +- ((const char *) (src))[4], '\0' } }), \ +- __extension__ ((__STRING2_COPY_ARR7) \ +- { { ((const char *) (src))[0], ((const char *) (src))[1], \ +- ((const char *) (src))[2], ((const char *) (src))[3], \ +- ((const char *) (src))[4], ((const char *) (src))[5], \ +- '\0' } }), \ +- __extension__ ((__STRING2_COPY_ARR8) \ +- { { ((const char *) (src))[0], ((const char *) (src))[1], \ +- ((const char *) (src))[2], ((const char *) (src))[3], \ +- ((const char *) (src))[4], ((const char *) (src))[5], \ +- ((const char *) (src))[6], '\0' } }) +-# endif +-__STRING_INLINE char *__stpcpy_small (char *, __STRING2_COPY_ARR2, +- __STRING2_COPY_ARR3, +- __STRING2_COPY_ARR4, +- __STRING2_COPY_ARR5, +- __STRING2_COPY_ARR6, +- __STRING2_COPY_ARR7, +- __STRING2_COPY_ARR8, size_t); ++# else + __STRING_INLINE char * + __stpcpy_small (char *__dest, + __STRING2_COPY_ARR2 __src2, __STRING2_COPY_ARR3 __src3, +@@ -748,27 +422,11 @@ __stpcpy_small (char *__dest, + } + return __dest + __srclen - 1; + } +-# endif + # endif + # endif + #endif + + +-/* Copy no more than N characters of SRC to DEST. */ +-#ifndef _HAVE_STRING_ARCH_strncpy +-# if __GNUC_PREREQ (3, 2) +-# define strncpy(dest, src, n) __builtin_strncpy (dest, src, n) +-# else +-# define strncpy(dest, src, n) \ +- (__extension__ (__builtin_constant_p (src) && __builtin_constant_p (n) \ +- ? (strlen (src) + 1 >= ((size_t) (n)) \ +- ? (char *) memcpy (dest, src, n) \ +- : strncpy (dest, src, n)) \ +- : strncpy (dest, src, n))) +-# endif +-#endif +- +- + /* Append no more than N characters from SRC onto DEST. */ + #ifndef _HAVE_STRING_ARCH_strncat + # ifdef _USE_STRING_ARCH_strchr +@@ -780,380 +438,29 @@ __stpcpy_small (char *__dest, + : (*((char *) __mempcpy (strchr (__dest, '\0'), \ + src, n)) = '\0', __dest)) \ + : strncat (dest, src, n); })) +-# elif __GNUC_PREREQ (3, 2) +-# define strncat(dest, src, n) __builtin_strncat (dest, src, n) + # else +-# define strncat(dest, src, n) \ +- (__extension__ (__builtin_constant_p (src) && __builtin_constant_p (n) \ +- ? (strlen (src) < ((size_t) (n)) \ +- ? strcat (dest, src) \ +- : strncat (dest, src, n)) \ +- : strncat (dest, src, n))) +-# endif +-#endif +- +- +-/* Compare characters of S1 and S2. */ +-#ifndef _HAVE_STRING_ARCH_strcmp +-# if __GNUC_PREREQ (3, 2) +-# define strcmp(s1, s2) \ +- __extension__ \ +- ({ size_t __s1_len, __s2_len; \ +- (__builtin_constant_p (s1) && __builtin_constant_p (s2) \ +- && (__s1_len = strlen (s1), __s2_len = strlen (s2), \ +- (!__string2_1bptr_p (s1) || __s1_len >= 4) \ +- && (!__string2_1bptr_p (s2) || __s2_len >= 4)) \ +- ? __builtin_strcmp (s1, s2) \ +- : (__builtin_constant_p (s1) && __string2_1bptr_p (s1) \ +- && (__s1_len = strlen (s1), __s1_len < 4) \ +- ? (__builtin_constant_p (s2) && __string2_1bptr_p (s2) \ +- ? __builtin_strcmp (s1, s2) \ +- : __strcmp_cg (s1, s2, __s1_len)) \ +- : (__builtin_constant_p (s2) && __string2_1bptr_p (s2) \ +- && (__s2_len = strlen (s2), __s2_len < 4) \ +- ? (__builtin_constant_p (s1) && __string2_1bptr_p (s1) \ +- ? __builtin_strcmp (s1, s2) \ +- : __strcmp_gc (s1, s2, __s2_len)) \ +- : __builtin_strcmp (s1, s2)))); }) +-# else +-# define strcmp(s1, s2) \ +- __extension__ \ +- ({ size_t __s1_len, __s2_len; \ +- (__builtin_constant_p (s1) && __builtin_constant_p (s2) \ +- && (__s1_len = strlen (s1), __s2_len = strlen (s2), \ +- (!__string2_1bptr_p (s1) || __s1_len >= 4) \ +- && (!__string2_1bptr_p (s2) || __s2_len >= 4)) \ +- ? memcmp ((const char *) (s1), (const char *) (s2), \ +- (__s1_len < __s2_len ? __s1_len : __s2_len) + 1) \ +- : (__builtin_constant_p (s1) && __string2_1bptr_p (s1) \ +- && (__s1_len = strlen (s1), __s1_len < 4) \ +- ? (__builtin_constant_p (s2) && __string2_1bptr_p (s2) \ +- ? __strcmp_cc (s1, s2, __s1_len) \ +- : __strcmp_cg (s1, s2, __s1_len)) \ +- : (__builtin_constant_p (s2) && __string2_1bptr_p (s2) \ +- && (__s2_len = strlen (s2), __s2_len < 4) \ +- ? (__builtin_constant_p (s1) && __string2_1bptr_p (s1) \ +- ? __strcmp_cc (s1, s2, __s2_len) \ +- : __strcmp_gc (s1, s2, __s2_len)) \ +- : strcmp (s1, s2)))); }) ++# define strncat(dest, src, n) __builtin_strncat (dest, src, n) + # endif +- +-# define __strcmp_cc(s1, s2, l) \ +- (__extension__ ({ int __result = \ +- (((const unsigned char *) (const char *) (s1))[0] \ +- - ((const unsigned char *) (const char *)(s2))[0]); \ +- if (l > 0 && __result == 0) \ +- { \ +- __result = (((const unsigned char *) \ +- (const char *) (s1))[1] \ +- - ((const unsigned char *) \ +- (const char *) (s2))[1]); \ +- if (l > 1 && __result == 0) \ +- { \ +- __result = \ +- (((const unsigned char *) \ +- (const char *) (s1))[2] \ +- - ((const unsigned char *) \ +- (const char *) (s2))[2]); \ +- if (l > 2 && __result == 0) \ +- __result = \ +- (((const unsigned char *) \ +- (const char *) (s1))[3] \ +- - ((const unsigned char *) \ +- (const char *) (s2))[3]); \ +- } \ +- } \ +- __result; })) +- +-# define __strcmp_cg(s1, s2, l1) \ +- (__extension__ ({ const unsigned char *__s2 = \ +- (const unsigned char *) (const char *) (s2); \ +- int __result = \ +- (((const unsigned char *) (const char *) (s1))[0] \ +- - __s2[0]); \ +- if (l1 > 0 && __result == 0) \ +- { \ +- __result = (((const unsigned char *) \ +- (const char *) (s1))[1] - __s2[1]); \ +- if (l1 > 1 && __result == 0) \ +- { \ +- __result = (((const unsigned char *) \ +- (const char *) (s1))[2] - __s2[2]); \ +- if (l1 > 2 && __result == 0) \ +- __result = (((const unsigned char *) \ +- (const char *) (s1))[3] \ +- - __s2[3]); \ +- } \ +- } \ +- __result; })) +- +-# define __strcmp_gc(s1, s2, l2) \ +- (__extension__ ({ const unsigned char *__s1 = \ +- (const unsigned char *) (const char *) (s1); \ +- register int __result = \ +- __s1[0] - ((const unsigned char *) \ +- (const char *) (s2))[0]; \ +- if (l2 > 0 && __result == 0) \ +- { \ +- __result = (__s1[1] \ +- - ((const unsigned char *) \ +- (const char *) (s2))[1]); \ +- if (l2 > 1 && __result == 0) \ +- { \ +- __result = \ +- (__s1[2] - ((const unsigned char *) \ +- (const char *) (s2))[2]); \ +- if (l2 > 2 && __result == 0) \ +- __result = \ +- (__s1[3] \ +- - ((const unsigned char *) \ +- (const char *) (s2))[3]); \ +- } \ +- } \ +- __result; })) +-#endif +- +- +-/* Compare N characters of S1 and S2. */ +-#ifndef _HAVE_STRING_ARCH_strncmp +-# define strncmp(s1, s2, n) \ +- (__extension__ (__builtin_constant_p (n) \ +- && ((__builtin_constant_p (s1) \ +- && strlen (s1) < ((size_t) (n))) \ +- || (__builtin_constant_p (s2) \ +- && strlen (s2) < ((size_t) (n)))) \ +- ? strcmp (s1, s2) : strncmp (s1, s2, n))) + #endif + + + /* Return the length of the initial segment of S which + consists entirely of characters not in REJECT. */ +-#if !defined _HAVE_STRING_ARCH_strcspn || defined _FORCE_INLINES +-# ifndef _HAVE_STRING_ARCH_strcspn +-# if __GNUC_PREREQ (3, 2) +-# define strcspn(s, reject) \ +- __extension__ \ +- ({ char __r0, __r1, __r2; \ +- (__builtin_constant_p (reject) && __string2_1bptr_p (reject) \ +- ? ((__builtin_constant_p (s) && __string2_1bptr_p (s)) \ +- ? __builtin_strcspn (s, reject) \ +- : ((__r0 = ((const char *) (reject))[0], __r0 == '\0') \ +- ? strlen (s) \ +- : ((__r1 = ((const char *) (reject))[1], __r1 == '\0') \ +- ? __strcspn_c1 (s, __r0) \ +- : ((__r2 = ((const char *) (reject))[2], __r2 == '\0') \ +- ? __strcspn_c2 (s, __r0, __r1) \ +- : (((const char *) (reject))[3] == '\0' \ +- ? __strcspn_c3 (s, __r0, __r1, __r2) \ +- : __builtin_strcspn (s, reject)))))) \ +- : __builtin_strcspn (s, reject)); }) +-# else +-# define strcspn(s, reject) \ +- __extension__ \ +- ({ char __r0, __r1, __r2; \ +- (__builtin_constant_p (reject) && __string2_1bptr_p (reject) \ +- ? ((__r0 = ((const char *) (reject))[0], __r0 == '\0') \ +- ? strlen (s) \ +- : ((__r1 = ((const char *) (reject))[1], __r1 == '\0') \ +- ? __strcspn_c1 (s, __r0) \ +- : ((__r2 = ((const char *) (reject))[2], __r2 == '\0') \ +- ? __strcspn_c2 (s, __r0, __r1) \ +- : (((const char *) (reject))[3] == '\0' \ +- ? __strcspn_c3 (s, __r0, __r1, __r2) \ +- : strcspn (s, reject))))) \ +- : strcspn (s, reject)); }) +-# endif +-# endif +- +-__STRING_INLINE size_t __strcspn_c1 (const char *__s, int __reject); +-__STRING_INLINE size_t +-__strcspn_c1 (const char *__s, int __reject) +-{ +- size_t __result = 0; +- while (__s[__result] != '\0' && __s[__result] != __reject) +- ++__result; +- return __result; +-} +- +-__STRING_INLINE size_t __strcspn_c2 (const char *__s, int __reject1, +- int __reject2); +-__STRING_INLINE size_t +-__strcspn_c2 (const char *__s, int __reject1, int __reject2) +-{ +- size_t __result = 0; +- while (__s[__result] != '\0' && __s[__result] != __reject1 +- && __s[__result] != __reject2) +- ++__result; +- return __result; +-} +- +-__STRING_INLINE size_t __strcspn_c3 (const char *__s, int __reject1, +- int __reject2, int __reject3); +-__STRING_INLINE size_t +-__strcspn_c3 (const char *__s, int __reject1, int __reject2, +- int __reject3) +-{ +- size_t __result = 0; +- while (__s[__result] != '\0' && __s[__result] != __reject1 +- && __s[__result] != __reject2 && __s[__result] != __reject3) +- ++__result; +- return __result; +-} ++#ifndef _HAVE_STRING_ARCH_strcspn ++# define strcspn(s, reject) __builtin_strcspn (s, reject) + #endif + + + /* Return the length of the initial segment of S which + consists entirely of characters in ACCEPT. */ +-#if !defined _HAVE_STRING_ARCH_strspn || defined _FORCE_INLINES +-# ifndef _HAVE_STRING_ARCH_strspn +-# if __GNUC_PREREQ (3, 2) +-# define strspn(s, accept) \ +- __extension__ \ +- ({ char __a0, __a1, __a2; \ +- (__builtin_constant_p (accept) && __string2_1bptr_p (accept) \ +- ? ((__builtin_constant_p (s) && __string2_1bptr_p (s)) \ +- ? __builtin_strspn (s, accept) \ +- : ((__a0 = ((const char *) (accept))[0], __a0 == '\0') \ +- ? ((void) (s), (size_t) 0) \ +- : ((__a1 = ((const char *) (accept))[1], __a1 == '\0') \ +- ? __strspn_c1 (s, __a0) \ +- : ((__a2 = ((const char *) (accept))[2], __a2 == '\0') \ +- ? __strspn_c2 (s, __a0, __a1) \ +- : (((const char *) (accept))[3] == '\0' \ +- ? __strspn_c3 (s, __a0, __a1, __a2) \ +- : __builtin_strspn (s, accept)))))) \ +- : __builtin_strspn (s, accept)); }) +-# else +-# define strspn(s, accept) \ +- __extension__ \ +- ({ char __a0, __a1, __a2; \ +- (__builtin_constant_p (accept) && __string2_1bptr_p (accept) \ +- ? ((__a0 = ((const char *) (accept))[0], __a0 == '\0') \ +- ? ((void) (s), (size_t) 0) \ +- : ((__a1 = ((const char *) (accept))[1], __a1 == '\0') \ +- ? __strspn_c1 (s, __a0) \ +- : ((__a2 = ((const char *) (accept))[2], __a2 == '\0') \ +- ? __strspn_c2 (s, __a0, __a1) \ +- : (((const char *) (accept))[3] == '\0' \ +- ? __strspn_c3 (s, __a0, __a1, __a2) \ +- : strspn (s, accept))))) \ +- : strspn (s, accept)); }) +-# endif +-# endif +- +-__STRING_INLINE size_t __strspn_c1 (const char *__s, int __accept); +-__STRING_INLINE size_t +-__strspn_c1 (const char *__s, int __accept) +-{ +- size_t __result = 0; +- /* Please note that __accept never can be '\0'. */ +- while (__s[__result] == __accept) +- ++__result; +- return __result; +-} +- +-__STRING_INLINE size_t __strspn_c2 (const char *__s, int __accept1, +- int __accept2); +-__STRING_INLINE size_t +-__strspn_c2 (const char *__s, int __accept1, int __accept2) +-{ +- size_t __result = 0; +- /* Please note that __accept1 and __accept2 never can be '\0'. */ +- while (__s[__result] == __accept1 || __s[__result] == __accept2) +- ++__result; +- return __result; +-} +- +-__STRING_INLINE size_t __strspn_c3 (const char *__s, int __accept1, +- int __accept2, int __accept3); +-__STRING_INLINE size_t +-__strspn_c3 (const char *__s, int __accept1, int __accept2, int __accept3) +-{ +- size_t __result = 0; +- /* Please note that __accept1 to __accept3 never can be '\0'. */ +- while (__s[__result] == __accept1 || __s[__result] == __accept2 +- || __s[__result] == __accept3) +- ++__result; +- return __result; +-} ++#ifndef _HAVE_STRING_ARCH_strspn ++# define strspn(s, accept) __builtin_strspn (s, accept) + #endif + + + /* Find the first occurrence in S of any character in ACCEPT. */ +-#if !defined _HAVE_STRING_ARCH_strpbrk || defined _FORCE_INLINES +-# ifndef _HAVE_STRING_ARCH_strpbrk +-# if __GNUC_PREREQ (3, 2) +-# define strpbrk(s, accept) \ +- __extension__ \ +- ({ char __a0, __a1, __a2; \ +- (__builtin_constant_p (accept) && __string2_1bptr_p (accept) \ +- ? ((__builtin_constant_p (s) && __string2_1bptr_p (s)) \ +- ? __builtin_strpbrk (s, accept) \ +- : ((__a0 = ((const char *) (accept))[0], __a0 == '\0') \ +- ? ((void) (s), (char *) NULL) \ +- : ((__a1 = ((const char *) (accept))[1], __a1 == '\0') \ +- ? __builtin_strchr (s, __a0) \ +- : ((__a2 = ((const char *) (accept))[2], __a2 == '\0') \ +- ? __strpbrk_c2 (s, __a0, __a1) \ +- : (((const char *) (accept))[3] == '\0' \ +- ? __strpbrk_c3 (s, __a0, __a1, __a2) \ +- : __builtin_strpbrk (s, accept)))))) \ +- : __builtin_strpbrk (s, accept)); }) +-# else +-# define strpbrk(s, accept) \ +- __extension__ \ +- ({ char __a0, __a1, __a2; \ +- (__builtin_constant_p (accept) && __string2_1bptr_p (accept) \ +- ? ((__a0 = ((const char *) (accept))[0], __a0 == '\0') \ +- ? ((void) (s), (char *) NULL) \ +- : ((__a1 = ((const char *) (accept))[1], __a1 == '\0') \ +- ? strchr (s, __a0) \ +- : ((__a2 = ((const char *) (accept))[2], __a2 == '\0') \ +- ? __strpbrk_c2 (s, __a0, __a1) \ +- : (((const char *) (accept))[3] == '\0' \ +- ? __strpbrk_c3 (s, __a0, __a1, __a2) \ +- : strpbrk (s, accept))))) \ +- : strpbrk (s, accept)); }) +-# endif +-# endif +- +-__STRING_INLINE char *__strpbrk_c2 (const char *__s, int __accept1, +- int __accept2); +-__STRING_INLINE char * +-__strpbrk_c2 (const char *__s, int __accept1, int __accept2) +-{ +- /* Please note that __accept1 and __accept2 never can be '\0'. */ +- while (*__s != '\0' && *__s != __accept1 && *__s != __accept2) +- ++__s; +- return *__s == '\0' ? NULL : (char *) (size_t) __s; +-} +- +-__STRING_INLINE char *__strpbrk_c3 (const char *__s, int __accept1, +- int __accept2, int __accept3); +-__STRING_INLINE char * +-__strpbrk_c3 (const char *__s, int __accept1, int __accept2, int __accept3) +-{ +- /* Please note that __accept1 to __accept3 never can be '\0'. */ +- while (*__s != '\0' && *__s != __accept1 && *__s != __accept2 +- && *__s != __accept3) +- ++__s; +- return *__s == '\0' ? NULL : (char *) (size_t) __s; +-} +-#endif +- +- +-/* Find the first occurrence of NEEDLE in HAYSTACK. Newer gcc versions +- do this itself. */ +-#if !defined _HAVE_STRING_ARCH_strstr && !__GNUC_PREREQ (2, 97) +-# define strstr(haystack, needle) \ +- (__extension__ (__builtin_constant_p (needle) && __string2_1bptr_p (needle) \ +- ? (((const char *) (needle))[0] == '\0' \ +- ? (char *) (size_t) (haystack) \ +- : (((const char *) (needle))[1] == '\0' \ +- ? strchr (haystack, \ +- ((const char *) (needle))[0]) \ +- : strstr (haystack, needle))) \ +- : strstr (haystack, needle))) ++#ifndef _HAVE_STRING_ARCH_strpbrk ++# define strpbrk(s, accept) __builtin_strpbrk (s, accept) + #endif + + +diff --git a/string/strncat.c b/string/strncat.c +index dcfb04d..a9cb913 100644 +--- a/string/strncat.c ++++ b/string/strncat.c +@@ -1,4 +1,4 @@ +-/* Copyright (C) 1991,1997,2011 Free Software Foundation, Inc. ++/* Copyright (C) 1991-2022 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or +@@ -13,14 +13,10 @@ + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see +- . */ ++ . */ + + #include + +-#ifdef _LIBC +-# include +-#endif +- + #ifndef STRNCAT + # undef strncat + # define STRNCAT strncat +@@ -29,54 +25,16 @@ + char * + STRNCAT (char *s1, const char *s2, size_t n) + { +- char c; + char *s = s1; + + /* Find the end of S1. */ +- do +- c = *s1++; +- while (c != '\0'); +- +- /* Make S1 point before next character, so we can increment +- it while memory is read (wins on pipelined cpus). */ +- s1 -= 2; ++ s1 += strlen (s1); + +- if (n >= 4) +- { +- size_t n4 = n >> 2; +- do +- { +- c = *s2++; +- *++s1 = c; +- if (c == '\0') +- return s; +- c = *s2++; +- *++s1 = c; +- if (c == '\0') +- return s; +- c = *s2++; +- *++s1 = c; +- if (c == '\0') +- return s; +- c = *s2++; +- *++s1 = c; +- if (c == '\0') +- return s; +- } while (--n4 > 0); +- n &= 3; +- } ++ size_t ss = __strnlen (s2, n); + +- while (n > 0) +- { +- c = *s2++; +- *++s1 = c; +- if (c == '\0') +- return s; +- n--; +- } +- +- if (c != '\0') +- *++s1 = '\0'; ++ s1[ss] = '\0'; ++ memcpy (s1, s2, ss); + + return s; + } ++ +diff --git a/string/strncpy.c b/string/strncpy.c +index 19d501e..83fb610 100644 +--- a/string/strncpy.c ++++ b/string/strncpy.c +@@ -1,4 +1,4 @@ +-/* Copyright (C) 1991, 1997, 2003 Free Software Foundation, Inc. ++/* Copyright (C) 1991-2022 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or +@@ -13,75 +13,22 @@ + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see +- . */ ++ . */ + + #include +-#include + + #undef strncpy + + #ifndef STRNCPY +-#define STRNCPY strncpy ++ #define STRNCPY strncpy + #endif + + char * + STRNCPY (char *s1, const char *s2, size_t n) + { +- char c; +- char *s = s1; +- +- --s1; +- +- if (n >= 4) +- { +- size_t n4 = n >> 2; +- +- for (;;) +- { +- c = *s2++; +- *++s1 = c; +- if (c == '\0') +- break; +- c = *s2++; +- *++s1 = c; +- if (c == '\0') +- break; +- c = *s2++; +- *++s1 = c; +- if (c == '\0') +- break; +- c = *s2++; +- *++s1 = c; +- if (c == '\0') +- break; +- if (--n4 == 0) +- goto last_chars; +- } +- n = n - (s1 - s) - 1; +- if (n == 0) +- return s; +- goto zero_fill; +- } +- +- last_chars: +- n &= 3; +- if (n == 0) +- return s; +- +- do +- { +- c = *s2++; +- *++s1 = c; +- if (--n == 0) +- return s; +- } +- while (c != '\0'); +- +- zero_fill: +- do +- *++s1 = '\0'; +- while (--n > 0); +- +- return s; ++ size_t size = __strnlen (s2, n); ++ if (size != n) ++ memset (s1 + size, '\0', n - size); ++ return memcpy (s1, s2, size); + } + libc_hidden_builtin_def (strncpy) +diff --git a/sysdeps/gnu/bits/utmp.h b/sysdeps/gnu/bits/utmp.h +index aed2750..434a533 100644 +--- a/sysdeps/gnu/bits/utmp.h ++++ b/sysdeps/gnu/bits/utmp.h +@@ -59,10 +59,14 @@ struct utmp + { + short int ut_type; /* Type of login. */ + pid_t ut_pid; /* Process ID of login process. */ +- char ut_line[UT_LINESIZE]; /* Devicename. */ +- char ut_id[4]; /* Inittab ID. */ +- char ut_user[UT_NAMESIZE]; /* Username. */ +- char ut_host[UT_HOSTSIZE]; /* Hostname for remote login. */ ++ char ut_line[UT_LINESIZE] ++ __attribute_nonstring__; /* Devicename. */ ++ char ut_id[4] ++ __attribute_nonstring__; /* Inittab ID. */ ++ char ut_user[UT_NAMESIZE] ++ __attribute_nonstring__; /* Username. */ ++ char ut_host[UT_HOSTSIZE] ++ __attribute_nonstring__; /* Hostname for remote login. */ + struct exit_status ut_exit; /* Exit status of a process marked + as DEAD_PROCESS. */ + /* The ut_session and ut_tv fields must be the same size when compiled +diff --git a/sysdeps/gnu/bits/utmpx.h b/sysdeps/gnu/bits/utmpx.h +index f8716ca..13d84e4 100644 +--- a/sysdeps/gnu/bits/utmpx.h ++++ b/sysdeps/gnu/bits/utmpx.h +@@ -56,10 +56,14 @@ struct utmpx + { + short int ut_type; /* Type of login. */ + __pid_t ut_pid; /* Process ID of login process. */ +- char ut_line[__UT_LINESIZE]; /* Devicename. */ +- char ut_id[4]; /* Inittab ID. */ +- char ut_user[__UT_NAMESIZE]; /* Username. */ +- char ut_host[__UT_HOSTSIZE]; /* Hostname for remote login. */ ++ char ut_line[__UT_LINESIZE] ++ __attribute_nonstring__; /* Devicename. */ ++ char ut_id[4] ++ __attribute_nonstring__; /* Inittab ID. */ ++ char ut_user[__UT_NAMESIZE] ++ __attribute_nonstring__; /* Username. */ ++ char ut_host[__UT_HOSTSIZE] ++ __attribute_nonstring__; /* Hostname for remote login. */ + struct __exit_status ut_exit; /* Exit status of a process marked + as DEAD_PROCESS. */ + +diff --git a/sysdeps/unix/sysv/linux/if_index.c b/sysdeps/unix/sysv/linux/if_index.c +index 8ba5eae..b620d21 100644 +--- a/sysdeps/unix/sysv/linux/if_index.c ++++ b/sysdeps/unix/sysv/linux/if_index.c +@@ -38,12 +38,19 @@ __if_nametoindex (const char *ifname) + return 0; + #else + struct ifreq ifr; ++ if (strlen (ifname) >= IFNAMSIZ) ++ { ++ __set_errno (ENODEV); ++ return 0; ++ } ++ ++ strncpy (ifr.ifr_name, ifname, sizeof (ifr.ifr_name)); ++ + int fd = __opensock (); + + if (fd < 0) + return 0; + +- strncpy (ifr.ifr_name, ifname, sizeof (ifr.ifr_name)); + if (__ioctl (fd, SIOCGIFINDEX, &ifr) < 0) + { + int saved_errno = errno; +diff --git a/timezone/zic.c b/timezone/zic.c +index a5202a1..772d081 100644 +--- a/timezone/zic.c ++++ b/timezone/zic.c +@@ -1609,7 +1609,7 @@ writezone(const char *const name, const char *const string) + } + #define DO(field) ((void) fwrite(tzh.field, sizeof tzh.field, 1, fp)) + tzh = tzh0; +- (void) strncpy(tzh.tzh_magic, TZ_MAGIC, sizeof tzh.tzh_magic); ++ memcpy(tzh.tzh_magic, TZ_MAGIC, sizeof tzh.tzh_magic); + tzh.tzh_version[0] = ZIC_VERSION; + convert(eitol(thistypecnt), tzh.tzh_ttisgmtcnt); + convert(eitol(thistypecnt), tzh.tzh_ttisstdcnt); diff --git a/ci/official/containers/ml_build_arm64/builder.packages.txt b/ci/official/containers/ml_build_arm64/builder.packages.txt new file mode 100644 index 00000000000..2be317ca4e2 --- /dev/null +++ b/ci/official/containers/ml_build_arm64/builder.packages.txt @@ -0,0 +1,47 @@ +# Packages needed to build devtoolset +file +flex +make +build-essential +patch +rpm2cpio +unar +wget +xz-utils +cpio +gawk +texinfo +gettext + +# Other build-related tools +software-properties-common +apt-transport-https +autoconf +automake +ca-certificates +pkg-config +libcurl3-dev +libcurl4-openssl-dev +libfreetype6-dev +libhdf5-serial-dev +libomp-18-dev +libssl-dev +libtool +libssl-dev +libxml2-dev +libxslt1-dev +libzmq3-dev +llvm-18 +clang-18 +clang-tidy-18 +lld-18 +clang-format-12 +curl +git +parallel +sudo +swig +unzip +zip +openjdk-21-jdk +vim diff --git a/ci/official/containers/ml_build_arm64/devel.bashrc b/ci/official/containers/ml_build_arm64/devel.bashrc new file mode 100644 index 00000000000..755d48783b1 --- /dev/null +++ b/ci/official/containers/ml_build_arm64/devel.bashrc @@ -0,0 +1,26 @@ +# Copyright 2021 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============================================================================== + +# Do not print anything if this is not being used interactively +[ -z "$PS1" ] && return + +# Set up attractive prompt +export PS1="\[\e[31m\]tf-docker\[\e[m\] \[\e[33m\]\w\[\e[m\] > " +export TERM=xterm-256color +alias grep="grep --color=auto" +alias ls="ls --color=auto" +# Fix nvidia-docker +ldconfig diff --git a/ci/official/containers/ml_build_arm64/ld.so.conf b/ci/official/containers/ml_build_arm64/ld.so.conf new file mode 100644 index 00000000000..e2aa028720e --- /dev/null +++ b/ci/official/containers/ml_build_arm64/ld.so.conf @@ -0,0 +1,18 @@ +# Copyright 2023 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +# +# Builds a devtoolset cross-compiler targeting manylinux2014 (glibc 2.17 / libstdc++ 4.8). + +/lib64 diff --git a/ci/official/containers/ml_build_arm64/requirements.txt b/ci/official/containers/ml_build_arm64/requirements.txt new file mode 100644 index 00000000000..37022aa5a9c --- /dev/null +++ b/ci/official/containers/ml_build_arm64/requirements.txt @@ -0,0 +1,4 @@ +portpicker==1.6.0 +# For wheel verification, and uploading +auditwheel ~= 6.1.0 +twine ~= 5.1.1 diff --git a/ci/official/containers/ml_build_arm64/setup.packages.sh b/ci/official/containers/ml_build_arm64/setup.packages.sh new file mode 100755 index 00000000000..347b853e349 --- /dev/null +++ b/ci/official/containers/ml_build_arm64/setup.packages.sh @@ -0,0 +1,28 @@ +#!/usr/bin/env bash +# +# Copyright 2022 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +# +# setup.packages.sh: Given a list of Ubuntu packages, install them and clean up. +# Usage: setup.packages.sh +set -e + +# Prevent apt install tzinfo from asking our location (assumes UTC) +export DEBIAN_FRONTEND=noninteractive + +apt-get update +# Remove commented lines and blank lines +apt-get install -y --no-install-recommends $(sed -e '/^\s*#.*$/d' -e '/^\s*$/d' "$1" | sort -u) +rm -rf /var/lib/apt/lists/* \ No newline at end of file diff --git a/ci/official/containers/ml_build_arm64/setup.python.sh b/ci/official/containers/ml_build_arm64/setup.python.sh new file mode 100755 index 00000000000..3f3da75e9cb --- /dev/null +++ b/ci/official/containers/ml_build_arm64/setup.python.sh @@ -0,0 +1,67 @@ +#!/usr/bin/env bash +# +# Copyright 2022 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +# +# setup.python.sh: Install a specific Python version and packages for it. +# Usage: setup.python.sh +set -xe + +source ~/.bashrc +VERSION=$1 +REQUIREMENTS=$2 + +add-apt-repository ppa:deadsnakes/ppa +# Install Python packages for this container's version +if [[ ${VERSION} == "python3.13" ]]; then + cat >pythons.txt <pythons.txt < + +# Sets up custom apt sources for our TF images. + +# Prevent apt install tzinfo from asking our location (assumes UTC) +export DEBIAN_FRONTEND=noninteractive + +# Set up shared custom sources +apt-get update +apt-get install -y gnupg ca-certificates + +# Deadsnakes: https://launchpad.net/~deadsnakes/+archive/ubuntu/ppa +apt-key adv --keyserver keyserver.ubuntu.com --recv-keys F23C5A6CF475977595C89F51BA6932366A755776 + +# LLVM/Clang: https://apt.llvm.org/ +apt-key adv --fetch-keys https://apt.llvm.org/llvm-snapshot.gpg.key + +# Set up custom sources +cat >/etc/apt/sources.list.d/custom.list <