537 lines
16 KiB
Bash
Executable file
537 lines
16 KiB
Bash
Executable file
#!/bin/sh
|
|
# Copyright (c) 2022, 2023 Jonas 'Sortie' Termansen.
|
|
#
|
|
# Permission to use, copy, modify, and distribute this software for any
|
|
# purpose with or without fee is hereby granted, provided that the above
|
|
# copyright notice and this permission notice appear in all copies.
|
|
#
|
|
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
#
|
|
# tix-port
|
|
# Download, patch, build, install, and clean ports.
|
|
|
|
set -e
|
|
|
|
unset build
|
|
cache_package=false
|
|
unset collection
|
|
destination=.
|
|
unset end
|
|
unset exec_prefix
|
|
unset generation
|
|
unset host
|
|
unset make
|
|
unset makeflags
|
|
unset prefix
|
|
unset source_port
|
|
unset start
|
|
unset sysroot
|
|
unset tar
|
|
unset target
|
|
unset tmp
|
|
unset mirror
|
|
unset mirror_directory
|
|
|
|
unset port
|
|
|
|
operand=1
|
|
dashdash=
|
|
previous_option=
|
|
for argument do
|
|
if [ -n "$previous_option" ]; then
|
|
eval $previous_option=\$argument
|
|
previous_option=
|
|
continue
|
|
fi
|
|
|
|
case $argument in
|
|
*=?*) parameter=$(expr "X$argument" : '[^=]*=\(.*\)' || true) ;;
|
|
*=) parameter= ;;
|
|
*) parameter=yes ;;
|
|
esac
|
|
|
|
case $dashdash$argument in
|
|
--) dashdash=yes ;;
|
|
--build=*) build=$parameter ;;
|
|
--build) previous_option=build ;;
|
|
--cache-package) cache_package=true ;;
|
|
--collection=*) collection=$parameter ;;
|
|
--collection) previous_option=collection ;;
|
|
--destination=*) destination=$parameter ;;
|
|
--destination) previous_option=destination ;;
|
|
--end=*) end=$parameter ;;
|
|
--end) previous_option=end ;;
|
|
--exec-prefix=*) exec_prefix=$parameter ;;
|
|
--exec-prefix) previous_option=exec_prefix ;;
|
|
--generation=*) generation=$parameter ;;
|
|
--generation) previous_option=generation ;;
|
|
--host=*) host=$parameter ;;
|
|
--host) previous_option=host ;;
|
|
--make=*) make=$parameter ;;
|
|
--make) previous_option=make ;;
|
|
--makeflags=*) makeflags=$parameter ;;
|
|
--makeflags) previous_option=makeflags ;;
|
|
--prefix=*) prefix=$parameter ;;
|
|
--prefix) previous_option=prefix ;;
|
|
--source-port=*) source_port=$parameter ;;
|
|
--source-port) previous_option=source_port ;;
|
|
--start=*) start=$parameter ;;
|
|
--start) previous_option=start ;;
|
|
--sysroot=*) sysroot=$parameter ;;
|
|
--sysroot) previous_option=sysroot ;;
|
|
--tar=*) tar=$parameter ;;
|
|
--tar) previous_option=tar ;;
|
|
--target=*) target=$parameter ;;
|
|
--target) previous_option=target ;;
|
|
--tmp=*) tmp=$parameter ;;
|
|
--tmp) previous_option=tmp ;;
|
|
--mirror=*) mirror=$parameter ;;
|
|
--mirror) previous_option=mirror ;;
|
|
--mirror-directory=*) mirror_directory=$parameter ;;
|
|
--mirror-directory) previous_option=mirror_directory ;;
|
|
-*) echo "$0: unrecognized option $argument" >&2
|
|
exit 1 ;;
|
|
*)
|
|
if [ $operand = 1 ]; then
|
|
port="$argument"
|
|
operand=2
|
|
else
|
|
echo "$0: unexpected extra operand $argument" >&2
|
|
exit 1
|
|
fi
|
|
;;
|
|
esac
|
|
done
|
|
|
|
if [ -n "$previous_option" ]; then
|
|
echo "$0: option '$argument' requires an argument" >&2
|
|
exit 1
|
|
fi
|
|
|
|
if [ -z "$port" ]; then
|
|
echo "$0: error: No port was specified" >&2
|
|
exit 1
|
|
fi
|
|
|
|
if [ ! -e "$port.port" ]; then
|
|
echo "$0: error: Port file doesn't exist: $port.port" >&2
|
|
exit 1
|
|
fi
|
|
|
|
port_dirname=$(dirname -- "$port" )
|
|
|
|
if [ "${collection+x}" = "" -a \
|
|
'(' "${sysroot+x}" = x -o "${prefix+x}" = x ')' ]; then
|
|
collection="$sysroot$prefix"
|
|
fi
|
|
|
|
NAME=$(tix-vars "$port.port" NAME)
|
|
SOURCE_PORT=$(tix-vars -d '' "$port.port" SOURCE_PORT)
|
|
DEVELOPMENT=$(tix-vars -d false "$port.port" DEVELOPMENT)
|
|
|
|
if [ -z "$NAME" ]; then
|
|
echo "$0: error: NAME must be set: $port.port" >&2
|
|
exit 1
|
|
fi
|
|
|
|
if [ -n "$SOURCE_PORT" ]; then
|
|
if [ -z "${source_port+x}" ]; then
|
|
source_port="$port_dirname/../$SOURCE_PORT/$SOURCE_PORT"
|
|
fi
|
|
if [ ! -e "$source_port.port" ]; then
|
|
echo "$0: error: Port file for source port $SOURCE_PORT doesn't exist:" \
|
|
"$source_port.port" >&2
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
step_number() {
|
|
nl << EOF | grep -E -- " $1$" | grep -Eo '[0-9]+'
|
|
start
|
|
download
|
|
extract
|
|
tix-build-start
|
|
clean
|
|
pre-clean
|
|
configure
|
|
build
|
|
install
|
|
post-install
|
|
post-clean
|
|
package
|
|
tix-build-end
|
|
strip
|
|
diff
|
|
tix-install
|
|
end
|
|
EOF
|
|
}
|
|
|
|
if [ -n "$start" ] && [ -z "$(step_number "$start")" ]; then
|
|
echo "$0: error: Invalid --start: $start" >&2
|
|
exit 1
|
|
fi
|
|
|
|
if [ -n "$end" ] && [ -z "$(step_number "$end")" ]; then
|
|
echo "$0: error: Invalid --end: $end" >&2
|
|
exit 1
|
|
fi
|
|
|
|
should_run_step() {
|
|
([ -z "$start" ] || [ $(step_number "$start") -le $(step_number "$1") ]) &&
|
|
([ -z "$end" ] || [ $(step_number "$end") -ge $(step_number "$1") ])
|
|
}
|
|
|
|
announce() {
|
|
cat << EOF
|
|
================================================================================
|
|
==== $1
|
|
================================================================================
|
|
EOF
|
|
}
|
|
|
|
download_archive_from_url() {(
|
|
port="$1"
|
|
name="$2"
|
|
archive="$3"
|
|
url="$4"
|
|
sha256sum="$5"
|
|
if [ -z "$mirror_directory" ]; then
|
|
mirror_directory="$port.mirror"
|
|
fi
|
|
mirror_directory="$mirror_directory/$name"
|
|
mkdir -p -- "$mirror_directory"
|
|
if [ ! -e "$mirror_directory/$archive.sha256sum" ]; then
|
|
announce "Downloading $1: $archive"
|
|
(if echo "$url" | grep -Eq '^[a-z][a-z0-9.+-]*://'; then
|
|
if ! wget -O "$mirror_directory/$archive.untrusted" -- "$url"; then
|
|
echo "$0: warning: Failed to download $archive from $url" >&2
|
|
exit 1
|
|
fi
|
|
else
|
|
if ! cp -- "$url" "$mirror_directory/$archive.untrusted"; then
|
|
echo "$0: warning: Failed to copy $archive from $url" >&2
|
|
exit 1
|
|
fi
|
|
fi
|
|
if ! echo "$sha256sum $mirror_directory/$archive.untrusted" | \
|
|
sha256sum -c; then
|
|
sha256sum "$mirror_directory/$archive.untrusted"
|
|
echo "$0: warning: $port.port: Wrong sha256sum downloading $archive from $url" >&2
|
|
exit 1
|
|
fi
|
|
mv "$mirror_directory/$archive.untrusted" "$mirror_directory/$archive"
|
|
echo "$url" > "$mirror_directory/$archive.url"
|
|
echo "$SHA256SUM $archive" > "$mirror_directory/$archive.sha256sum.new"
|
|
mv "$mirror_directory/$archive.sha256sum.new" \
|
|
"$mirror_directory/$archive.sha256sum"
|
|
) || (
|
|
rm -f "$mirror_directory/$archive.untrusted"
|
|
rm -f "$mirror_directory/$archive.url"
|
|
rm -f "$mirror_directory/$archive.sha256sum.new"
|
|
rm -f "$mirror_directory/$archive.sha256sum"
|
|
exit 1
|
|
)
|
|
fi
|
|
)}
|
|
|
|
download_archive() {(
|
|
port="$1"
|
|
name="$2"
|
|
archive="$3"
|
|
upstream_site="$4"
|
|
upstream_archive="$5"
|
|
sha256sum="$6"
|
|
if ! ([ -n "$mirror" ] &&
|
|
download_archive_from_url "$port" "$name" "$archive" \
|
|
"$mirror/$name/$archive" "$sha256sum") &&
|
|
! download_archive_from_url "$port" "$name" "$archive" \
|
|
"$upstream_site/$upstream_archive" \
|
|
"$sha256sum"; then
|
|
echo "$0: error: Failed to download $archive with sha256sum $sha256sum" >&2
|
|
false
|
|
fi
|
|
)}
|
|
|
|
download_port() {(
|
|
port="$1"
|
|
NAME=$(tix-vars "$port.port" NAME)
|
|
ARCHIVE=$(tix-vars -d '' "$port.port" ARCHIVE)
|
|
if [ -n "$ARCHIVE" ]; then
|
|
UPSTREAM_SITE=$(tix-vars "$port.port" UPSTREAM_SITE)
|
|
UPSTREAM_ARCHIVE=$(tix-vars "$port.port" UPSTREAM_ARCHIVE)
|
|
SHA256SUM=$(tix-vars "$port.port" SHA256SUM)
|
|
download_archive "$port" "$NAME" "$ARCHIVE" "$UPSTREAM_SITE" \
|
|
"$UPSTREAM_ARCHIVE" "$SHA256SUM"
|
|
ARCHIVE_2=$(tix-vars -d '' "$port.port" ARCHIVE_2)
|
|
if [ -n "$ARCHIVE_2" ]; then
|
|
UPSTREAM_SITE_2=$(tix-vars "$port.port" UPSTREAM_SITE_2)
|
|
UPSTREAM_ARCHIVE_2=$(tix-vars "$port.port" UPSTREAM_ARCHIVE_2)
|
|
SHA256SUM_2=$(tix-vars "$port.port" SHA256SUM_2)
|
|
download_archive "$port" "$NAME" "$ARCHIVE_2" \
|
|
"$UPSTREAM_SITE_2" "$UPSTREAM_ARCHIVE_2" "$SHA256SUM_2"
|
|
fi
|
|
fi
|
|
)}
|
|
|
|
desired_version() {(
|
|
port="$1"
|
|
ARCHIVE=$(tix-vars -d '' "$port.port" ARCHIVE)
|
|
stamp="$NAME"
|
|
if [ -n "$ARCHIVE" ]; then
|
|
VERSION=$(tix-vars "$port.port" VERSION)
|
|
SHA256SUM=$(tix-vars "$port.port" SHA256SUM)
|
|
stamp="$stamp.$VERSION.$SHA256SUM"
|
|
ARCHIVE_2=$(tix-vars -d '' "$port.port" ARCHIVE_2)
|
|
if [ -n "$ARCHIVE_2" ]; then
|
|
VERSION_2=$(tix-vars "$port.port" VERSION_2)
|
|
SHA256SUM_2=$(tix-vars "$port.port" SHA256SUM_2)
|
|
stamp="$stamp.$VERSION_2.$SHA256SUM_2"
|
|
fi
|
|
fi
|
|
if [ -f "$port.patch" ]; then
|
|
stamp="$stamp.$(cat "$port.patch" | sha256sum | grep -Eo '^[^ ]*')"
|
|
fi
|
|
if [ -f "$port.execpatch" ]; then
|
|
stamp="$stamp.$(cat "$port.execpatch" | sha256sum | grep -Eo '^[^ ]*')"
|
|
fi
|
|
if [ -f "$port.rmpatch" ]; then
|
|
stamp="$stamp.$(cat "$port.rmpatch" | sha256sum | grep -Eo '^[^ ]*')"
|
|
fi
|
|
if [ -f "$port.post-install" ]; then
|
|
stamp="$stamp.$(cat "$port.post-install" | sha256sum | grep -Eo '^[^ ]*')"
|
|
fi
|
|
DEVELOPMENT=$(tix-vars -d false "$port.port" DEVELOPMENT)
|
|
if [ "$DEVELOPMENT" = true ]; then
|
|
stamp="$stamp.development"
|
|
fi
|
|
echo "$stamp"
|
|
)}
|
|
|
|
diff_package() {(
|
|
port="$1"
|
|
cd "$(dirname -- "$port")"
|
|
base=$(basename -- "$port")
|
|
if [ -e "$base.upstream" ]; then
|
|
announce "diff $base.upstream $base"
|
|
LC_ALL=C diff -Paur --no-dereference -- "$base.upstream" "$base" |
|
|
sed -E -e '/^Only in.*$/d' -e 's/^((---|\+\+\+)[^\t]+)\t.*/\1/' \
|
|
> "$base.patch"
|
|
if [ ! -s "$base.patch" ]; then rm "$base.patch"; fi
|
|
tix-execdiff -- "$base.upstream" "$base" |
|
|
LC_ALL=C sort > "$base.execpatch"
|
|
if [ ! -s "$base.execpatch" ]; then rm "$base.execpatch"; fi
|
|
tix-rmdiff -- "$base.upstream" "$base" |
|
|
LC_ALL=C sort > "$base.rmpatch"
|
|
if [ ! -s "$base.rmpatch" ]; then rm "$base.rmpatch"; fi
|
|
desired_version "$base" > "$base.version"
|
|
fi
|
|
)}
|
|
|
|
extract_package() {(
|
|
port="$1"
|
|
NAME=$(tix-vars "$port.port" NAME)
|
|
DEVELOPMENT=$(tix-vars -d false "$port.port" DEVELOPMENT)
|
|
NEED_WRITABLE=$(tix-vars -d false "$port.port" NEED_WRITABLE)
|
|
ARCHIVE=$(tix-vars -d '' "$port.port" ARCHIVE)
|
|
ARCHIVE_2=$(tix-vars -d '' "$port.port" ARCHIVE_2)
|
|
if [ -z "$mirror_directory" ]; then
|
|
mirror_directory="$port.mirror"
|
|
fi
|
|
mirror_directory="$mirror_directory/$NAME"
|
|
version_stamp="$(desired_version "$port")"
|
|
if [ ! -e "$port.version" ] ||
|
|
[ "$(cat "$port.version")" != "$version_stamp" ] ||
|
|
[ ! -e "$port.version" ]; then
|
|
if [ -e "$port.version" ]; then
|
|
old_version_stamp="$(cat "$port.version")"
|
|
case "$old_version_stamp" in
|
|
*.development)
|
|
if [ "$DEVELOPMENT" = true ]; then
|
|
echo "$0: error: $NAME: Refusing to delete port in development" >&2
|
|
echo "$0: error: $NAME: .version is currently: $old_version_stamp" >&2
|
|
echo "$0: error: $NAME: .version should be: $version_stamp" >&2
|
|
exit 1
|
|
fi
|
|
esac
|
|
fi
|
|
echo "$version_stamp" > "$port.version.new"
|
|
rm -rf "$port"
|
|
rm -rf "$port.upstream"
|
|
mkdir "$port"
|
|
if [ "$DEVELOPMENT" = true ]; then
|
|
mkdir "$port.upstream"
|
|
fi
|
|
if [ -n "$ARCHIVE" ]; then
|
|
announce "Extracting $1: $ARCHIVE"
|
|
tar -C "$port" -xf "$mirror_directory/$ARCHIVE" --strip-components=1
|
|
if [ "$DEVELOPMENT" = true ]; then
|
|
tar -C "$port.upstream" -xf "$mirror_directory/$ARCHIVE" \
|
|
--strip-components=1
|
|
fi
|
|
if [ -n "$ARCHIVE_2" ]; then
|
|
announce "Extracting $1: $ARCHIVE_2"
|
|
tar -C "$port" -xf "$mirror_directory/$ARCHIVE_2" --strip-components=1
|
|
if [ "$DEVELOPMENT" = true ]; then
|
|
tar -C "$port.upstream" -xf "$mirror_directory/$ARCHIVE_2" \
|
|
--strip-components=1
|
|
fi
|
|
fi
|
|
fi
|
|
if [ -f "$port.patch" ]; then
|
|
if [ "$DEVELOPMENT" = true ]; then
|
|
patch -f -d "$port" -p1 < "$port.patch" || true
|
|
# .rej files might already have been applied
|
|
(cd "$port" &&
|
|
find \
|
|
-name '*.rej' \
|
|
-exec sh -c 'patch -fRs -p0 --dry-run < "$0" >/dev/null 2>&1' \
|
|
'{}' ';' -delete)
|
|
# .orig files aren't useful unless part of the patch got rejected.
|
|
find "$port" \
|
|
-name '*.orig' \
|
|
-exec sh -c 'test ! -e "$(echo "$0" | sed -E "s,\\.orig$,.rej,")"' \
|
|
'{}' ';' -delete
|
|
else
|
|
patch -d "$port" -p1 < "$port.patch"
|
|
fi
|
|
fi
|
|
if [ -f "$port.execpatch" ]; then
|
|
tix-execpatch --directory "$port" "$port.execpatch"
|
|
fi
|
|
if [ -f "$port.rmpatch" ]; then
|
|
tix-rmpatch --directory "$port" "$port.rmpatch"
|
|
fi
|
|
if [ "$DEVELOPMENT" != true -a "$NEED_WRITABLE" != true ]; then
|
|
find "$port" '!' -type d -exec chmod a-w '{}' +
|
|
fi
|
|
mv "$port.version.new" "$port.version"
|
|
if [ "$DEVELOPMENT" = true ]; then
|
|
REJECTS="$(find "$port" -name '*.rej' -o -name '*.orig' | sort)"
|
|
if [ -n "$REJECTS" ]; then
|
|
echo >&2
|
|
echo "$REJECTS" >&2
|
|
echo "$0: error: $NAME: The above patch hunks were rejected" >&2
|
|
exit 1
|
|
fi
|
|
fi
|
|
fi
|
|
)}
|
|
|
|
# TODO: This adds another decompression and compression to the build time, this
|
|
# should be done as a tix post installation step. Also this might miss
|
|
# programs in unusual locations, so a thorough search and strip is needed.
|
|
strip_tix() {(
|
|
strip=${host+$host-}strip
|
|
dir=$(mktemp -d)
|
|
tar -C "$dir" -xf "$1"
|
|
# TODO: After releasing Sortix 1.1, remove the data directory compatibility.
|
|
if [ -e "$dir/data" ]; then
|
|
data_dir="$dir/data"
|
|
else
|
|
data_dir="$dir"
|
|
fi
|
|
$strip -d "$data_dir/bin/"* 2>/dev/null || true
|
|
$strip -d "$data_dir/lib/"* 2>/dev/null || true
|
|
$strip -d "$data_dir/libexec"* 2>/dev/null || true
|
|
$strip -d "$data_dir/libexec/git-core/"* 2>/dev/null || true
|
|
$strip -d "$data_dir/sbin/"* 2>/dev/null || true
|
|
(cd "$dir" &&
|
|
LC_ALL=C ls -A | grep -Ev '^tix$' |
|
|
tar --numeric-owner --owner=0 --group=0 -cJf "$1" tix -T -)
|
|
rm -rf "$dir"
|
|
)}
|
|
|
|
if $cache_package &&
|
|
[ -f "$destination/$NAME.tix.tar.xz" -a \
|
|
-f "$destination/$NAME.version" ] &&
|
|
[ "$(cat $destination/$NAME.version)" = "$(desired_version $port)" ]; then
|
|
start=tix-install
|
|
fi
|
|
|
|
if should_run_step download; then
|
|
if [ -n "$SOURCE_PORT" ]; then
|
|
download_port "$source_port"
|
|
fi
|
|
download_port "$port"
|
|
fi
|
|
|
|
if should_run_step extract; then
|
|
if [ -n "$SOURCE_PORT" ]; then
|
|
extract_package "$source_port"
|
|
fi
|
|
extract_package "$port"
|
|
fi
|
|
|
|
update_version=false
|
|
if [ $(step_number "${start-start}") -lt $(step_number tix-build-end) ] &&
|
|
[ $(step_number "${end-end}") -gt $(step_number tix-build-start) ]; then
|
|
announce "Building $NAME"
|
|
unset tix_build_start
|
|
unset tix_build_end
|
|
if [ -n "$start" ]; then
|
|
if [ $(step_number "$start") -le $(step_number tix-build-start) ]; then
|
|
tix_build_start=start
|
|
else
|
|
tix_build_start="$start"
|
|
fi
|
|
fi
|
|
if [ -n "$end" ]; then
|
|
if [ $(step_number "$end") -ge $(step_number tix-build-end) ]; then
|
|
tix_build_end=end
|
|
else
|
|
tix_build_end="$end"
|
|
fi
|
|
fi
|
|
if should_run_step package; then
|
|
mkdir -p "$destination"
|
|
fi
|
|
tix-build \
|
|
${build+--build="$build"} \
|
|
${destination+--destination="$destination"} \
|
|
${tix_build_end+--end="$tix_build_end"} \
|
|
${exec_prefix+--exec-prefix="$exec_prefix"} \
|
|
${generation+--generation="$generation"} \
|
|
${host+--host="$host"} \
|
|
${make+--make="$make"} \
|
|
${makeflags+--makeflags="$makeflags"} \
|
|
${prefix+--prefix="$prefix"} \
|
|
${source_port+--source-port="$source_port"} \
|
|
${tix_build_start+--start="$tix_build_start"} \
|
|
${sysroot+--sysroot="$sysroot"} \
|
|
${tar+--tar="$tar"} \
|
|
${target+--target="$target"} \
|
|
${tmp+--tmp="$tmp"} \
|
|
"$port"
|
|
update_version=true
|
|
fi
|
|
|
|
if should_run_step strip; then
|
|
strip_tix "$destination/$NAME.tix.tar.xz"
|
|
update_version=true
|
|
fi
|
|
|
|
if should_run_step diff; then
|
|
if [ "$DEVELOPMENT" = true ]; then
|
|
diff_package "$port"
|
|
fi
|
|
update_version=true
|
|
fi
|
|
|
|
if $update_version && [ "${destination-.}" != "." ]; then
|
|
cp "$port.version" "$destination/$NAME.version"
|
|
fi
|
|
|
|
if should_run_step tix-install; then
|
|
announce "Installing $NAME"
|
|
tix-install \
|
|
${collection+--collection="$collection"} \
|
|
--reinstall \
|
|
"$destination/$NAME.tix.tar.xz"
|
|
fi
|