225 lines
6.3 KiB
Bash
Executable File
225 lines
6.3 KiB
Bash
Executable File
#!/bin/sh -e
|
|
|
|
# Copyright (c) 2025 Alexander Hill
|
|
|
|
# Permission to use, copy, modify, and/or 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.
|
|
|
|
#############
|
|
# Changelog #
|
|
#############
|
|
|
|
# November 13, 2025 (1.0.2)
|
|
# + Added the target triple to the package path
|
|
# * Prevented fetch from re-downloading packages given a valid hash
|
|
# * Renamed all TREETAP_* variables to TT_*
|
|
|
|
# November 11, 2025 (1.0.1)
|
|
# - Removed bashisms to become POSIX compliant
|
|
|
|
# November 9, 2025 (1.0.0)
|
|
# * Initial release
|
|
|
|
####################
|
|
# Global Variables #
|
|
####################
|
|
|
|
[ -z "$TT_DIR" ] && TT_DIR="$(pwd)/.treetap"
|
|
[ -z "$TT_PKGDIR" ] && TT_PKGDIR="$TT_DIR/packages"
|
|
[ -z "$TT_SYSROOT" ] && TT_SYSROOT=/
|
|
TT_VERSION="1.0.2"
|
|
|
|
#####################
|
|
# Utility Functions #
|
|
#####################
|
|
|
|
# Displays the usage information for treetap
|
|
help_message() {
|
|
echo "treetap $TT_VERSION"
|
|
echo
|
|
echo "Package Commands:"
|
|
echo " $0 install <package> [sysroot]"
|
|
echo " $0 uninstall <package> [sysroot]"
|
|
echo
|
|
echo "Source Commands:"
|
|
echo " $0 build <spec>"
|
|
echo " $0 clean <spec>"
|
|
echo " $0 fetch <spec>"
|
|
echo " $0 package <spec>"
|
|
echo " $0 purge <spec>"
|
|
exit 1
|
|
}
|
|
|
|
# Confirms that the given strings are valid package and sysroot paths
|
|
package_check() {
|
|
[ -z "$1" ] && (echo "package_check: Missing package file"; exit 1)
|
|
[ -z "$2" ] && (echo "package_check: Missing sysroot"; exit 1)
|
|
[ ! -f "$1" ] && (echo "package_check: Package file \"$1\" not found"; exit 1)
|
|
[ ! -d "$2" ] && (echo "package_check: Sysroot \"$2\" not found"; exit 1)
|
|
true
|
|
}
|
|
|
|
# Reads the source specification and ensures it includes the required data
|
|
source_spec() {
|
|
# Sanity Check
|
|
[ -z "$1" ] && (echo "source_spec: Missing specification file"; exit 1)
|
|
[ ! -f "$1" ] && (echo "source_spec: Specification file \"$1\" not found"; exit 1)
|
|
|
|
# Zhu Li, do the thing!
|
|
. $1
|
|
|
|
# Required Fields
|
|
[ -z "$SRC_HASH" ] && (echo "source_spec: SRC_HASH is required but not defined"; exit 1)
|
|
[ -z "$SRC_NAME" ] && (echo "source_spec: SRC_NAME is required but not defined"; exit 1)
|
|
[ -z "$SRC_URL" ] && (echo "source_spec: SRC_URL is required but not defined"; exit 1)
|
|
[ -z "$SRC_VERSION" ] && (echo "source_spec: SRC_VERSION is required but not defined"; exit 1)
|
|
|
|
# Optional Fields
|
|
[ -z "$SRC_FILENAME" ] && SRC_FILENAME=$(basename $SRC_URL)
|
|
|
|
# Environmental Variables
|
|
[ -z "$TT_BINDIR" ] && TT_BINDIR=/bin
|
|
TT_BUILD=$(clang -dumpmachine)
|
|
[ -z "$TT_TARGET" ] && TT_TARGET=$TT_BUILD
|
|
TT_BUILDDIR="$TT_DIR/sources/$SRC_NAME/$SRC_VERSION/$TT_TARGET"
|
|
[ -z "$TT_INCLUDEDIR" ] && TT_INCLUDEDIR=/usr/include
|
|
TT_INSTALLDIR="$TT_BUILDDIR/install"
|
|
[ -z "$TT_LIBDIR" ] && TT_LIBDIR=/lib
|
|
[ -z "$TT_PREFIX" ] && TT_PREFIX=/
|
|
[ -z "$TT_PROCS" ] && TT_PROCS=$(nproc)
|
|
|
|
true
|
|
}
|
|
|
|
###############
|
|
# Subcommands #
|
|
###############
|
|
|
|
# Installs a package to the sysroot
|
|
package_install() {
|
|
[ ! -z "$2" ] && TT_SYSROOT=$2
|
|
package_check $1 $TT_SYSROOT
|
|
echo "Installing $(basename $1)"
|
|
FULLPATH=$(pwd)/$1
|
|
PUSHD=$(pwd)
|
|
cd $TT_SYSROOT
|
|
xz -cd $FULLPATH | cpio -idmu --quiet
|
|
cd $PUSHD
|
|
exit 0
|
|
}
|
|
|
|
# Uninstalls a package from the sysroot
|
|
package_uninstall() {
|
|
[ ! -z "$2" ] && TT_SYSROOT=$2
|
|
package_check $1 $TT_SYSROOT
|
|
echo "Uninstalling $(basename $1)"
|
|
FULLPATH=$(pwd)/$1
|
|
PUSHD=$(pwd)
|
|
cd $TT_SYSROOT
|
|
xz -cd $FULLPATH | cpio -it --quiet | tail -n +2 | sort -r | while read path; do
|
|
if [ -d $path ]; then
|
|
rmdir --ignore-fail-on-non-empty $path
|
|
else
|
|
rm -f $path
|
|
fi
|
|
done
|
|
cd $PUSHD
|
|
exit 0
|
|
}
|
|
|
|
# Builds the source from the previously fetched tarball
|
|
source_build() {
|
|
source_spec $1
|
|
mkdir -p $TT_BUILDDIR
|
|
PUSHD=$(pwd)
|
|
cd $TT_BUILDDIR
|
|
echo "Building $SRC_NAME $SRC_VERSION"
|
|
build > build-$(date +%Y%m%d%H%M%S).log 2>&1
|
|
cd $PUSHD
|
|
exit 0
|
|
}
|
|
|
|
# Cleans the source from the previous build
|
|
source_clean() {
|
|
source_spec $1
|
|
mkdir -p $TT_BUILDDIR
|
|
PUSHD=$(pwd)
|
|
cd $TT_BUILDDIR
|
|
echo "Cleaning $SRC_NAME $SRC_VERSION"
|
|
clean
|
|
rm -rf $TT_INSTALLDIR
|
|
cd $PUSHD
|
|
exit 0
|
|
}
|
|
|
|
# Fetches and verifies the integrity of the source tarball
|
|
source_fetch() {
|
|
source_spec $1
|
|
mkdir -p $TT_BUILDDIR
|
|
PUSHD=$(pwd)
|
|
cd $TT_BUILDDIR/..
|
|
if [ -f $SRC_FILENAME ]; then
|
|
if (echo "$SRC_HASH $SRC_FILENAME" | sha256sum -c - > /dev/null); then
|
|
echo "Skipping $SRC_FILENAME"
|
|
exit 0
|
|
else
|
|
rm -f $SRC_FILENAME
|
|
fi
|
|
fi
|
|
echo "Fetching $SRC_FILENAME"
|
|
curl -L -sS $SRC_URL -o $SRC_FILENAME
|
|
echo "Verifying $SRC_FILENAME"
|
|
echo "$SRC_HASH $SRC_FILENAME" | sha256sum -c - > /dev/null
|
|
cd $PUSHD
|
|
exit 0
|
|
}
|
|
|
|
# Packages the built artifacts for distribution
|
|
source_package() {
|
|
source_spec $1
|
|
mkdir -p $TT_BUILDDIR
|
|
mkdir -p $TT_INSTALLDIR
|
|
mkdir -p $TT_PKGDIR/$TT_TARGET
|
|
PUSHD=$(pwd)
|
|
cd $TT_BUILDDIR
|
|
echo "Moving artifacts for $SRC_NAME $SRC_VERSION"
|
|
package > package-$(date +%Y%m%d%H%M%S).log
|
|
echo "Archiving $SRC_NAME $SRC_VERSION"
|
|
cd $TT_INSTALLDIR
|
|
find | cpio -o --quiet | xz -cz > "$TT_PKGDIR/$TT_TARGET/$SRC_NAME-$SRC_VERSION.cpio.xz"
|
|
rm -rf $TT_INSTALLDIR
|
|
cd $PUSHD
|
|
exit 0
|
|
}
|
|
|
|
# Purges the entire build directory for a source
|
|
source_purge() {
|
|
source_spec $1
|
|
rm -rf $TT_BUILDDIR
|
|
exit 0
|
|
}
|
|
|
|
###############
|
|
# Entry Point #
|
|
###############
|
|
|
|
case "$1" in
|
|
"build") source_build $2 ;;
|
|
"clean") source_clean $2 ;;
|
|
"fetch") source_fetch $2 ;;
|
|
"install") package_install $2 $3 ;;
|
|
"package") source_package $2 ;;
|
|
"purge") source_purge $2 ;;
|
|
"uninstall") package_uninstall $2 $3 ;;
|
|
*) help_message ;;
|
|
esac
|