[cmake] Update CPMUtil (#4123)

Notable changes

- Single cpmfile
- version/min_version/git_version have been fixed and replaced with
  version and min_version
- Docs rewrite
- Legacy options are gone
- Fixed update/version commands
- Added patch creation functionality

Signed-off-by: crueter <crueter@eden-emu.dev>
Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4123
Reviewed-by: Lizzie <lizzie@eden-emu.dev>
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
This commit is contained in:
crueter 2026-06-26 02:22:04 +02:00
parent 6bdb03d8ac
commit c993bc01a4
No known key found for this signature in database
GPG key ID: 425ACD2D4830EBC6
35 changed files with 1500 additions and 1294 deletions

View file

@ -7,31 +7,20 @@ RETURN=0
usage() {
cat <<EOF
Usage: cpmutil.sh package add [-s|--sha] [-t|--tag]
[-c|--cpmfile CPMFILE] [package name]
Usage: cpmutil.sh package add [package name]
Add a new package to a cpmfile.
Options:
-t, --tag Use tag versioning, instead of the default,
commit sha versioning.
-c, --cpmfile <CPMFILE> Use the specified cpmfile instead of the root cpmfile
Note that you are still responsible for integrating this into your CMake.
EOF
exit $RETURN
exit "$RETURN"
}
die() {
echo "-- $*" >&2
exit 1
}
_cpmfile() {
[ -n "$1" ] || die "You must specify a valid cpmfile."
CPMFILE="$1"
RETURN=1 usage
}
while :; do
@ -44,21 +33,11 @@ while :; do
opt=$(echo "$opt" | cut -c2-)
case "$char" in
t) TAG=1 ;;
c)
_cpmfile "$2"
shift
;;
h) usage ;;
*) die "Invalid option -$char" ;;
esac
done
;;
--tag) TAG=1 ;;
--cpmfile)
_cpmfile "$2"
shift
;;
--help) usage ;;
"$0") break ;;
"") break ;;
@ -68,12 +47,8 @@ while :; do
shift
done
: "${CPMFILE:=$PWD/cpmfile.json}"
[ -n "$PKG" ] || die "You must specify a package name."
export PKG
export CPMFILE
export TAG
"$SCRIPTS"/util/interactive.sh

57
tools/cpm/package/dir.sh Executable file
View file

@ -0,0 +1,57 @@
#!/bin/sh -e
# SPDX-FileCopyrightText: Copyright 2026 crueter
# SPDX-License-Identifier: LGPL-3.0-or-later
# shellcheck disable=SC1091
. "$SCRIPTS"/../common.sh
usage() {
cat <<EOF
Usage: cpmutil.sh package dir [-a|--all] [PACKAGE]...
Get the local directory for the specified packages.
Options:
-a, --all Operate on all packages in this project.
EOF
exit 0
}
while :; do
case "$1" in
-a | --all) ALL=1 ;;
-h | --help) usage ;;
"$0") break ;;
"") break ;;
*) packages="$packages $1" ;;
esac
shift
done
[ "$ALL" != 1 ] || packages="${LIBS:-$packages}"
[ -n "$packages" ] || usage
for pkg in $packages; do
unset JSON
export PACKAGE="$pkg"
# shellcheck disable=SC1091
. "$SCRIPTS"/vars.sh
# TODO: common get dir func
if [ "$CI" = true ]; then
dir="${CPM_SOURCE_CACHE}/${LOWER_PACKAGE}"
else
dir="${CPM_SOURCE_CACHE}/${LOWER_PACKAGE}/${KEY}"
fi
echo "-- $pkg: $dir"
if [ ! -d "$dir" ]; then
echo "-- * Warning: directory does not exist. Use fetch or reset to create it"
fi
done

View file

@ -33,8 +33,9 @@ done
[ -n "$packages" ] || usage
for pkg in $packages; do
PACKAGE="$pkg"
export PACKAGE
unset JSON
export PACKAGE="$pkg"
# shellcheck disable=SC1091
. "$SCRIPTS"/vars.sh

View file

@ -3,115 +3,8 @@
# SPDX-FileCopyrightText: Copyright 2026 crueter
# SPDX-License-Identifier: LGPL-3.0-or-later
: "${CPM_SOURCE_CACHE:=$PWD/.cache/cpm}"
mkdir -p "$CPM_SOURCE_CACHE"
ROOTDIR="$PWD"
TMP=$(mktemp -d)
download_package() {
FILENAME=$(basename "$DOWNLOAD")
OUTFILE="$TMP/$FILENAME"
LOWER_PACKAGE=$(echo "$PACKAGE_NAME" | tr '[:upper:]' '[:lower:]')
OUTDIR="${CPM_SOURCE_CACHE}/${LOWER_PACKAGE}/${KEY}"
[ -d "$OUTDIR" ] && return
curl "$DOWNLOAD" -sS -L -o "$OUTFILE"
ACTUAL_HASH=$("${HASH_ALGO}"sum "$OUTFILE" | cut -d" " -f1)
[ "$ACTUAL_HASH" != "$HASH" ] && echo "!! $FILENAME did not match expected hash; expected $HASH but got $ACTUAL_HASH" && exit 1
TMPDIR="$TMP/extracted"
mkdir -p "$OUTDIR"
mkdir -p "$TMPDIR"
PREVDIR="$PWD"
mkdir -p "$TMPDIR"
cd "$TMPDIR"
case "$FILENAME" in
*.7z)
7z x "$OUTFILE" >/dev/null
;;
*.tar*)
tar xf "$OUTFILE" >/dev/null
;;
*.zip)
unzip "$OUTFILE" >/dev/null
;;
esac
# basically if only one real item exists at the top we just move everything from there
# since github and some vendors hate me
DIRS=$(find . -maxdepth 1 -type d -o -type f)
# thanks gnu
if [ "$(echo "$DIRS" | wc -l)" -eq 2 ]; then
SUBDIR=$(find . -maxdepth 1 -type d -not -name ".")
mv "$SUBDIR"/* "$OUTDIR"
mv "$SUBDIR"/.* "$OUTDIR" 2>/dev/null || true
rmdir "$SUBDIR"
else
mv ./* "$OUTDIR"
mv ./.* "$OUTDIR" 2>/dev/null || true
fi
cd "$OUTDIR"
if echo "$JSON" | grep -e "patches" >/dev/null; then
PATCHES=$(echo "$JSON" | jq -r '.patches | join(" ")')
for patch in $PATCHES; do
patch --binary -p1 <"$ROOTDIR/.patch/$PACKAGE/$patch"
done
fi
cd "$PREVDIR"
}
ci_package() {
[ "$REPO" != null ] || { echo "-- ! No repo defined" && return; }
echo "-- CI package $PACKAGE_NAME"
for platform in \
windows-amd64 windows-arm64 \
mingw-amd64 mingw-arm64 \
android-aarch64 android-x86_64 \
solaris-amd64 freebsd-amd64 openbsd-amd64 \
linux-amd64 linux-aarch64 \
macos-universal ios-aarch64; do
echo "-- * platform $platform"
case $DISABLED in
*"$platform"*)
echo "-- * -- disabled"
continue
;;
esac
FILENAME="${NAME}-${platform}-${VERSION}.${EXT}"
DOWNLOAD="https://$GIT_HOST/${REPO}/releases/download/v${VERSION}/${FILENAME}"
KEY="$platform-$VERSION"
LOWER_PACKAGE=$(echo "$PACKAGE_NAME" | tr '[:upper:]' '[:lower:]')
OUTDIR="${CPM_SOURCE_CACHE}/${LOWER_PACKAGE}/${KEY}"
[ -d "$OUTDIR" ] && continue
HASH_ALGO=$(echo "$JSON" | jq -r ".hash_algo")
[ "$HASH_ALGO" != null ] || HASH_ALGO=sha512
HASH_SUFFIX="${HASH_ALGO}sum"
HASH_URL="${DOWNLOAD}.${HASH_SUFFIX}"
HASH=$(curl "$HASH_URL" -sS -q -L -o -)
download_package
done
}
# shellcheck disable=SC1091
. "$SCRIPTS/util/fetch.sh"
usage() {
cat <<EOF
@ -141,16 +34,11 @@ done
[ -n "$packages" ] || usage
for PACKAGE in $packages; do
unset JSON
export PACKAGE
# shellcheck disable=SC1091
. "$SCRIPTS"/vars.sh
if [ "$CI" = "true" ]; then
ci_package
else
echo "-- Downloading regular package $PACKAGE, with key $KEY, from $DOWNLOAD"
download_package
fi
fetch_package
done
rm -rf "$TMP"

View file

@ -59,8 +59,33 @@ done
export UPDATE
for pkg in $packages; do
unset JSON
echo "-- Package $pkg"
"$SCRIPTS"/util/fix-hash.sh "$pkg" || RETURN=1
export PACKAGE="$pkg"
# shellcheck disable=SC1091
. "$SCRIPTS"/vars.sh
[ "$CI" = null ] || continue
ACTUAL=$("$SCRIPTS"/util/url-hash.sh "$DOWNLOAD")
if [ "$ACTUAL" != "$HASH" ] && [ "$QUIET" != true ]; then
echo "-- * Expected $HASH"
echo "-- * Got $ACTUAL"
if [ "$UPDATE" != "true" ]; then
RETURN=1
continue
fi
fi
if [ "$UPDATE" = "true" ] && [ "$ACTUAL" != "$HASH" ]; then
NEW_JSON=$(echo "$JSON" | jq ".hash = \"$ACTUAL\"")
"$SCRIPTS"/util/replace.sh "$PACKAGE" "$NEW_JSON"
fi
done
exit $RETURN

173
tools/cpm/package/patch.sh Executable file
View file

@ -0,0 +1,173 @@
#!/bin/sh -e
# SPDX-FileCopyrightText: Copyright 2026 crueter
# SPDX-License-Identifier: LGPL-3.0-or-later
# shellcheck disable=SC1091
. "$SCRIPTS"/../common.sh
RETURN=0
usage() {
cat <<EOF
Usage: cpmutil.sh package patch [PACKAGE]
Create an in-tree patch for the specified package.
EOF
exit "$RETURN"
}
die() {
echo "-- $*" >&2
RETURN=1 usage
}
while :; do
case "$1" in
-h | --help) usage ;;
"$0") break ;;
"") break ;;
*)
if [ -n "$PACKAGE" ]; then
die "You may only specify one package."
else
PACKAGE="$1"
fi
;;
esac
shift
done
[ -n "$PACKAGE" ] || usage
unset JSON
export PACKAGE
# shellcheck disable=SC1091
. "$SCRIPTS"/vars.sh
if [ "$CI" = true ]; then
die "CI packages do not support in-tree patching"
fi
patch_dir="$PWD/.patch/$PACKAGE"
TMP=$(make_temp_dir)
tmp_package="${TMP}/${LOWER_PACKAGE}/${KEY}"
# First fetch the package...
# shellcheck disable=SC1091
. "$SCRIPTS"/util/fetch.sh
local_dir="$CPM_SOURCE_CACHE/$LOWER_PACKAGE/$KEY"
if [ ! -d "$local_dir" ]; then
echo "-- $PACKAGE_NAME is not fetched locally" >&2
exit 1
fi
src_dir="$tmp_package/$LOWER_PACKAGE/$KEY"
CPM_SOURCE_CACHE="$tmp_package" fetch_package
mkdir -p "$patch_dir"
existing=$(find "$patch_dir" -maxdepth 1 -type f -name '[0-9][0-9][0-9][0-9]-*.patch' 2>/dev/null | sort | tail -1)
if [ -n "$existing" ]; then
last_num=$(basename "$existing" | cut -c1-4)
last_num=$(echo "$last_num" | sed 's/^0*//')
last_num="${last_num:-0}"
next_num=$(printf "%04d" $((last_num + 1)))
else
next_num="0001"
fi
echo "-- Creating patch for $PACKAGE..."
orig_dir="$PWD"
if cmd_exists git; then
cd "$src_dir"
git init >/dev/null 2>&1
git add -A >/dev/null 2>&1
git commit -m "base" >/dev/null 2>&1
git --work-tree="$local_dir" add -A #>/dev/null 2>&1
if git diff --cached --quiet; then
echo "-- No differences found between local and source"
cd "$orig_dir"
rm -rf "$TMP"
exit 0
fi
if ! git commit -v; then
echo "-- Patch cancelled" >&2
cd "$orig_dir"
rm -rf "$TMP"
exit 1
fi
description=$(git log -1 --format="%s")
git format-patch -1 HEAD --stdout >"$patch_dir/tmp.patch"
rm -rf .git
cd "$orig_dir"
unset orig_dir
else
if diff -ruN "$src_dir" "$local_dir" >/dev/null 2>&1; then
echo "-- No differences found between local and source"
rm -rf "$TMP"
exit 0
fi
printf -- "-- Enter a patch description: "
if ! read -r description; then
echo "" >&2
echo "-- Patch cancelled" >&2
rm -rf "$TMP"
exit 1
fi
mkdir -p "$TMP/patchdir/a" "$TMP/patchdir/b"
cp -r "$src_dir/." "$TMP/patchdir/a/"
cp -r "$local_dir/." "$TMP/patchdir/b/"
cd "$TMP/patchdir"
{
echo "Subject: [PATCH] $description" | fold -s -w 80
echo "---"
diff -ruN a b || true
} >"$patch_dir/tmp.patch"
cd "$orig_dir"
unset orig_dir
fi
rm -rf "$TMP"
if [ ! -s "$patch_dir/tmp.patch" ]; then
rm -f "$patch_dir/tmp.patch"
echo "-- No differences found between local and source for $PACKAGE"
exit 0
fi
name_part=$(printf "%s" "$description" | sed 's/^[0-9]\{4\}-//' | sed 's/ /-/g; s/[^a-zA-Z0-9-]//g; s/--*/-/g; s/^-//; s/-$//')
[ -n "$name_part" ] || name_part="patch"
# max is 60 chars, minus 5 for number, minus 6 for patch suffix
max_name_len=49
name_part=$(printf "%s" "$name_part" | cut -c1-"$max_name_len" | sed 's/-$//')
patch_name="${next_num}-${name_part}.patch"
mv "$patch_dir/tmp.patch" "$patch_dir/$patch_name"
NEW_JSON=$(echo "$JSON" | jq ".patches += [\"$patch_name\"]")
"$SCRIPTS"/util/replace.sh "$PACKAGE" "$NEW_JSON"
echo "-- Patch created at $patch_dir/$patch_name"

56
tools/cpm/package/reset.sh Executable file
View file

@ -0,0 +1,56 @@
#!/bin/sh -e
# SPDX-FileCopyrightText: Copyright 2026 crueter
# SPDX-License-Identifier: LGPL-3.0-or-later
# shellcheck disable=SC1091
. "$SCRIPTS"/../common.sh
usage() {
cat <<EOF
Usage: cpmutil.sh package reset [a|--all] [PACKAGE]...
Reset a locally fetched package to its original state.
This is most useful for dropping any changes you've made.
EOF
exit 0
}
while :; do
case "$1" in
-h | --help) usage ;;
-a | --all) ALL=1 ;;
"$0") break ;;
"") break ;;
*) packages="$packages $1" ;;
esac
shift
done
[ "$ALL" != 1 ] || packages="${LIBS:-$packages}"
[ -n "$packages" ] || usage
for PACKAGE in $packages; do
unset JSON
export PACKAGE
# shellcheck disable=SC1091
. "$SCRIPTS"/vars.sh
if [ "$CI" = true ]; then
dir="${CPM_SOURCE_CACHE}/${LOWER_PACKAGE}"
else
dir="${CPM_SOURCE_CACHE}/${LOWER_PACKAGE}/${KEY}"
fi
echo "-- Removing $dir"
rm -rf "$dir"
# shellcheck disable=SC1091
. "$SCRIPTS"/util/fetch.sh
fetch_package
done

View file

@ -9,7 +9,7 @@ usage() {
cat <<EOF
Usage: cpmutil.sh package rm [PACKAGE]...
Delete a package or packages' cpmfile definition(s).
Delete a package or packages' cpmfile definition.
EOF
@ -19,12 +19,12 @@ EOF
[ $# -ge 1 ] || usage
for pkg in "$@"; do
JSON=$("$SCRIPTS"/which.sh "$pkg") || {
"$SCRIPTS"/which.sh "$pkg" || {
echo "!! No cpmfile definition for $pkg"
continue
}
jq --indent 4 "del(.\"$pkg\")" "$JSON" >"$JSON".tmp
mv "$JSON".tmp "$JSON"
echo "-- Removed $pkg from $JSON" || :
jq --indent 4 "del(.\"$pkg\")" cpmfile.json >cpmfile.json.new
mv cpmfile.json.new cpmfile.json
echo "-- Removed $pkg"
done

View file

@ -63,8 +63,9 @@ done
[ -n "$packages" ] || usage
for pkg in $packages; do
PACKAGE="$pkg"
export PACKAGE
unset JSON
export PACKAGE="$pkg"
# shellcheck disable=SC1091
. "$SCRIPTS"/vars.sh
@ -82,13 +83,14 @@ for pkg in $packages; do
echo "-- Package $PACKAGE"
# TODO(crueter): Support for Forgejo updates w/ forgejo_token
# Use gh-cli to avoid ratelimits, if available
# TODO(crueter): Support for forgejo_token?
endpoint="/repos/$REPO/tags"
if command -v gh >/dev/null 2>&1; then
TAGS=$(gh api --method GET "$endpoint")
else
elif [ "$GIT_HOST" = github.com ]; then
TAGS=$(curl -sfL "https://api.github.com$endpoint")
else
TAGS=$(curl -sfL "https://$GIT_HOST/api/v1$endpoint")
fi
# filter out some commonly known annoyances
@ -102,7 +104,6 @@ for pkg in $packages; do
filter_out yotta # mbedtls
# ????????????????????????????????
filter_out vksc
# ignore betas/alphas (remove if needed)
@ -110,15 +111,15 @@ for pkg in $packages; do
filter_out beta
filter_out rc
# openssl
# Add package-specific overrides here, e.g. here for fmt:
[ "$PACKAGE" != fmt ] || filter_out v0.11
# Or for OpenSSL:
if [ "$PACKAGE" = openssl ]; then
filter_out rsaref
filter_in "openssl-"
fi
# Add package-specific overrides here, e.g. here for fmt:
[ "$PACKAGE" != fmt ] || filter_out v0.11
LATEST=$(echo "$TAGS" | jq -r '.[0].name')
if [ "$LATEST" = "null" ] ||
@ -127,45 +128,47 @@ for pkg in $packages; do
continue
fi
# TODO: This is identical to version.sh
if [ "$HAS_REPLACE" = "true" ]; then
# this just extracts the tag prefix
VERSION_PREFIX=$(echo "$ORIGINAL_TAG" | cut -d"%" -f1)
# then we strip out the prefix from the new tag, and make that our new git_version
# then we strip out the prefix from the new tag, and make that our new version
if [ -z "$VERSION_PREFIX" ]; then
NEW_GIT_VERSION="$LATEST"
NEW_VERSION="$LATEST"
else
NEW_GIT_VERSION=$(echo "$LATEST" | sed "s/$VERSION_PREFIX//g")
NEW_VERSION=$(echo "$LATEST" | sed "s/$VERSION_PREFIX//g")
fi
else
NEW_GIT_VERSION="$LATEST"
NEW_VERSION="$LATEST"
fi
_commit="$_commit
* $PACKAGE: $GIT_VERSION -> $NEW_GIT_VERSION"
* $PACKAGE: $VERSION -> $NEW_VERSION"
echo "-- * Version $LATEST available, current is $TAG"
if [ "$UPDATE" = "true" ]; then
if [ "$HAS_REPLACE" = "true" ]; then
NEW_JSON=$(echo "$JSON" | jq ".git_version = \"$NEW_GIT_VERSION\"")
JSON=$(echo "$JSON" | jq ".version = \"$NEW_VERSION\"")
else
NEW_JSON=$(echo "$JSON" | jq ".tag = \"$NEW_GIT_VERSION\"")
JSON=$(echo "$JSON" | jq ".tag = \"$NEW_VERSION\"")
fi
"$SCRIPTS"/util/replace.sh "$PACKAGE" "$NEW_JSON"
echo "-- * -- Updating hash"
export UPDATE
QUIET=true "$SCRIPTS"/util/fix-hash.sh "$PACKAGE"
# shellcheck disable=SC1091
. "$SCRIPTS"/vars.sh
HASH=$("$SCRIPTS"/util/url-hash.sh "$DOWNLOAD")
JSON=$(echo "$JSON" | jq ".hash = \"$HASH\"")
"$SCRIPTS"/util/replace.sh "$PACKAGE" "$JSON"
fi
done
if [ "$UPDATE" = "true" ] && [ "$COMMIT" = "true" ] && [ -n "$_commit" ]; then
for file in $CPMFILES; do
git add "$file"
done
git add "cpmfile.json"
git commit -m "Update dependencies
$_commit"
fi

134
tools/cpm/package/util/fetch.sh Executable file
View file

@ -0,0 +1,134 @@
#!/bin/sh -e
# SPDX-FileCopyrightText: Copyright 2026 crueter
# SPDX-License-Identifier: LGPL-3.0-or-later
# shellcheck disable=SC1091
. "$SCRIPTS"/../common.sh
download_package() {
mkdir -p "$CPM_SOURCE_CACHE"
tmp=$(make_temp_dir)
FILENAME=$(basename "$DOWNLOAD")
OUTFILE="$tmp/$FILENAME"
OUTDIR="${CPM_SOURCE_CACHE}/${LOWER_PACKAGE}/${KEY}"
if [ -d "$OUTDIR" ]; then return; fi
curl "$DOWNLOAD" -sS -L -o "$OUTFILE"
ACTUAL_HASH=$(sha512sum "$OUTFILE" | cut -d" " -f1)
if [ "$ACTUAL_HASH" != "$HASH" ]; then
echo "!! $FILENAME did not match expected hash; expected $HASH but got $ACTUAL_HASH" >&2
exit 1
fi
TMPDIR="$tmp/extracted"
mkdir -p "$OUTDIR"
mkdir -p "$TMPDIR"
PREVDIR="$PWD"
mkdir -p "$TMPDIR"
cd "$TMPDIR"
case "$FILENAME" in
*.7z)
must_install 7z
7z x "$OUTFILE" >/dev/null
;;
*.tar*)
# TODO: Extensions
must_install tar
tar xf "$OUTFILE" >/dev/null
;;
*.zip)
must_install unzip
unzip "$OUTFILE" >/dev/null
;;
esac
# basically if only one real item exists at the top we just move everything from there
# since github and some vendors hate me
DIRS=$(find . -maxdepth 1 -type d -o -type f)
# thanks gnu
if [ "$(echo "$DIRS" | wc -l)" -eq 2 ]; then
SUBDIR=$(find . -maxdepth 1 -type d -not -name ".")
mv "$SUBDIR"/* "$OUTDIR"
mv "$SUBDIR"/.* "$OUTDIR" 2>/dev/null || true
rmdir "$SUBDIR"
else
mv ./* "$OUTDIR"
mv ./.* "$OUTDIR" 2>/dev/null || true
fi
cd "$OUTDIR"
# TODO: Common custom patch/source cache dirs
if echo "$JSON" | grep -e "patches" >/dev/null; then
PATCHES=$(echo "$JSON" | jq -r '.patches | join(" ")')
for patch in $PATCHES; do
abs_patch="$CPMUTIL_PATCH_DIR/$PACKAGE/$patch"
if [ ! -f "$abs_patch" ]; then
echo "-- * Attempted to apply nonexistent patch $patch!"
continue
fi
echo "-- * Applying patch $patch"
patch --binary -p1 <"$abs_patch"
done
fi
cd "$PREVDIR"
rm -rf "$tmp"
}
# TODO: individual platform fetch?
ci_package() {
[ "$REPO" != null ] || { echo "-- ! No repo defined" && return; }
mkdir -p "$CPM_SOURCE_CACHE"
echo "-- CI package $PACKAGE_NAME"
for platform in \
windows-amd64 windows-arm64 \
mingw-amd64 mingw-arm64 \
android-aarch64 android-x86_64 \
linux-amd64 linux-aarch64 \
macos-universal ios-aarch64; do
echo "-- * platform $platform"
case $DISABLED in
*"$platform"*)
echo "-- * -- disabled"
continue
;;
esac
FILENAME="${NAME}-${platform}-${VERSION}.${EXT}"
DOWNLOAD="https://$GIT_HOST/${REPO}/releases/download/v${VERSION}/${FILENAME}"
KEY="$platform-$VERSION"
OUTDIR="${CPM_SOURCE_CACHE}/${LOWER_PACKAGE}/${KEY}"
[ -d "$OUTDIR" ] && continue
HASH_URL="${DOWNLOAD}.sha512sum"
HASH=$(curl "$HASH_URL" -sS -q -L -o -)
download_package
done
}
fetch_package() {
if [ "$CI" = "true" ]; then
ci_package
else
echo "-- Downloading regular package $PACKAGE, with key $KEY, from $DOWNLOAD"
download_package
fi
}

View file

@ -9,18 +9,10 @@
# re-read json files
# shellcheck disable=SC2016
PACKAGES=$(echo "$CPMFILES" | xargs jq -s 'reduce .[] as $item ({}; . * $item)')
export PACKAGES
. "$SCRIPTS"/vars.sh
[ "$CI" = null ] || exit 0
[ "$HASH_URL" = null ] || exit 0
[ "$HASH_SUFFIX" = null ] || exit 0
[ "$HASH" != null ] || { echo "-- * Package has no hash specified" && exit 0; }
ACTUAL=$("$SCRIPTS"/util/url-hash.sh "$DOWNLOAD")
if [ "$ACTUAL" != "$HASH" ] && [ "$QUIET" != true ]; then

View file

@ -86,6 +86,18 @@ optional "Additional find_package arguments, space-separated" \
FIND_ARGS="$reply"
optional "Git host (default: github.com)" \
"The hostname of the Git server, if not GitHub (e.g. codeberg.org, git.crueter.xyz)"
GIT_HOST="$reply"
required "Numeric version of the bundled package" \
"The semantic version of the bundled package. This is only used for package identification,
and if you use tag/artifact fetching. Do not input the entire tag here; for example, if you're using
tag v1.3.0, then set this to 1.3.0 and set the tag to v%VERSION%."
VERSION="$reply"
optional "Is this a CI package? [y/N]" \
"Yes if the package is a prebuilt binary distribution (e.g. crueter-ci),
no if the package is built from source if it's bundled."
@ -96,27 +108,31 @@ case "$reply" in
esac
if [ "$CI" = "false" ]; then
optional "Git host (default: github.com)" \
"The hostname of the Git server, if not GitHub (e.g. codeberg.org, git.crueter.xyz)"
while :; do
required "Use tag or commit sha versioning? [tag/sha]" \
"Tag versioning is compatible with auto-updating.
Use sha versioning for projects with improper tagging practices"
GIT_HOST="$reply"
if [ "$reply" = "tag" ]; then
TAG=1
break
elif [ "$reply" = "sha" ]; then
SHA=1
break
else
echo "-- Invalid choice $reply"
fi
done
if [ "$TAG" = "1" ]; then
required "Numeric version of the bundled package" \
"The semantic version of the bundled package. This is only used for package identification,
and if you use tag/artifact fetching. Do not input the entire tag here; for example, if you're using
tag v1.3.0, then set this to 1.3.0 and set the tag to v%VERSION%."
GIT_VERSION="$reply"
optional "Name of the upstream tag. %VERSION% is replaced by the numeric version (default: %VERSION%)" \
optional "Name of the upstream tag. %VERSION% is replaced by the numeric version ($VERSION) (default: %VERSION%)" \
"Most commonly this will be something like v%VERSION% or release-%VERSION%, or just %VERSION%."
TAGNAME="$reply"
[ -n "$TAGNAME" ] || TAGNAME="%VERSION%"
optional "Name of the release artifact to download, if applicable.
-- %VERSION% is replaced by the numeric version and %TAG% is replaced by the tag name" \
-- %VERSION% is replaced by the numeric version ($VERSION) and %TAG% is replaced by the tag name" \
"Download the specified artifact from the release with the previously specified tag.
If unspecified, the source code at the specified tag will be used instead."
@ -134,11 +150,6 @@ should be set in CMake with AddJsonPackage's OPTIONS parameter."
OPTIONS="$reply"
else
required "Version of the CI package (e.g. 3.6.0-9eff87adb1)" \
"CI artifacts are stored as <name>-<platform>-<version>.tar.zst. This option controls the version."
VERSION="$reply"
required "Name of the CI artifact" \
"CI artifacts are stored as <name>-<platform>-<version>.tar.zst. This option controls the name."
@ -149,7 +160,6 @@ else
windows-amd64 windows-arm64
mingw-amd64 mingw-arm64
android-aarch64 android-x86_64
solaris-amd64 freebsd-amd64 openbsd-amd64
linux-amd64 linux-aarch64
macos-universal ios-aarch64"
@ -163,11 +173,15 @@ jq_input='{repo: "'"$REPO"'"}'
[ -z "$PACKAGE" ] || jq_input="$jq_input + {package: \"$PACKAGE\"}"
[ -z "$MIN_VERSION" ] || jq_input="$jq_input + {min_version: \"$MIN_VERSION\"}"
[ -z "$FIND_ARGS" ] || jq_input="$jq_input + {find_args: \"$FIND_ARGS\"}"
jq_input="$jq_input + {version: \"$VERSION\"}"
if [ -n "$GIT_HOST" ] && [ "$GIT_HOST" != "github.com" ]; then
jq_input="$jq_input + {git_host: \"$GIT_HOST\"}"
fi
if [ "$CI" = "true" ]; then
jq_input="$jq_input + {
ci: true,
version: \"$VERSION\",
artifact: \"$ARTIFACT\"
}"
@ -186,32 +200,29 @@ else
jq_input="$jq_input + {options: $options_json}"
fi
# Git host
if [ -n "$GIT_HOST" ] && [ "$GIT_HOST" != "github.com" ]; then
jq_input="$jq_input + {git_host: \"$GIT_HOST\"}"
fi
# versioning stuff
if [ -n "$GIT_VERSION" ]; then
jq_input="$jq_input + {git_version: \"$GIT_VERSION\"}"
[ -z "$TAGNAME" ] || jq_input="$jq_input + {tag: \"$TAGNAME\"}"
if [ "$TAG" = 1 ]; then
jq_input="$jq_input + {tag: \"$TAGNAME\"}"
[ -z "$ARTIFACT" ] || jq_input="$jq_input + {artifact: \"$ARTIFACT\"}"
else
jq_input="$jq_input + {sha: \"$SHA\"}"
fi
fi
new_json=$(jq -n "$jq_input")
JSON=$(jq -n "$jq_input")
jq --arg key "$PKG" --argjson new "$new_json" \
'.[$key] = $new' "$CPMFILE" --indent 4 >"${CPMFILE}.tmp" &&
mv "${CPMFILE}.tmp" "$CPMFILE"
# shellcheck disable=SC1091
. "$SCRIPTS"/vars.sh
# now correct the hash
if [ "$CI" != true ]; then
# shellcheck disable=SC1091
. "$ROOTDIR"/common.sh
QUIET=true UPDATE=true "$SCRIPTS"/util/fix-hash.sh "$PKG"
HASH=$("$SCRIPTS"/util/url-hash.sh "$DOWNLOAD")
JSON=$(echo "$JSON" | jq ".hash = \"$HASH\"")
fi
echo "Added package $PKG to $CPMFILE. Include it in your project with AddJsonPackage($PKG)"
jq --arg key "$PKG" --argjson new "$JSON" \
'.[$key] = $new' "cpmfile.json" --indent 4 >"cpmfile.json.tmp" &&
mv "cpmfile.json.tmp" cpmfile.json
"$SCRIPTS"/format.sh
echo "Added package $PKG to cpmfile.json. Include it in your project with AddJsonPackage($PKG)"

View file

@ -1,13 +1,11 @@
#!/bin/sh -e
# SPDX-FileCopyrightText: Copyright 2025 crueter
# SPDX-FileCopyrightText: Copyright 2026 crueter
# SPDX-License-Identifier: LGPL-3.0-or-later
# Replace a specified package with a modified json.
FILE=$(echo "$CPMFILES" | xargs grep -l "\"$1\"")
jq --indent 4 --argjson repl "$2" ".\"$1\" *= \$repl" cpmfile.json >cpmfile.json.new
mv cpmfile.json.new cpmfile.json
jq --indent 4 --argjson repl "$2" ".\"$1\" *= \$repl" "$FILE" >"$FILE".new
mv "$FILE".new "$FILE"
echo "-- * -- Updated $FILE"
echo "-- * -- Updated cpmfile.json"

View file

@ -1,28 +1,23 @@
#!/bin/sh
#!/bin/sh -e
# SPDX-FileCopyrightText: Copyright 2025 crueter
# SPDX-FileCopyrightText: Copyright 2026 crueter
# SPDX-License-Identifier: LGPL-3.0-or-later
# Required vars: URL, GIT_HOST, REPO, TAG, ARTIFACT, BRANCH, SHA
# Get the download URL for a package
if [ "$URL" != "null" ]; then
DOWNLOAD="$URL"
elif [ "$REPO" != "null" ]; then
GIT_URL="https://$GIT_HOST/$REPO"
if [ "$TAG" != "null" ]; then
if [ "$SHA" != "null" ]; then
DOWNLOAD="${GIT_URL}/archive/${SHA}.tar.gz"
elif [ "$TAG" != "null" ]; then
if [ "$ARTIFACT" != "null" ]; then
DOWNLOAD="${GIT_URL}/releases/download/${TAG}/${ARTIFACT}"
else
DOWNLOAD="${GIT_URL}/archive/refs/tags/${TAG}.tar.gz"
fi
elif [ "$SHA" != "null" ]; then
DOWNLOAD="${GIT_URL}/archive/${SHA}.tar.gz"
else
if [ "$BRANCH" = null ]; then
BRANCH=master
fi
DOWNLOAD="${GIT_URL}/archive/refs/heads/${BRANCH}.tar.gz"
fi
else
echo "!! No repo or URL defined for $PACKAGE_NAME"

View file

@ -9,14 +9,16 @@ value() {
echo "$JSON" | jq -r ".$1"
}
[ -n "$PACKAGE" ] || { echo "Package was not specified" && exit 0; }
# shellcheck disable=SC2153
JSON=$(echo "$PACKAGES" | jq -r ".\"$PACKAGE\" | select( . != null )")
if [ -z "$JSON" ]; then
echo "!! No cpmfile definition for $PACKAGE" >&2
exit 1
[ -n "$PACKAGE" ] || { echo "Package was not specified" && exit 0; }
# shellcheck disable=SC2153
JSON=$(jq -r ".\"$PACKAGE\" | select( . != null )" cpmfile.json)
if [ -z "$JSON" ]; then
echo "!! No cpmfile definition for $PACKAGE" >&2
exit 1
fi
fi
# unset stuff
@ -31,7 +33,7 @@ export TAG="null"
export ARTIFACT="null"
export SHA="null"
export VERSION="null"
export GIT_VERSION="null"
export MIN_VERSION="null"
export DOWNLOAD="null"
export URL="null"
export KEY="null"
@ -39,9 +41,6 @@ export HASH="null"
export ORIGINAL_TAG="null"
export HAS_REPLACE="null"
export VERSION_REPLACE="null"
export HASH_URL="null"
export HASH_SUFFIX="null"
export HASH_ALGO="null"
########
# Meta #
@ -56,7 +55,11 @@ PACKAGE_NAME=$(value "package")
GIT_HOST=$(value "git_host")
[ "$GIT_HOST" != null ] || GIT_HOST=github.com
# used for cache key
LOWER_PACKAGE=$(echo "$PACKAGE_NAME" | tr '[:upper:]' '[:lower:]')
export PACKAGE_NAME
export LOWER_PACKAGE
export REPO
export CI
export GIT_HOST
@ -65,8 +68,12 @@ export GIT_HOST
# CI Package Parsing #
######################
MIN_VERSION=$(value "min_version")
VERSION=$(value "version")
export VERSION
export MIN_VERSION
if [ "$CI" = "true" ]; then
EXT=$(value "extension")
[ "$EXT" != null ] || EXT="tar.zst"
@ -79,7 +86,6 @@ if [ "$CI" = "true" ]; then
export EXT
export NAME
export DISABLED
export VERSION
return 0
fi
@ -91,15 +97,6 @@ fi
TAG=$(value "tag")
ARTIFACT=$(value "artifact")
SHA=$(value "sha")
GIT_VERSION=$(value "git_version")
[ "$GIT_VERSION" != null ] || GIT_VERSION="$VERSION"
if [ "$GIT_VERSION" != null ]; then
VERSION_REPLACE="$GIT_VERSION"
else
VERSION_REPLACE="$VERSION"
fi
if echo "$TAG" | grep -e "%VERSION%" >/dev/null; then
HAS_REPLACE=true
@ -109,30 +106,24 @@ fi
ORIGINAL_TAG="$TAG"
TAG=$(echo "$TAG" | sed "s/%VERSION%/$VERSION_REPLACE/g")
ARTIFACT=$(echo "$ARTIFACT" | sed "s/%VERSION%/$VERSION_REPLACE/g")
TAG=$(echo "$TAG" | sed "s/%VERSION%/$VERSION/g")
ARTIFACT=$(echo "$ARTIFACT" | sed "s/%VERSION%/$VERSION/g")
ARTIFACT=$(echo "$ARTIFACT" | sed "s/%TAG%/$TAG/g")
export TAG
export ARTIFACT
export SHA
export VERSION
export GIT_VERSION
export ORIGINAL_TAG
export HAS_REPLACE
export VERSION_REPLACE
###############
# URL Parsing #
###############
URL=$(value "url")
BRANCH=$(value "branch")
export BRANCH
export URL
. "$SCRIPTS"/vars/url.sh
. "$SCRIPTS"/util/url.sh
export DOWNLOAD
@ -140,9 +131,16 @@ export DOWNLOAD
# Key Parsing #
###############
KEY=$(value "key")
. "$SCRIPTS"/vars/key.sh
if [ "$SHA" != null ]; then
KEY=$(echo "$SHA" | cut -c1-4)
elif [ "$VERSION" != null ]; then
KEY="$VERSION"
elif [ "$TAG" != null ]; then
KEY="$TAG"
else
echo "!! No valid key could be determined for $PACKAGE_NAME. Must define one of: sha, tag, version"
exit 1
fi
export KEY
@ -150,27 +148,11 @@ export KEY
# Hash Parsing #
################
HASH_ALGO=$(value "hash_algo")
[ "$HASH_ALGO" != null ] || HASH_ALGO=sha512
HASH=$(value "hash")
if [ "$HASH" = null ]; then
HASH_SUFFIX="${HASH_ALGO}sum"
HASH_URL=$(value "hash_url")
if [ "$HASH_URL" = null ]; then
HASH_URL="${DOWNLOAD}.${HASH_SUFFIX}"
fi
HASH=$(curl "$HASH_URL" -Ss -L -o -)
else
HASH_URL=null
HASH_SUFFIX=null
echo "!! No hash defined for $PACKAGE_NAME" >&2
fi
export HASH_URL
export HASH_SUFFIX
export HASH
export HASH_ALGO
export JSON

View file

@ -1,21 +0,0 @@
#!/bin/sh -e
# SPDX-FileCopyrightText: Copyright 2025 crueter
# SPDX-License-Identifier: LGPL-3.0-or-later
if [ "$KEY" = null ]; then
if [ "$SHA" != null ]; then
KEY=$(echo "$SHA" | cut -c1-4)
elif [ "$GIT_VERSION" != null ]; then
KEY="$GIT_VERSION"
elif [ "$TAG" != null ]; then
KEY="$TAG"
elif [ "$VERSION" != null ]; then
KEY="$VERSION"
else
echo "!! No valid key could be determined for $PACKAGE_NAME. Must define one of: key, sha, tag, version, git_version"
exit 1
fi
fi
export KEY

View file

@ -34,27 +34,29 @@ if [ "$HAS_REPLACE" = "true" ]; then
VERSION_PREFIX=$(echo "$ORIGINAL_TAG" | cut -d"%" -f1)
# then we strip out the prefix from the new tag, and make that our new git_version
if [ -z "$VERSION_PREFIX" ]; then
NEW_GIT_VERSION="$NEW_VERSION"
else
NEW_GIT_VERSION=$(echo "$NEW_VERSION" | sed "s/$VERSION_PREFIX//g")
if [ -n "$VERSION_PREFIX" ]; then
NEW_VERSION=$(echo "$NEW_VERSION" | sed "s/$VERSION_PREFIX//g")
fi
fi
if [ "$SHA" != null ]; then
NEW_JSON=$(echo "$JSON" | jq ".sha = \"$NEW_VERSION\"")
elif [ "$CI" = "true" ]; then
NEW_JSON=$(echo "$JSON" | jq ".version = \"$NEW_VERSION\"")
elif [ "$HAS_REPLACE" = "true" ]; then
NEW_JSON=$(echo "$JSON" | jq ".git_version = \"$NEW_GIT_VERSION\"")
JSON=$(echo "$JSON" | jq ".sha = \"$NEW_VERSION\"")
elif [ "$CI" = "true" ] || [ "$HAS_REPLACE" = "true" ]; then
JSON=$(echo "$JSON" | jq ".version = \"$NEW_VERSION\"")
else
NEW_JSON=$(echo "$JSON" | jq ".tag = \"$NEW_VERSION\"")
JSON=$(echo "$JSON" | jq ".tag = \"$NEW_VERSION\"")
fi
echo "-- * -- Updating $PACKAGE to version $NEW_VERSION"
"$SCRIPTS"/util/replace.sh "$PACKAGE" "$NEW_JSON"
echo "-- * Updating $PACKAGE to version $NEW_VERSION"
[ "$CI" != "true" ] || exit 0
echo "-- * -- Fixing hash"
. "$ROOTDIR"/common.sh
UPDATE=true QUIET=true "$SCRIPTS"/util/fix-hash.sh
# TODO: ci hash thing please
if [ "$CI" != true ]; then
echo "-- * -- Updating hash"
# shellcheck disable=SC1091
. "$SCRIPTS"/vars.sh
HASH=$("$SCRIPTS"/util/url-hash.sh "$DOWNLOAD")
JSON=$(echo "$JSON" | jq ".hash = \"$HASH\"")
fi
"$SCRIPTS"/util/replace.sh "$PACKAGE" "$JSON"

View file

@ -3,10 +3,6 @@
# SPDX-FileCopyrightText: Copyright 2026 crueter
# SPDX-License-Identifier: LGPL-3.0-or-later
# check which file a package is in
# check if a package is defined
JSON=$(echo "$CPMFILES" | xargs grep -l "\"$1\"")
[ -n "$JSON" ] || { echo "!! No cpmfile definition for $1" >&2 && exit 1; }
echo "$JSON"
echo "$LIBS" | grep "$1" >/dev/null 2>&1