Loading Dockerfile +1 −0 Original line number Diff line number Diff line Loading @@ -6,6 +6,7 @@ COPY bootstrap-stage.bash /stage/scripts/bootstrap-stage COPY collect-binaries.bash /stage/scripts/collect-binaries COPY config-nsswitch.bash /stage/scripts/config-nsswitch COPY stage-useradd.bash /stage/scripts/stage-useradd COPY translate-platform.bash /stage/scripts/translate-platform RUN /stage/scripts/collect-binaries /bin/bash FROM scratch Loading translate-platform.bash 0 → 100755 +224 −0 Original line number Diff line number Diff line #!/bin/bash # Copyright (c) 2022 Dom Sekotill <dom.sekotill@kodo.org.uk> # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in all # copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. set -eu -o pipefail shopt -s nullglob localvar_inherit localvar_unset USAGE="Usage: $0 [-h] [--libc=LIBC] OUTPUT-TYPE DOCKER-PLATFORM Arguments: OUTPUT-TYPE The type of output to convert to. See \"Output Types\" below. DOCKER-PLATFORM A string used by Docker to identify a platform. See \"Docker Platforms\". Options: --help -h Display this message and exit --libc=LIBC Override or provide the name of the libc implementation Output Types: autoconf: Prints a value suitable for passing to the --build, --host and --target options of ./configures scripts generated by autoconf. debian: Prints the value used for identifying cross-compiler tools' target platform. Intended to be suitable for Debian package names. Docker Platforms: The Docker platform argument is a string used by Docker to identify kernel and machine architecture combinations. Commonly it is obtained from one of the BUILDPLATFORM or TARGETPLATFORM automatic build arguments. It is in the format \"kernel/arch\" or \"kernel/arch/variant\", for example \"linux/arm64\". Libc: Not all kernels have alternative libc implementations; those that have only one do not require the --libc option. If not supplied (but required), a value will be guessed that matches the host environment if the kernel in DOCKER-PLATFORM matches the current platform. Otherwise the command fails. " declare -r CONFIG_GUESS_URL="https://git.savannah.gnu.org/cgit/config.git/plain/config.guess" declare -r CONFIG_SUB_URL="https://git.savannah.gnu.org/cgit/config.git/plain/config.sub" has() { type 1>&2 2>/dev/null "$1"; } die() { [[ ${code:=$?} -gt 0 ]] || code=1; echo >&2 "Error: $*"; exit $code; } badarg() { echo >&2 "$USAGE"; code=2 die "$@"; } get_temp_dir() { if ! [[ -v TEMP_DIR ]]; then TEMP_DIR=$(mktemp -d) cleanup rm -r "$TEMP_DIR" fi echo "$TEMP_DIR" } # Run the config.guess script from GNU # # This script determines the right autoconf host value for the current host config_guess() ( dl_script CONFIG_GUESS config.guess "$CONFIG_GUESS_URL" # Exec with bash instead of /bin/sh to ensure $BASH_ENV is sourced (used by # the distributed Docker image). Disable errexit and nounset as the script # does not explicitly set or unset them, so they need to be the default # (unset). set +eu exec $BASH $CONFIG_GUESS "$@" ) # Run the config.sub script from GNU # # This script validates and canonicalises autoconf host values config_sub() ( dl_script CONFIG_SUB config.sub "$CONFIG_SUB_URL" # Exec with bash instead of /bin/sh to ensure $BASH_ENV is sourced (used by # the distributed Docker image). Disable errexit and nounset as the script # does not explicitly set or unset them, so they need to be the default # (unset). set +eu exec $BASH $CONFIG_SUB "$@" ) # Set a variable to the (cached) path to a downloaded script # # Usage: # dl_script VAR_NAME NAME URL # # Arguments: # VAR_NAME The name of a variable where the path is stored # NAME The base name of the script # URL The download location of the script # # If the script is downloaded the path to the script is stored in VAR_NAME for # caching. If VAR_NAME exists and is set to the path of an executable script it # will be returned immediately. Setting VAR_NAME in the environment can be # a way for users to override with a particular copy of the script. dl_script() { declare -n path=$1 local name=$2 url=$3 trap "[[ -z \"\$$1\" ]] && die 'failed to get $name'" RETURN [[ -v path ]] && [[ -x "$path" ]] && return if ! [[ -f "${path:=$(get_temp_dir)/$name}" ]]; then if has wget; then wget "$url" -O "$path" elif has curl; then curl -LsS "$url" > "$path" else die "cannot download $name; please install curl or wget" fi fi if ! [[ -x "$path" ]]; then chmod +x "$path" fi } # Attempt to guess and echo a libc variant from a kernel name # # For OSes with no alternatives for kernels and C runtimes nothing will be # echoed as no value is needed. If the OS has alternatives for libc and the # kernel matches the host's kernel, the host's libc variant will be echoed. # Otherwise the function exits with return code 1. guess_libc() { [[ $1 =~ .*(linux|bsd).* ]] || return 0 local kernel=$1 local host=$(config_guess) local host_os=${host#*-*-} local host_kernel=${host_os%-*} local host_libc=${host_os#$host_kernel}; host_libc=${host_libc#-} [[ $host_kernel =~ ^$kernel ]] || return 1 LIBC=$host_libc echo "$LIBC" } parse_args() { until test $# -eq 0; do case $1 in -h|--help) echo >&2 "$USAGE"; exit 0 ;; --libc) LIBC=$2; shift ;; --*=*) set -- ${1%%=*} ${1#*=} "${@:2}" ;; -*) badarg "unknown option: $1" ;; *) case '' in "${OUTPUT_TYPE-}") OUTPUT_TYPE=$1 ;; "${DOCKER_PLATFORM-}") DOCKER_PLATFORM=$1 ;; esac ;; esac shift done [[ -v OUTPUT_TYPE ]] || badarg "missing OUTPUT-TYPE" [[ -v DOCKER_PLATFORM ]] || badarg "missing DOCKER-PLATFORM" [[ $DOCKER_PLATFORM =~ ^[^/]+/[^/]+(/[^/]+)?$ ]] || badarg "docker platform must be formatted as '<kernel>/<arch>'" case $OUTPUT_TYPE in autoconf) CMD=output_autoconf ;; debian) CMD=output_debian ;; *) badarg "unknown output type: $OUTPUT_TYPE" esac DOCKER_KERNEL=${DOCKER_PLATFORM%%/*} DOCKER_ARCH=${DOCKER_PLATFORM#*/} } output_autoconf() { local LIBC if [[ ! -v LIBC ]]; then LIBC=$(guess_libc $DOCKER_KERNEL) || die "cannot guess a suitable libc value, please use --libc" fi # TODO: this is a very naïve munge of DOCKER_ARCH, works for arm/v{6,7} config_sub "${DOCKER_ARCH/\//}-$DOCKER_KERNEL${LIBC:+-$LIBC}" } output_debian() { local conf=$(output_autoconf) local arch=${conf%%-*} local os=${conf#$arch-*-} case $arch in # Are these values universally correct? # Based on https://www.debian.org/ports/arm/ armv6) arch=armel ;; armv7) arch=armhf ;; esac echo "${arch//_/-}-${os}" } if ! has cleanup; then cleanup() { declare -ga CLEANUP CLEANUP+=( "$(printf "%q " "$@")" ) } trap 'for cmd in "${CLEANUP[@]}"; do eval "$cmd" || true; done' EXIT fi if [[ ! -v SKIP_INIT ]]; then # Pre-download scripts if required, set path variables in the parent shell dl_script CONFIG_GUESS config.guess "$CONFIG_GUESS_URL" dl_script CONFIG_SUB config.sub "$CONFIG_SUB_URL" fi if [[ $0 = ${BASH_SOURCE[0]} ]]; then parse_args "$@" $CMD fi Loading
Dockerfile +1 −0 Original line number Diff line number Diff line Loading @@ -6,6 +6,7 @@ COPY bootstrap-stage.bash /stage/scripts/bootstrap-stage COPY collect-binaries.bash /stage/scripts/collect-binaries COPY config-nsswitch.bash /stage/scripts/config-nsswitch COPY stage-useradd.bash /stage/scripts/stage-useradd COPY translate-platform.bash /stage/scripts/translate-platform RUN /stage/scripts/collect-binaries /bin/bash FROM scratch Loading
translate-platform.bash 0 → 100755 +224 −0 Original line number Diff line number Diff line #!/bin/bash # Copyright (c) 2022 Dom Sekotill <dom.sekotill@kodo.org.uk> # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in all # copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. set -eu -o pipefail shopt -s nullglob localvar_inherit localvar_unset USAGE="Usage: $0 [-h] [--libc=LIBC] OUTPUT-TYPE DOCKER-PLATFORM Arguments: OUTPUT-TYPE The type of output to convert to. See \"Output Types\" below. DOCKER-PLATFORM A string used by Docker to identify a platform. See \"Docker Platforms\". Options: --help -h Display this message and exit --libc=LIBC Override or provide the name of the libc implementation Output Types: autoconf: Prints a value suitable for passing to the --build, --host and --target options of ./configures scripts generated by autoconf. debian: Prints the value used for identifying cross-compiler tools' target platform. Intended to be suitable for Debian package names. Docker Platforms: The Docker platform argument is a string used by Docker to identify kernel and machine architecture combinations. Commonly it is obtained from one of the BUILDPLATFORM or TARGETPLATFORM automatic build arguments. It is in the format \"kernel/arch\" or \"kernel/arch/variant\", for example \"linux/arm64\". Libc: Not all kernels have alternative libc implementations; those that have only one do not require the --libc option. If not supplied (but required), a value will be guessed that matches the host environment if the kernel in DOCKER-PLATFORM matches the current platform. Otherwise the command fails. " declare -r CONFIG_GUESS_URL="https://git.savannah.gnu.org/cgit/config.git/plain/config.guess" declare -r CONFIG_SUB_URL="https://git.savannah.gnu.org/cgit/config.git/plain/config.sub" has() { type 1>&2 2>/dev/null "$1"; } die() { [[ ${code:=$?} -gt 0 ]] || code=1; echo >&2 "Error: $*"; exit $code; } badarg() { echo >&2 "$USAGE"; code=2 die "$@"; } get_temp_dir() { if ! [[ -v TEMP_DIR ]]; then TEMP_DIR=$(mktemp -d) cleanup rm -r "$TEMP_DIR" fi echo "$TEMP_DIR" } # Run the config.guess script from GNU # # This script determines the right autoconf host value for the current host config_guess() ( dl_script CONFIG_GUESS config.guess "$CONFIG_GUESS_URL" # Exec with bash instead of /bin/sh to ensure $BASH_ENV is sourced (used by # the distributed Docker image). Disable errexit and nounset as the script # does not explicitly set or unset them, so they need to be the default # (unset). set +eu exec $BASH $CONFIG_GUESS "$@" ) # Run the config.sub script from GNU # # This script validates and canonicalises autoconf host values config_sub() ( dl_script CONFIG_SUB config.sub "$CONFIG_SUB_URL" # Exec with bash instead of /bin/sh to ensure $BASH_ENV is sourced (used by # the distributed Docker image). Disable errexit and nounset as the script # does not explicitly set or unset them, so they need to be the default # (unset). set +eu exec $BASH $CONFIG_SUB "$@" ) # Set a variable to the (cached) path to a downloaded script # # Usage: # dl_script VAR_NAME NAME URL # # Arguments: # VAR_NAME The name of a variable where the path is stored # NAME The base name of the script # URL The download location of the script # # If the script is downloaded the path to the script is stored in VAR_NAME for # caching. If VAR_NAME exists and is set to the path of an executable script it # will be returned immediately. Setting VAR_NAME in the environment can be # a way for users to override with a particular copy of the script. dl_script() { declare -n path=$1 local name=$2 url=$3 trap "[[ -z \"\$$1\" ]] && die 'failed to get $name'" RETURN [[ -v path ]] && [[ -x "$path" ]] && return if ! [[ -f "${path:=$(get_temp_dir)/$name}" ]]; then if has wget; then wget "$url" -O "$path" elif has curl; then curl -LsS "$url" > "$path" else die "cannot download $name; please install curl or wget" fi fi if ! [[ -x "$path" ]]; then chmod +x "$path" fi } # Attempt to guess and echo a libc variant from a kernel name # # For OSes with no alternatives for kernels and C runtimes nothing will be # echoed as no value is needed. If the OS has alternatives for libc and the # kernel matches the host's kernel, the host's libc variant will be echoed. # Otherwise the function exits with return code 1. guess_libc() { [[ $1 =~ .*(linux|bsd).* ]] || return 0 local kernel=$1 local host=$(config_guess) local host_os=${host#*-*-} local host_kernel=${host_os%-*} local host_libc=${host_os#$host_kernel}; host_libc=${host_libc#-} [[ $host_kernel =~ ^$kernel ]] || return 1 LIBC=$host_libc echo "$LIBC" } parse_args() { until test $# -eq 0; do case $1 in -h|--help) echo >&2 "$USAGE"; exit 0 ;; --libc) LIBC=$2; shift ;; --*=*) set -- ${1%%=*} ${1#*=} "${@:2}" ;; -*) badarg "unknown option: $1" ;; *) case '' in "${OUTPUT_TYPE-}") OUTPUT_TYPE=$1 ;; "${DOCKER_PLATFORM-}") DOCKER_PLATFORM=$1 ;; esac ;; esac shift done [[ -v OUTPUT_TYPE ]] || badarg "missing OUTPUT-TYPE" [[ -v DOCKER_PLATFORM ]] || badarg "missing DOCKER-PLATFORM" [[ $DOCKER_PLATFORM =~ ^[^/]+/[^/]+(/[^/]+)?$ ]] || badarg "docker platform must be formatted as '<kernel>/<arch>'" case $OUTPUT_TYPE in autoconf) CMD=output_autoconf ;; debian) CMD=output_debian ;; *) badarg "unknown output type: $OUTPUT_TYPE" esac DOCKER_KERNEL=${DOCKER_PLATFORM%%/*} DOCKER_ARCH=${DOCKER_PLATFORM#*/} } output_autoconf() { local LIBC if [[ ! -v LIBC ]]; then LIBC=$(guess_libc $DOCKER_KERNEL) || die "cannot guess a suitable libc value, please use --libc" fi # TODO: this is a very naïve munge of DOCKER_ARCH, works for arm/v{6,7} config_sub "${DOCKER_ARCH/\//}-$DOCKER_KERNEL${LIBC:+-$LIBC}" } output_debian() { local conf=$(output_autoconf) local arch=${conf%%-*} local os=${conf#$arch-*-} case $arch in # Are these values universally correct? # Based on https://www.debian.org/ports/arm/ armv6) arch=armel ;; armv7) arch=armhf ;; esac echo "${arch//_/-}-${os}" } if ! has cleanup; then cleanup() { declare -ga CLEANUP CLEANUP+=( "$(printf "%q " "$@")" ) } trap 'for cmd in "${CLEANUP[@]}"; do eval "$cmd" || true; done' EXIT fi if [[ ! -v SKIP_INIT ]]; then # Pre-download scripts if required, set path variables in the parent shell dl_script CONFIG_GUESS config.guess "$CONFIG_GUESS_URL" dl_script CONFIG_SUB config.sub "$CONFIG_SUB_URL" fi if [[ $0 = ${BASH_SOURCE[0]} ]]; then parse_args "$@" $CMD fi