HandBrake/scripts/mac-toolchain-build

708 lines
28 KiB
Bash
Executable File

#!/usr/bin/env bash
# mac-toolchain-build - download and build common macOS toolchain components
#
# Copyright 2024 Bradley Sepos
# Released under the MIT License. See LICENSE for details.
# https://github.com/bradleysepos/mac-toolchain-build
# checks for required external tools
function check_dependencies { # check_dependencies $DEP1 $DEP2 ...
local DEPS DEPS_EACH DEPS_MULTI ERRORS FOUND
DEPS=("${@}");
ERRORS=()
for DEPS_EACH in ${DEPS[@]}; do
DEPS_MULTI=(${DEPS_EACH//|/ })
FOUND=false
for DEP in ${DEPS_MULTI[@]}; do
if echo "${DEP}" | grep '/' >/dev/null 2>&1 && [[ -x "${DEP}" ]]; then
FOUND=true
break
elif hash "${DEP}" >/dev/null 2>&1; then
FOUND=true
break
fi
done
if [[ "${FOUND}" == false ]]; then
ERRORS+=("$(echo ${DEPS_MULTI[@]} | sed 's/ /|/')")
fi
done
if [[ "${#ERRORS[@]}" -ne 0 ]]; then
echo "dependencies: ${DEPS[@]}"
echo "unable to find command(s): ${ERRORS[*]}" >&2
return 1
fi
}
# checks version is greater than or equal to target version
function check_version_gte { # check_version_gte $VERSION $TARGET
if [[ "${1:-}" == "${2:-}" ]]; then
return 0
fi
local VERSION TARGET INDEX
IFS='.' read -r -a VERSION <<< "${1:-}"
IFS='.' read -r -a TARGET <<< "${2:-}"
for ((INDEX=${#VERSION[@]}; INDEX<${#TARGET[@]}; INDEX++)); do
VERSION[INDEX]=0
done
for ((INDEX=0; INDEX<${#VERSION[@]}; INDEX++))
do
if [[ -z ${TARGET[INDEX]} ]]; then
TARGET[INDEX]=0
fi
if ((10#${VERSION[INDEX]} > 10#${TARGET[INDEX]})); then
return 0
fi
if ((10#${VERSION[INDEX]} < 10#${TARGET[INDEX]})); then
return 1
fi
done
return 0
}
# downloads from one or more urls
function download_url { # download_url $VERBOSE $FILE $URLS
local VERBOSE FILE URLS I FAILED
OPTIND=1
VERBOSE="${1}"
FILE="${2}"
shift 2
URLS=("${@}")
if [[ "${#URLS[@]}" -eq 0 ]] || [[ "${URLS[0]:-}" == "" ]]; then
echo "url not specified for download" >&2
return 1
fi
if [[ "${FILE:-}" == "" ]]; then
echo "output path not specified for download: ${FILE}" >&2
return 1
fi
FAILED=()
for I in "${!URLS[@]}"; do
if ! curl --head -Lf --connect-timeout 30 "${URLS[I]}" >/dev/null 2>&1; then
FAILED+=("${URLS[I]}")
if [[ "$(( ${I} + 1 ))" -lt "${#URLS[@]}" ]]; then
continue
else
echo "unable to download from urls: ${FAILED[@]}" >&2
echo "unable to download to file: ${FILE}" >&2
return 1
fi
fi
if ! touch "${FILE}" >/dev/null 2>&1; then
echo "unable to create path: ${FILE}" >&2
return 1
fi
if [[ "${VERBOSE:-}" == true ]]; then
echo "curl -Lf --connect-timeout 30 \"${URLS[I]}\" -o \"${FILE}\""
fi
if ! curl -Lf --connect-timeout 30 "${URLS[I]}" -o "${FILE}" >/dev/null 2>&1; then
FAILED+=("${URLS[I]}")
if [[ "$(( ${I} + 1 ))" -lt "${#URLS[@]}" ]]; then
continue
else
echo "unable to download from urls: ${FAILED[@]}" >&2
echo "unable to download to file: ${FILE}" >&2
return 1
fi
fi
return 0
done
}
# prints continuous output to avoid timeouts on build systems like Travis
function display_progress {
local str=""
while [ "$(ps a | awk '{print $1}' | grep ${1})" ]; do
printf "%c" "$str"
sleep 5
str="."
done
}
# kills child processes
function die_gracefully {
trap - EXIT INT
trap ":" INT # prevent recursion due to spamming ctrl-c
echo ""
echo "logs and temporary files may exist at ${TMPDIR%/}/mac-toolchain-build-*" >&2
trap - TERM && kill -- -$$
}
# tests whether a string is an exact match for an array item
function in_array { # in_array needle haystack[@]
local e
for e in "${@:2}"; do
[[ "${e}" == "${1}" ]] && return 0
done
return 1
}
# builds toolchain components
function mac_toolchain_build {
set -o pipefail
# package names
local M4_NAME AUTOCONF_NAME AUTOMAKE_NAME CMAKE_NAME LIBTOOL_NAME MESON_NAME NASM_NAME NINJA_NAME OPENSSL_NAME PKGCONFIG_NAME NAMES
M4_NAME="m4"
AUTOCONF_NAME="autoconf"
AUTOMAKE_NAME="automake"
CMAKE_NAME="cmake"
LIBTOOL_NAME="libtool"
MESON_NAME="meson"
NASM_NAME="nasm"
NINJA_NAME="ninja"
OPENSSL_NAME="openssl"
PKGCONFIG_NAME="pkg-config"
NAMES=("${M4_NAME}" "${AUTOCONF_NAME}" "${AUTOMAKE_NAME}" "${CMAKE_NAME}" "${LIBTOOL_NAME}" "${MESON_NAME}" "${NASM_NAME}" "${NINJA_NAME}" "${OPENSSL_NAME}" "${PKGCONFIG_NAME}")
# versions
local M4_VER AUTOCONF_VER AUTOMAKE_VER CMAKE_VER LIBTOOL_VER MESON_VER NASM_VER NINJA_VER OPENSSL_VER PKGCONFIG_VER VERSIONS
M4_VER="1.4.20"
AUTOCONF_VER="2.72"
AUTOMAKE_VER="1.18"
CMAKE_VER="4.0.3"
LIBTOOL_VER="2.5.4"
MESON_VER="1.8.2"
NASM_VER="2.16.03"
NINJA_VER="1.13.1"
OPENSSL_VER="3.5.1"
PKGCONFIG_VER="0.29.2"
VERSIONS=("${M4_VER}" "${AUTOCONF_VER}" "${AUTOMAKE_VER}" "${CMAKE_VER}" "${LIBTOOL_VER}" "${MESON_VER}" "${NASM_VER}" "${NINJA_VER}" "${OPENSSL_VER}" "${PKGCONFIG_VER}")
# filenames
local M4_PKG AUTOCONF_PKG AUTOMAKE_PKG CMAKE_PKG LIBTOOL_PKG MESON_PKG NASM_PKG NINJA_PKG OPENSSL_PKG PKGCONFIG_PKG PKGS
M4_PKG="m4-${M4_VER}.tar.bz2"
AUTOCONF_PKG="autoconf-${AUTOCONF_VER}.tar.gz"
AUTOMAKE_PKG="automake-${AUTOMAKE_VER}.tar.gz"
CMAKE_PKG="cmake-${CMAKE_VER}.tar.gz"
LIBTOOL_PKG="libtool-${LIBTOOL_VER}.tar.gz"
MESON_PKG="meson-${MESON_VER}.tar.gz"
NASM_PKG="nasm-${NASM_VER}.tar.bz2"
NINJA_PKG="ninja-${NINJA_VER}.tar.gz"
OPENSSL_PKG="openssl-openssl-${OPENSSL_VER}.tar.gz"
PKGCONFIG_PKG="pkg-config-${PKGCONFIG_VER}.tar.gz"
PKGS=("${M4_PKG}" "${AUTOCONF_PKG}" "${AUTOMAKE_PKG}" "${CMAKE_PKG}" "${LIBTOOL_PKG}" "${MESON_PKG}" "${NASM_PKG}" "${NINJA_PKG}" "${OPENSSL_PKG}" "${PKGCONFIG_PKG}")
# urls
local M4_URLS AUTOCONF_URLS AUTOMAKE_URLS CMAKE_URLS LIBTOOL_URLS MESON_URLS NASM_URLS NINJA_URLS OPENSSL_URLS PKGCONFIG_URLS URLS_VARNAMES
M4_URLS=("https://ftp.gnu.org/gnu/m4/m4-${M4_VER}.tar.bz2")
AUTOCONF_URLS=("https://ftp.gnu.org/gnu/autoconf/autoconf-${AUTOCONF_VER}.tar.gz")
AUTOMAKE_URLS=("https://ftp.gnu.org/gnu/automake/automake-${AUTOMAKE_VER}.tar.gz")
CMAKE_URLS=("https://cmake.org/files/v${CMAKE_VER%.*}/cmake-${CMAKE_VER}.tar.gz")
LIBTOOL_URLS=("https://ftp.gnu.org/gnu/libtool/libtool-${LIBTOOL_VER}.tar.gz")
MESON_URLS=("https://github.com/mesonbuild/meson/archive/${MESON_VER}.tar.gz")
NASM_URLS=("https://www.nasm.us/pub/nasm/releasebuilds/${NASM_VER}/nasm-${NASM_VER}.tar.bz2")
NINJA_URLS=("https://github.com/ninja-build/ninja/archive/v${NINJA_VER}.tar.gz")
OPENSSL_URLS=("https://github.com/openssl/openssl/archive/openssl-${OPENSSL_VER}.tar.gz")
PKGCONFIG_URLS=("https://pkg-config.freedesktop.org/releases/pkg-config-${PKGCONFIG_VER}.tar.gz")
URLS_VARNAMES=('M4_URLS' 'AUTOCONF_URLS' 'AUTOMAKE_URLS' 'CMAKE_URLS' 'LIBTOOL_URLS' 'MESON_URLS' 'NASM_URLS' 'NINJA_URLS' 'OPENSSL_URLS' 'PKGCONFIG_URLS')
# checksums
local M4_SHA256 AUTOCONF_SHA256 AUTOMAKE_SHA256 CMAKE_SHA256 LIBTOOL_SHA256 MESON_SHA256 NASM_SHA256 NINJA_SHA256 OPENSSL_SHA256 PKGCONFIG_SHA256 CHECKSUMS
M4_SHA256="ac6989ee5d2aed81739780630cc2ce097e2a6546feb96a4a54db37d46a1452e4"
AUTOCONF_SHA256="afb181a76e1ee72832f6581c0eddf8df032b83e2e0239ef79ebedc4467d92d6e"
AUTOMAKE_SHA256="af6043a5d4b3beef0c48161f4a6936259321cd101a34c1ab0768328515626c8a"
CMAKE_SHA256="8d3537b7b7732660ea247398f166be892fe6131d63cc291944b45b91279f3ffb"
LIBTOOL_SHA256="da8ebb2ce4dcf46b90098daf962cffa68f4b4f62ea60f798d0ef12929ede6adf"
MESON_SHA256="6b878fb0f6f0318cbd54e13539f89a1a8305791668e8e93ffd59d82722888dac"
NASM_SHA256="bef3de159bcd61adf98bb7cc87ee9046e944644ad76b7633f18ab063edb29e57"
NINJA_SHA256="f0055ad0369bf2e372955ba55128d000cfcc21777057806015b45e4accbebf23"
OPENSSL_SHA256="24e3a8a1e832e29255b55d06fcc473b9f56e60555b504bf4422ca64a0d0c1426"
PKGCONFIG_SHA256="6fc69c01688c9458a57eb9a1664c9aba372ccda420a02bf4429fe610e7e7d591"
CHECKSUMS=("${M4_SHA256}" "${AUTOCONF_SHA256}" "${AUTOMAKE_SHA256}" "${CMAKE_SHA256}" "${LIBTOOL_SHA256}" "${MESON_SHA256}" "${NASM_SHA256}" "${NINJA_SHA256}" "${OPENSSL_SHA256}" "${PKGCONFIG_SHA256}")
# internal vars
local NAME VERSION SELF SELF_NAME HELP SUDO TOTAL
NAME="mac-toolchain-build"
VERSION="2.13.0"
SELF="${BASH_SOURCE[0]}"
SELF_NAME=$(basename "${SELF}")
HELP="\
${NAME} ${VERSION}
usage: ${SELF_NAME} [-h | --help]
${SELF_NAME} [-l | --list]
${SELF_NAME} [-v | --version]
${SELF_NAME} [-f | --force] [-j # | --jobs #] [install-dir]
where:
-h, --help
display this help text
-l, --list
display components list
-v, --version
display version information
-f, --force
force installation even if adequate versions of tools are installed
-j, --jobs
number of concurrent build jobs to run
default: 0 (automatic)
default install-dir: /usr/local"
SUDO=
TOTAL="${#NAMES[@]}"
# args
local FORCE JOBS LIST OPTIND OPTSPEC OPTARRAY PREFIX
FORCE=false
JOBS=0
LIST=false
OPTIND=1
OPTSPEC=":-:hlvfj:"
OPTARRAY=('-h' '--help' '-l' '--list' '-v' '--version' '-f' '--force' '-j' '--jobs') # all short and long options
while getopts "${OPTSPEC}" OPT; do
case "${OPT}" in
-)
case "${OPTARG}" in
help)
# Print help and exit
echo -e "${HELP}"
return 0
;;
help=*)
# Print help and exit
echo -e "${HELP}"
return 0
;;
list)
# List components
LIST=true
;;
list=*)
# List components
LIST=true
;;
version)
# Print version and exit
echo -e "${NAME} ${VERSION}"
return 0
;;
version=*)
# Print version and exit
echo -e "${NAME} ${VERSION}"
return 0
;;
force)
# Force installation
FORCE=true
;;
force=*)
# Option with prohibited value
echo "Option --${OPTARG%%=*} takes no value" >&2
echo -e "${HELP}"
return 1
;;
jobs)
# Number of jobs
if [[ -z ${!OPTIND+isset} ]] || in_array "${!OPTIND}" "${OPTARRAY[@]}"; then
# Option without required argument
echo "Option --${OPTARG} requires a value" >&2
echo -e "${HELP}"
return 1
fi
JOBS="${!OPTIND}"
if [[ ! "${JOBS}" =~ ^[0-9]*$ ]]; then
echo "Option --${OPTARG} requires a numeric value" >&2
echo -e "${HELP}"
return 1
fi
OPTIND=$((OPTIND + 1))
;;
jobs=*)
# Number of jobs
JOBS="${OPTARG#*=}"
if [[ ! "${JOBS}" =~ ^[0-9]*$ ]]; then
echo "Option --${OPTARG} requires a numeric value" >&2
echo -e "${HELP}"
return 1
fi
;;
*)
if [[ "${OPTERR}" == 1 ]]; then
# Invalid option specified
echo "Invalid option: --${OPTARG}" >&2
echo -e "${HELP}"
return 1
fi
;;
esac
;;
h)
# Print help and exit
echo -e "${HELP}"
return 0
;;
l)
# List components
LIST=true
;;
v)
# Print version and exit
echo "${NAME} ${VERSION}"
return 0
;;
f)
# Force installation
FORCE=true
;;
j)
# Number of jobs
JOBS="${OPTARG}"
if [[ ! "${JOBS}" =~ ^[0-9]*$ ]]; then
echo "Option -${OPT} requires a numeric value" >&2
echo -e "${HELP}"
return 1
fi
;;
:)
# Option without required value
echo "Option -${OPTARG} requires a value" >&2
echo -e "${HELP}"
return 1
;;
\?)
# Invalid option specified
echo "Invalid option: -${OPTARG}" >&2
echo -e "${HELP}"
return 1
;;
esac
done
shift $((OPTIND - 1))
# host
local SYS_NAME CPU_COUNT
SYS_NAME=$(uname | awk '{ print tolower($0)}')
if [[ "${SYS_NAME}" == "darwin" ]]; then
CPU_COUNT=$(sysctl -n hw.activecpu 2>/dev/null)
fi
CPU_COUNT="${CPU_COUNT:-1}"
[[ "${JOBS}" -eq 0 ]] && JOBS="${CPU_COUNT}"
# list components
if [[ "${LIST}" == true ]]; then
local COMPONENTS COMPONENTS_TEMP
COMPONENTS_TEMP=()
for I in "${!NAMES[@]}"; do
COMPONENTS_TEMP+=("${NAMES[$I]} ${VERSIONS[$I]}")
done
OIFS="${IFS}"
IFS=$'\n'
COMPONENTS=($(sort <<< "${COMPONENTS_TEMP[*]}"))
IFS="${OIFS}"
echo "${NAME} ${VERSION}"
echo "Components:"
for I in "${!COMPONENTS[@]}"; do
echo " ${COMPONENTS[$I]}"
done
return 0
fi
# begin output
echo "${NAME} ${VERSION} (${JOBS} job$([[ ${JOBS} -gt 1 ]] && echo 's'))"
# mac only
if [[ "${SYS_NAME}" != "darwin" ]]; then
echo "macOS/Darwin required" >&2
return 1
fi
# dependencies
local DEPS
DEPS=("curl" "python3" "sed" "shasum|sha256sum")
check_dependencies "${DEPS[@]}" || return 1
# sha256 binary
local SHA256
if hash shasum >/dev/null 2>&1; then
SHA256="shasum -a 256"
elif hash sha256sum >/dev/null 2>&1; then
SHA256="sha256sum"
else
return 1
fi
# prefix
PREFIX="${1:-/usr/local}"
# check installed tool versions, skip if adequate
local INSTALLED_VERSIONS SKIP NOT_SKIPPED_TOTAL
INSTALLED_VERSIONS=()
SKIP=()
NOT_SKIPPED_TOTAL=0
for I in "${!NAMES[@]}"; do
INSTALLED_VERSIONS[$I]=$("${PREFIX}/bin/${NAMES[I]}" --version 2>&1 | head -n 1 | grep -Eo '[0-9]+\.[0-9]+(\.[0-9]+)?' 2>&1 | head -n 1)
if [[ "${FORCE}" == false ]] && check_version_gte "${INSTALLED_VERSIONS[I]}" "${VERSIONS[I]}"; then
SKIP[$I]=true
else
NOT_SKIPPED_TOTAL=$((NOT_SKIPPED_TOTAL+1))
SKIP[$I]=false
fi
done
# permissions
if [[ "${NOT_SKIPPED_TOTAL}" -gt 0 ]]; then
mkdir -p "${PREFIX}" >/dev/null 2>&1
if [[ ! -w "${PREFIX}" ]]; then
if ! sudo -n date >/dev/null 2>&1; then
echo "sudo is required to install files to ${PREFIX}"
[[ "${SUDO}" != "" ]] && ${SUDO} -v
fi
sudo mkdir -p "${PREFIX}" >/dev/null 2>&1
if sudo touch "${PREFIX}" >/dev/null 2>&1; then
SUDO=sudo
else
echo "Unable to write to directory: ${PREFIX}" >&2
return 1
fi
fi
fi
PREFIX=$(cd "${PREFIX}" && pwd -P)
# directory creation
local PKG_DIR SOURCE_DIR BUILD_DIR
PKG_DIR=$(mktemp -d "${TMPDIR:-/tmp/}mac-toolchain-build-XXXXXX")
if [[ ! -d "${PKG_DIR}" ]]; then
echo "unable to create directory: ${PKG_DIR}" >&2
return 1
fi
SOURCE_DIR="${PKG_DIR}"
BUILD_DIR="${PKG_DIR}"
# verify/fetch
local DOWNLOAD_VERBOSE COUNT I URLS_IREF URLS CHECKSUM
DOWNLOAD_VERBOSE=false
COUNT=0
for I in "${!PKGS[@]}"; do
if [[ "${SKIP[I]}" == true ]]; then
continue
fi
COUNT=$((COUNT+1))
printf "Downloading [%02i/%02i] %s " "${COUNT}" "${NOT_SKIPPED_TOTAL}" "${NAMES[I]} ${VERSIONS[I]}"
URLS_IREF="${URLS_VARNAMES[I]}[@]"
URLS="${!URLS_IREF}"
CHECKSUM=$(${SHA256} "${PKG_DIR}/${PKGS[I]}" 2>/dev/null | awk '{ print $1 }')
if [[ "${CHECKSUM}" != "${CHECKSUMS[I]}" ]] >/dev/null 2>&1; then
download_url "${DOWNLOAD_VERBOSE}" "${PKG_DIR}/${PKGS[I]}" ${URLS[@]} || return 1
fi
CHECKSUM=$(${SHA256} "${PKG_DIR}/${PKGS[I]}" 2>/dev/null | awk '{ print $1 }')
if [[ "${CHECKSUM}" != "${CHECKSUMS[I]}" ]]; then
echo "checksum mismatch for package: ${PKG_DIR}/${PKGS[I]}" >&2
echo "expected: ${CHECKSUMS[I]}" >&2
echo "actual: ${CHECKSUM}" >&2
return 1
fi
echo ""
done
# extract
COUNT=0
for I in "${!PKGS[@]}"; do
if [[ "${SKIP[I]}" == true ]]; then
continue
fi
COUNT=$((COUNT+1))
printf "Extracting [%02i/%02i] %s " "${COUNT}" "${NOT_SKIPPED_TOTAL}" "${PKGS[I]}"
if [[ -e "${SOURCE_DIR}/${NAMES[I]}" ]]; then
rm -rf "${SOURCE_DIR}/${NAMES[I]}"
fi
mkdir -p "${SOURCE_DIR}/${NAMES[I]}"
if ! tar -xf "${PKG_DIR}/${PKGS[I]}" -C "${SOURCE_DIR}/${NAMES[I]}" >/dev/null 2>&1; then
echo "unable to extract package: ${PKG_DIR}/${PKGS[I]}" >&2
return 1
fi
echo ""
done
# build
local INDEX
export PATH="${PREFIX}/bin${PATH:+:$PATH}"
# m4
INDEX=0
printf "Building [%02i/%02i] %s " "$((INDEX+1))" "${TOTAL}" "${NAMES[$INDEX]} ${VERSIONS[$INDEX]}"
if [[ "${SKIP[$INDEX]}" == true ]]; then
echo "(${INSTALLED_VERSIONS[$INDEX]} installed, skipping)"
else
[[ "${SUDO}" != "" ]] && ${SUDO} -v
touch "${BUILD_DIR}/${NAMES[$INDEX]}.log"
mkdir -pv "${BUILD_DIR}/${NAMES[$INDEX]}" > "${BUILD_DIR}/${NAMES[$INDEX]}.log" 2>&1 || return 1
cd "${BUILD_DIR}/${NAMES[$INDEX]}"
"${SOURCE_DIR}/${NAMES[$INDEX]}/${PKGS[$INDEX]%\.tar\.*}/configure" --prefix="${PREFIX}" >> "${BUILD_DIR}/${NAMES[$INDEX]}.log" 2>&1 || return 1
make -j "${JOBS}" >> "${BUILD_DIR}/${NAMES[$INDEX]}.log" 2>&1 || return 1
${SUDO} make install >> "${BUILD_DIR}/${NAMES[$INDEX]}.log" 2>&1 || return 1
echo ""
fi
# autoconf
INDEX=$((INDEX+1))
printf "Building [%02i/%02i] %s " "$((INDEX+1))" "${TOTAL}" "${NAMES[$INDEX]} ${VERSIONS[$INDEX]}"
if [[ "${SKIP[$INDEX]}" == true ]]; then
echo "(${INSTALLED_VERSIONS[$INDEX]} installed, skipping)"
else
[[ "${SUDO}" != "" ]] && ${SUDO} -v
touch "${BUILD_DIR}/${NAMES[$INDEX]}.log"
mkdir -pv "${BUILD_DIR}/${NAMES[$INDEX]}" > "${BUILD_DIR}/${NAMES[$INDEX]}.log" 2>&1 || return 1
cd "${BUILD_DIR}/${NAMES[$INDEX]}"
"${SOURCE_DIR}/${NAMES[$INDEX]}/${PKGS[$INDEX]%\.tar\.*}/configure" --prefix="${PREFIX}" >> "${BUILD_DIR}/${NAMES[$INDEX]}.log" 2>&1 || return 1
make -j "${JOBS}" >> "${BUILD_DIR}/${NAMES[$INDEX]}.log" 2>&1 || return 1
${SUDO} make install >> "${BUILD_DIR}/${NAMES[$INDEX]}.log" 2>&1 || return 1
echo ""
fi
# automake
INDEX=$((INDEX+1))
printf "Building [%02i/%02i] %s " "$((INDEX+1))" "${TOTAL}" "${NAMES[$INDEX]} ${VERSIONS[$INDEX]}"
if [[ "${SKIP[$INDEX]}" == true ]]; then
echo "(${INSTALLED_VERSIONS[$INDEX]} installed, skipping)"
else
[[ "${SUDO}" != "" ]] && ${SUDO} -v
touch "${BUILD_DIR}/${NAMES[$INDEX]}.log"
mkdir -pv "${BUILD_DIR}/${NAMES[$INDEX]}" > "${BUILD_DIR}/${NAMES[$INDEX]}.log" 2>&1 || return 1
cd "${BUILD_DIR}/${NAMES[$INDEX]}"
"${SOURCE_DIR}/${NAMES[$INDEX]}/${PKGS[$INDEX]%\.tar\.*}/configure" --prefix="${PREFIX}" >> "${BUILD_DIR}/${NAMES[$INDEX]}.log" 2>&1 || return 1
make -j "${JOBS}" >> "${BUILD_DIR}/${NAMES[$INDEX]}.log" 2>&1 || return 1
${SUDO} make install >> "${BUILD_DIR}/${NAMES[$INDEX]}.log" 2>&1 || return 1
echo ""
fi
# cmake
INDEX=$((INDEX+1))
printf "Building [%02i/%02i] %s " "$((INDEX+1))" "${TOTAL}" "${NAMES[$INDEX]} ${VERSIONS[$INDEX]}"
if [[ "${SKIP[$INDEX]}" == true ]]; then
echo "(${INSTALLED_VERSIONS[$INDEX]} installed, skipping)"
else
[[ "${SUDO}" != "" ]] && ${SUDO} -v
touch "${BUILD_DIR}/${NAMES[$INDEX]}.log"
mkdir -pv "${BUILD_DIR}/${NAMES[$INDEX]}" > "${BUILD_DIR}/${NAMES[$INDEX]}.log" 2>&1 || return 1
cd "${BUILD_DIR}/${NAMES[$INDEX]}"
"${SOURCE_DIR}/${NAMES[$INDEX]}/${PKGS[$INDEX]%\.tar\.*}/configure" --prefix="${PREFIX}" --no-qt-gui --system-curl >> "${BUILD_DIR}/${NAMES[$INDEX]}.log" 2>&1 || return 1
make -j "${JOBS}" >> "${BUILD_DIR}/${NAMES[$INDEX]}.log" 2>&1 || return 1
${SUDO} make install >> "${BUILD_DIR}/${NAMES[$INDEX]}.log" 2>&1 || return 1
echo ""
fi
# libtool
INDEX=$((INDEX+1))
printf "Building [%02i/%02i] %s " "$((INDEX+1))" "${TOTAL}" "${NAMES[$INDEX]} ${VERSIONS[$INDEX]}"
if [[ "${SKIP[$INDEX]}" == true ]]; then
echo "(${INSTALLED_VERSIONS[$INDEX]} installed, skipping)"
else
[[ "${SUDO}" != "" ]] && ${SUDO} -v
touch "${BUILD_DIR}/${NAMES[$INDEX]}.log"
mkdir -pv "${BUILD_DIR}/${NAMES[$INDEX]}" > "${BUILD_DIR}/${NAMES[$INDEX]}.log" 2>&1 || return 1
cd "${BUILD_DIR}/${NAMES[$INDEX]}"
"${SOURCE_DIR}/${NAMES[$INDEX]}/${PKGS[$INDEX]%\.tar\.*}/configure" --prefix="${PREFIX}" >> "${BUILD_DIR}/${NAMES[$INDEX]}.log" 2>&1 || return 1
make -j "${JOBS}" >> "${BUILD_DIR}/${NAMES[$INDEX]}.log" 2>&1 || return 1
${SUDO} make install >> "${BUILD_DIR}/${NAMES[$INDEX]}.log" 2>&1 || return 1
echo ""
fi
# meson
INDEX=$((INDEX+1))
printf "Building [%02i/%02i] %s " "$((INDEX+1))" "${TOTAL}" "${NAMES[$INDEX]} ${VERSIONS[$INDEX]}"
if [[ "${SKIP[$INDEX]}" == true ]]; then
echo "(${INSTALLED_VERSIONS[$INDEX]} installed globally, skipping)"
else
[[ "${SUDO}" != "" ]] && ${SUDO} -v
touch "${BUILD_DIR}/${NAMES[$INDEX]}.log"
mkdir -pv "${BUILD_DIR}/${NAMES[$INDEX]}" > "${BUILD_DIR}/${NAMES[$INDEX]}.log" 2>&1 || return 1
cd "${SOURCE_DIR}/${NAMES[$INDEX]}/${PKGS[$INDEX]%\.tar\.*}"
${SUDO} python3 setup.py --no-user-cfg install --root="${PREFIX}" --prefix=/ --install-scripts=/bin --install-lib=/bin --single-version-externally-managed --no-compile --force >> "${BUILD_DIR}/${NAMES[$INDEX]}.log" 2>&1 || return 1
${SUDO} sed -i.bak '1s:.*:#!/usr/bin/env python3:' "${PREFIX}/bin/${NAMES[$INDEX]}" >> "${BUILD_DIR}/${NAMES[$INDEX]}.log" 2>&1 || return 1
${SUDO} rm -f "${PREFIX}/bin/${NAMES[$INDEX]}.bak" >> "${BUILD_DIR}/${NAMES[$INDEX]}.log" 2>&1 || return 1
${SUDO} rm -rf "${PREFIX}/bin/${NAMES[$INDEX]}build/__pycache__" >> "${BUILD_DIR}/${NAMES[$INDEX]}.log" 2>&1 || return 1
${SUDO} rm -rf "${PREFIX}/bin/${NAMES[$INDEX]}-${VERSIONS[$INDEX]}.dist-info" 2>&1 || return 1
${SUDO} mv "${PREFIX}/bin/${NAMES[$INDEX]}-${VERSIONS[$INDEX]}"*.egg-info "${PREFIX}/bin/${NAMES[$INDEX]}-${VERSIONS[$INDEX]}.dist-info" >> "${BUILD_DIR}/${NAMES[$INDEX]}.log" 2>&1 || return 1
${SUDO} mv "${PREFIX}/bin/${NAMES[$INDEX]}-${VERSIONS[$INDEX]}.dist-info/PKG-INFO" "${PREFIX}/bin/${NAMES[$INDEX]}-${VERSIONS[$INDEX]}.dist-info/METADATA" >> "${BUILD_DIR}/${NAMES[$INDEX]}.log" 2>&1 || return 1
echo ""
fi
# nasm
INDEX=$((INDEX+1))
printf "Building [%02i/%02i] %s " "$((INDEX+1))" "${TOTAL}" "${NAMES[$INDEX]} ${VERSIONS[$INDEX]}"
if [[ "${SKIP[$INDEX]}" == true ]]; then
echo "(${INSTALLED_VERSIONS[$INDEX]} installed, skipping)"
else
[[ "${SUDO}" != "" ]] && ${SUDO} -v
touch "${BUILD_DIR}/${NAMES[$INDEX]}.log"
mkdir -pv "${BUILD_DIR}/${NAMES[$INDEX]}" > "${BUILD_DIR}/${NAMES[$INDEX]}.log" 2>&1 || return 1
cd "${BUILD_DIR}/${NAMES[$INDEX]}"
"${SOURCE_DIR}/${NAMES[$INDEX]}/${PKGS[$INDEX]%\.tar\.*}/configure" --prefix="${PREFIX}" >> "${BUILD_DIR}/${NAMES[$INDEX]}.log" 2>&1 || return 1
make -j "${JOBS}" AR=ar RANLIB=ranlib >> "${BUILD_DIR}/${NAMES[$INDEX]}.log" 2>&1 || return 1
${SUDO} make install >> "${BUILD_DIR}/${NAMES[$INDEX]}.log" 2>&1 || return 1
echo ""
fi
# ninja
INDEX=$((INDEX+1))
printf "Building [%02i/%02i] %s " "$((INDEX+1))" "${TOTAL}" "${NAMES[$INDEX]} ${VERSIONS[$INDEX]}"
if [[ "${SKIP[$INDEX]}" == true ]]; then
echo "(${INSTALLED_VERSIONS[$INDEX]} installed, skipping)"
else
[[ "${SUDO}" != "" ]] && ${SUDO} -v
touch "${BUILD_DIR}/${NAMES[$INDEX]}.log"
mkdir -pv "${BUILD_DIR}/${NAMES[$INDEX]}" > "${BUILD_DIR}/${NAMES[$INDEX]}.log" 2>&1 || return 1
cd "${BUILD_DIR}/${NAMES[$INDEX]}"
python3 "${SOURCE_DIR}/${NAMES[$INDEX]}/${PKGS[$INDEX]%\.tar\.*}/configure.py" --bootstrap >> "${BUILD_DIR}/${NAMES[$INDEX]}.log" 2>&1 || return 1
${SUDO} mv ninja "${PREFIX}/bin" >> "${BUILD_DIR}/${NAMES[$INDEX]}.log" 2>&1 || return 1
echo ""
fi
# openssl
INDEX=$((INDEX+1))
printf "Building [%02i/%02i] %s " "$((INDEX+1))" "${TOTAL}" "${NAMES[$INDEX]} ${VERSIONS[$INDEX]}"
if [[ "${SKIP[$INDEX]}" == true ]]; then
echo "(${INSTALLED_VERSIONS[$INDEX]} installed, skipping)"
else
[[ "${SUDO}" != "" ]] && ${SUDO} -v
touch "${BUILD_DIR}/${NAMES[$INDEX]}.log"
mkdir -pv "${BUILD_DIR}/${NAMES[$INDEX]}" > "${BUILD_DIR}/${NAMES[$INDEX]}.log" 2>&1 || return 1
cd "${BUILD_DIR}/${NAMES[$INDEX]}"
"${SOURCE_DIR}/${NAMES[$INDEX]}/${PKGS[$INDEX]%\.tar\.*}/Configure" --prefix="${PREFIX}" >> "${BUILD_DIR}/${NAMES[$INDEX]}.log" 2>&1 || return 1
make -j "${JOBS}" AR=ar RANLIB=ranlib >> "${BUILD_DIR}/${NAMES[$INDEX]}.log" 2>&1 || return 1
${SUDO} make install_sw >> "${BUILD_DIR}/${NAMES[$INDEX]}.log" 2>&1 || return 1
echo ""
fi
# pkg-config
INDEX=$((INDEX+1))
printf "Building [%02i/%02i] %s " "$((INDEX+1))" "${TOTAL}" "${NAMES[$INDEX]} ${VERSIONS[$INDEX]}"
if [[ "${SKIP[$INDEX]}" == true ]]; then
echo "(${INSTALLED_VERSIONS[$INDEX]} installed, skipping)"
else
[[ "${SUDO}" != "" ]] && ${SUDO} -v
touch "${BUILD_DIR}/${NAMES[$INDEX]}.log"
mkdir -pv "${BUILD_DIR}/${NAMES[$INDEX]}" > "${BUILD_DIR}/${NAMES[$INDEX]}.log" 2>&1 || return 1
cd "${BUILD_DIR}/${NAMES[$INDEX]}"
"${SOURCE_DIR}/${NAMES[$INDEX]}/${PKGS[$INDEX]%\.tar\.*}/configure" --prefix="${PREFIX}" --with-internal-glib --disable-host-tool CFLAGS="-Wno-int-conversion" >> "${BUILD_DIR}/${NAMES[$INDEX]}.log" 2>&1 || return 1
make -j "${JOBS}" >> "${BUILD_DIR}/${NAMES[$INDEX]}.log" 2>&1 || return 1
${SUDO} make install >> "${BUILD_DIR}/${NAMES[$INDEX]}.log" 2>&1 || return 1
echo ""
fi
# clean up
${SUDO} rm -rf "${PKG_DIR}"
# done
if [[ "${PREFIX}" != "/usr/local" ]] && [[ "${NOT_SKIPPED_TOTAL}" -gt 0 ]]; then
echo " run the following command and add it to your shell startup script"
echo " (e.g., .bashrc or .bash_profile) to make persistent across sessions:"
echo " export PATH=\"${PREFIX}/bin:\${PATH}\""
fi
echo "Complete."
set +o pipefail
}
trap die_gracefully EXIT INT TERM
mac_toolchain_build "${@}" &
PID=$!
display_progress "${PID}"
wait "${PID}" || CODE=$?
trap - EXIT INT TERM
if [[ "${CODE}" -ne 0 ]]; then
echo -n "error: subprocess returned non-zero error code (${CODE})" >&2
die_gracefully
fi
exit 0