[tools, cmake] refactor: update/hash check scripts, use tags for some more deps, proper CPMUtil separation (#2666)

Uses tags for a bunch of deps that can use them

Also adds a bunmch of scripts to tools/cpm, notably for checking hashes
and checking for updates.

TODO for the future:
- CI target to check hashes
- Weekly CI to check for updates

Need to get that other CI runner up

additional stuff

- Ports gentoo fixes
- makes solaris work (TODO: sdl2)
- way better docs
- properly separates CPMUtil as a standalone project

Reviewed-on: #2666
Reviewed-by: Lizzie <lizzie@eden-emu.dev>
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
This commit is contained in:
crueter 2025-10-05 03:04:53 +02:00
parent 1a13e79c3d
commit 9f385bf627
Signed by: crueter
GPG key ID: 425ACD2D4830EBC6
55 changed files with 1197 additions and 683 deletions

21
tools/README.md Normal file
View file

@ -0,0 +1,21 @@
# Tools
Tools for Eden and other subprojects.
## Third-Party
- [CPMUtil Scripts](./cpm)
## Eden
- `shellcheck.sh`: Ensure POSIX compliance (and syntax sanity) for all tools in this directory and subdirectories.
- `llvmpipe-run.sh`: Sets environment variables needed to run any command (or Eden) with llvmpipe.
- `optimize-assets.sh`: Optimize PNG assets with OptiPng.
- `update-cpm.sh`: Updates CPM.cmake to the latest version.
- `update-icons.sh`: Rebuild all icons (macOS, Windows, bitmaps) based on the master SVG file (`dist/dev.eden_emu.eden.svg`)
* Also optimizes the master SVG
* Requires: `png2icns` (libicns), ImageMagick, [`svgo`](https://github.com/svg/svgo)
- `dtrace-tool.sh`
- `lanczos_gen.c`
- `clang-format.sh`: Runs `clang-format` on the entire codebase.
* Requires: clang

View file

@ -1,3 +1,6 @@
#! /bin/sh
exec find src -iname *.h -o -iname *.cpp | xargs clang-format-15 -i -style=file:src/.clang-format
# SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
# SPDX-License-Identifier: GPL-3.0-or-later
exec find src -iname "*.h" -o -iname "*.cpp" | xargs clang-format -i -style=file:src/.clang-format

12
tools/cpm-fetch-all.sh Executable file → Normal file
View file

@ -1,4 +1,4 @@
#!/bin/bash -ex
#!/bin/sh -e
# SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
# SPDX-License-Identifier: GPL-3.0-or-later
@ -6,6 +6,12 @@
# SPDX-FileCopyrightText: 2025 crueter
# SPDX-License-Identifier: GPL-3.0-or-later
LIBS=$(find . src -maxdepth 3 -name cpmfile.json -exec jq -j 'keys_unsorted | join(" ")' {} \; -printf " ")
# provided for workflow compat
tools/cpm-fetch.sh $LIBS
# shellcheck disable=SC1091
. tools/cpm/common.sh
chmod +x tools/cpm/fetch.sh
# shellcheck disable=SC2086
tools/cpm/fetch.sh $LIBS

View file

@ -1,236 +0,0 @@
#!/bin/bash -e
# SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
# SPDX-License-Identifier: GPL-3.0-or-later
# SPDX-FileCopyrightText: 2025 crueter
# SPDX-License-Identifier: GPL-3.0-or-later
[ -z "$CPM_SOURCE_CACHE" ] && 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=$(tr '[:upper:]' '[:lower:]' <<< "$PACKAGE_NAME")
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
mkdir -p "$OUTDIR"
pushd "$OUTDIR" > /dev/null
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 [ $(wc -l <<< "$DIRS") -eq 2 ]; then
SUBDIR=$(find . -maxdepth 1 -type d -not -name ".")
mv "$SUBDIR"/* .
mv "$SUBDIR"/.* . 2>/dev/null || true
rmdir "$SUBDIR"
fi
if grep -e "patches" <<< "$JSON" > /dev/null; then
PATCHES=$(jq -r '.patches | join(" ")' <<< "$JSON")
for patch in $PATCHES; do
patch --binary -p1 < "$ROOTDIR"/.patch/$package/$patch
done
fi
popd > /dev/null
}
ci_package() {
REPO=$(jq -r ".repo" <<< "$JSON")
EXT=$(jq -r '.extension' <<< "$JSON")
[ "$EXT" = null ] && EXT="tar.zst"
VERSION=$(jq -r ".version" <<< "$JSON")
NAME=$(jq -r ".name" <<< "$JSON")
[ "$NAME" = null ] && NAME="$PACKAGE"
PACKAGE=$(jq -r ".package | \"$package\"" <<< "$JSON")
DISABLED=$(jq -j '.disabled_platforms' <<< "$JSON")
[ "$REPO" = null ] && echo "No repo defined for CI package $package" && return
echo "-- CI package $PACKAGE"
for platform in windows-amd64 windows-arm64 android solaris-amd64 freebsd-amd64 linux-amd64 linux-aarch64 macos-universal; 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}"
PACKAGE_NAME="$PACKAGE"
KEY=$platform
LOWER_PACKAGE=$(tr '[:upper:]' '[:lower:]' <<< "$PACKAGE_NAME")
OUTDIR="${CPM_SOURCE_CACHE}/${LOWER_PACKAGE}/${KEY}"
[ -d "$OUTDIR" ] && continue
HASH_ALGO=$(jq -r ".hash_algo" <<< "$JSON")
[ "$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
}
for package in $@
do
# prepare for cancer
# TODO(crueter): Fetch json once?
JSON=$(find . src -maxdepth 3 -name cpmfile.json -exec jq -r ".\"$package\" | select( . != null )" {} \;)
[ -z "$JSON" ] && echo "!! No cpmfile definition for $package" && continue
PACKAGE_NAME=$(jq -r ".package" <<< "$JSON")
[ "$PACKAGE_NAME" = null ] && PACKAGE_NAME="$package"
GIT_HOST=$(jq -r ".git_host" <<< "$JSON")
[ "$GIT_HOST" = null ] && GIT_HOST=github.com
REPO=$(jq -r ".repo" <<< "$JSON")
CI=$(jq -r ".ci" <<< "$JSON")
if [ "$CI" != null ]; then
ci_package
continue
fi
VERSION=$(jq -r ".version" <<< "$JSON")
GIT_VERSION=$(jq -r ".git_version" <<< "$JSON")
TAG=$(jq -r ".tag" <<< "$JSON")
SHA=$(jq -r ".sha" <<< "$JSON")
[ "$GIT_VERSION" = null ] && GIT_VERSION="$VERSION"
[ "$GIT_VERSION" = null ] && GIT_VERSION="$TAG"
# url parsing WOOOHOOHOHOOHOHOH
URL=$(jq -r ".url" <<< "$JSON")
SHA=$(jq -r ".sha" <<< "$JSON")
VERSION=$(jq -r ".version" <<< "$JSON")
GIT_VERSION=$(jq -r ".git_version" <<< "$JSON")
if [ "$GIT_VERSION" != null ]; then
VERSION_REPLACE="$GIT_VERSION"
else
VERSION_REPLACE="$VERSION"
fi
TAG=$(jq -r ".tag" <<< "$JSON")
TAG=$(sed "s/%VERSION%/$VERSION_REPLACE/" <<< $TAG)
ARTIFACT=$(jq -r ".artifact" <<< "$JSON")
ARTIFACT=$(sed "s/%VERSION%/$VERSION_REPLACE/" <<< $ARTIFACT)
ARTIFACT=$(sed "s/%TAG%/$TAG/" <<< $ARTIFACT)
if [ "$URL" != "null" ]; then
DOWNLOAD="$URL"
elif [ "$REPO" != "null" ]; then
GIT_URL="https://$GIT_HOST/$REPO"
BRANCH=$(jq -r ".branch" <<< "$JSON")
if [ "$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}.zip"
else
if [ "$BRANCH" = null ]; then
BRANCH=master
fi
DOWNLOAD="${GIT_URL}/archive/refs/heads/${BRANCH}.zip"
fi
else
echo "!! No repo or URL defined for $package"
continue
fi
# key parsing
KEY=$(jq -r ".key" <<< "$JSON")
if [ "$KEY" = null ]; then
if [ "$SHA" != null ]; then
KEY=$(cut -c1-4 - <<< "$SHA")
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. Must define one of: key, sha, tag, version, git_version"
continue
fi
fi
echo "-- Downloading regular package $package, with key $KEY, from $DOWNLOAD"
# hash parsing
HASH_ALGO=$(jq -r ".hash_algo" <<< "$JSON")
[ "$HASH_ALGO" = null ] && HASH_ALGO=sha512
HASH=$(jq -r ".hash" <<< "$JSON")
if [ "$HASH" = null ]; then
HASH_SUFFIX="${HASH_ALGO}sum"
HASH_URL=$(jq -r ".hash_url" <<< "$JSON")
if [ "$HASH_URL" = null ]; then
HASH_URL="${DOWNLOAD}.${HASH_SUFFIX}"
fi
HASH=$(curl "$HASH_URL" -sS -L -o -)
fi
download_package
done
rm -rf $TMP

View file

@ -1,4 +0,0 @@
#!/bin/sh
SUM=`wget -q https://github.com/$1/archive/$2.zip -O - | sha512sum`
echo "$SUM" | cut -d " " -f1

71
tools/cpm/README.md Executable file
View file

@ -0,0 +1,71 @@
# CPMUtil Tools
These are supplemental shell scripts for CPMUtil aiming to ease maintenance burden for sanity checking, updates, prefetching, formatting, and standard operations done by these shell scripts, all in one common place.
All scripts are POSIX-compliant.
## Meta
These scripts are generally reserved for internal use.
- `common.sh`: Grabs all available cpmfiles and aggregates them together.
* Outputs:
- `PACKAGES`: The aggregated cpmfile
- `LIBS`: The list of individual libraries contained within each cpmfile
- `value`: A function that grabs a key from the `JSON` variable (typically the package key)
- `download.sh`: Utility script to handle downloading of regular and CI packages.
* Generally only used by the fetch scripts.
- `package.sh`: The actual package parser.
* Inputs:
- `PACKAGE`: The package key
* Outputs:
- Basically everything. You're best off reading the code rather than me poorly explaining it.
- `which.sh`: Find which cpmfile a package is located in.
* Inputs:
- The package key
- `replace.sh`: Replace a package's cpmfile definition.
* Inputs:
- `PACKAGE`: The package key
- `NEW_JSON`: All keys to replace/add
* Keys not found in the new json are not touched. Keys cannot currently be deleted.
## Simple Utilities
These scripts don't really have any functionality, they just help you out a bit yknow?
- `format.sh`: Format all cpmfiles (4-space indent is enforced)
* In the future, these scripts will have options for spacing
- `hash.sh`: Determine the hash of a specific package.
* Inputs:
- The repository (e.g. fmtlib/fmt)
- The sha or tag (e.g. v1.0.1)
- `GIT_HOST`: What git host to use (default github.com)
- `USE_TAG`: Set to "true" if the second argument is a tag instead of a sha
- `ARTIFACT`: The artifact to download, if using a tag. Set to null or empty to use the tag source archive instead
* Output: the SHA512 sum of the package
- `url-hash.sh`: Determine the hash of a URL
* Input: the URL
* Output: the SHA512 sum of the URL
## Functional Utilities
These modify the CPM cache or cpmfiles. Each allows you to input all the packages to act on, as well as a `<scriptname>-all.sh` that acts upon all available packages.
For the update and hash scripts, set `UPDATE=true` to update the cpmfile with the new version or hash. Beware: if the hash is `cf83e1357...` that means you got a 404 error!
- `fetch.sh`: Prefetch a package according to its cpmfile definition
* Packages are fetched to the `.cache/cpm` directory by default, following the CPMUtil default.
* Already-fetched packages will be skipped. You can invalidate the entire cache with `rm -rf .cache/cpm`, or invalidate a specific package with e.g. `rm -rf .cache/cpm/packagename` to force a refetch.
* In the future, a force option will be added
* Note that full prefetching will take a long time depending on your internet, the amount of dependencies, and the size of each dependency.
- `check-updates.sh`: Check a package for available updates
* This only applies to packages that utilize tags.
* If the tag is a format string, the `git_version` is acted upon instead.
* Setting `FORCE=true` will forcefully update every package and its hash, even if they are on the latest version (`UPDATE` must also be true)
* This script generally runs fast.
* Packages that should skip updates (e.g. older versions or packages with poorly-made tag structures... looking at you mbedtls) may specify `"skip_updates": true` in their cpmfile definition. This is unnecessary for untagged (e.g. sha or bare URL) packages.
- `check-hashes.sh`: Check a package's hash
* This only applies to packages with hardcoded hashes, NOT ones that use hash URLs.
* This script will take a looooooooooooooong time. This is operationally equivalent to a prefetch, and thus checking all hashes will take a while--but it's worth it! Just make sure you're not using dial-up.
You are recommended to run sanity hash checking for every pull request and commit, and weekly update checks.

10
tools/cpm/check-hash-all.sh Executable file
View file

@ -0,0 +1,10 @@
#!/bin/bash -e
# SPDX-FileCopyrightText: 2025 crueter
# SPDX-License-Identifier: GPL-3.0-or-later
# shellcheck disable=SC1091
. tools/cpm/common.sh
# shellcheck disable=SC2086
tools/cpm/check-hash.sh $LIBS

46
tools/cpm/check-hash.sh Executable file
View file

@ -0,0 +1,46 @@
#!/bin/sh -e
# SPDX-FileCopyrightText: 2025 crueter
# SPDX-License-Identifier: GPL-3.0-or-later
# env vars:
# - UPDATE: fix hashes if needed
# shellcheck disable=SC1091
. tools/cpm/common.sh
RETURN=0
for PACKAGE in "$@"
do
export PACKAGE
# shellcheck disable=SC1091
. tools/cpm/package.sh
if [ "$CI" != null ]; then
continue
fi
[ "$HASH_URL" != null ] && continue
[ "$HASH_SUFFIX" != null ] && continue
echo "-- Package $PACKAGE"
[ "$HASH" = null ] && echo "-- * Warning: no hash specified" && continue
export USE_TAG=true
ACTUAL=$(tools/cpm/url-hash.sh "$DOWNLOAD")
# shellcheck disable=SC2028
[ "$ACTUAL" != "$HASH" ] && echo "-- * Expected $HASH" && echo "-- * Got $ACTUAL" && [ "$UPDATE" != "true" ] && RETURN=1
if [ "$UPDATE" = "true" ] && [ "$ACTUAL" != "$HASH" ]; then
# shellcheck disable=SC2034
NEW_JSON=$(echo "$JSON" | jq ".hash = \"$ACTUAL\"")
export NEW_JSON
tools/cpm/replace.sh
fi
done
exit $RETURN

10
tools/cpm/check-updates-all.sh Executable file
View file

@ -0,0 +1,10 @@
#!/bin/bash -e
# SPDX-FileCopyrightText: 2025 crueter
# SPDX-License-Identifier: GPL-3.0-or-later
# shellcheck disable=SC1091
. tools/cpm/common.sh
# shellcheck disable=SC2086
tools/cpm/check-updates.sh $LIBS

90
tools/cpm/check-updates.sh Executable file
View file

@ -0,0 +1,90 @@
#!/bin/sh -e
# SPDX-FileCopyrightText: 2025 crueter
# SPDX-License-Identifier: GPL-3.0-or-later
# env vars:
# - UPDATE: update if available
# - FORCE: forcefully update
# shellcheck disable=SC1091
. tools/cpm/common.sh
RETURN=0
filter() {
TAGS=$(echo "$TAGS" | jq "[.[] | select(.name | test(\"$1\"; \"i\") | not)]") # vulkan
}
for PACKAGE in "$@"
do
export PACKAGE
# shellcheck disable=SC1091
. tools/cpm/package.sh
SKIP=$(value "skip_updates")
[ "$SKIP" = "true" ] && continue
[ "$REPO" = null ] && continue
[ "$GIT_HOST" != "github.com" ] && continue # TODO
# shellcheck disable=SC2153
[ "$TAG" = null ] && continue
echo "-- Package $PACKAGE"
# TODO(crueter): Support for Forgejo updates w/ forgejo_token
# Use gh-cli to avoid ratelimits lmao
TAGS=$(gh api --method GET "/repos/$REPO/tags")
# filter out some commonly known annoyances
# TODO add more
filter vulkan-sdk # vulkan
filter yotta # mbedtls
# ignore betas/alphas (remove if needed)
filter alpha
filter beta
filter rc
# Add package-specific overrides here, e.g. here for fmt:
[ "$PACKAGE" = fmt ] && filter v0.11
LATEST=$(echo "$TAGS" | jq -r '.[0].name')
[ "$LATEST" = "$TAG" ] && [ "$FORCE" != "true" ] && echo "-- * Up-to-date" && continue
RETURN=1
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
NEW_GIT_VERSION=$(echo "$LATEST" | sed "s/$VERSION_PREFIX//g")
fi
echo "-- * Version $LATEST available, current is $TAG"
export USE_TAG=true
HASH=$(tools/cpm/hash.sh "$REPO" "$LATEST")
echo "-- * New hash: $HASH"
if [ "$UPDATE" = "true" ]; then
RETURN=0
if [ "$HAS_REPLACE" = "true" ]; then
NEW_JSON=$(echo "$JSON" | jq ".hash = \"$HASH\" | .git_version = \"$NEW_GIT_VERSION\"")
else
NEW_JSON=$(echo "$JSON" | jq ".hash = \"$HASH\" | .tag = \"$LATEST\"")
fi
export NEW_JSON
tools/cpm/replace.sh
fi
done
exit $RETURN

32
tools/cpm/common.sh Executable file
View file

@ -0,0 +1,32 @@
#!/bin/sh -e
# SPDX-FileCopyrightText: 2025 crueter
# SPDX-License-Identifier: GPL-3.0-or-later
##################################
# CHANGE THESE FOR YOUR PROJECT! #
##################################
# Which directories to search
DIRS=". src"
# How many levels to go (3 is 2 subdirs max)
MAXDEPTH=3
# shellcheck disable=SC2038
# shellcheck disable=SC2016
# shellcheck disable=SC2086
[ -z "$PACKAGES" ] && PACKAGES=$(find $DIRS -maxdepth "$MAXDEPTH" -name cpmfile.json | xargs jq -s 'reduce .[] as $item ({}; . * $item)')
# For your project you'll want to change the PACKAGES call to include whatever locations you may use (externals, src, etc.)
# Always include .
LIBS=$(echo "$PACKAGES" | jq -j 'keys_unsorted | join(" ")')
export PACKAGES
export LIBS
export DIRS
export MAXDEPTH
value() {
echo "$JSON" | jq -r ".$1"
}

100
tools/cpm/download.sh Executable file
View file

@ -0,0 +1,100 @@
#!/bin/sh -e
# SPDX-FileCopyrightText: 2025 crueter
# SPDX-License-Identifier: GPL-3.0-or-later
# env vars:
# - UPDATE: fix hashes if needed
# shellcheck disable=SC1091
. tools/cpm/common.sh
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
mkdir -p "$OUTDIR"
PREVDIR="$PWD"
cd "$OUTDIR"
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"/* .
mv "$SUBDIR"/.* . 2>/dev/null || true
rmdir "$SUBDIR"
fi
if echo "$JSON" | grep -e "patches" > /dev/null; then
PATCHES=$(echo "$JSON" | jq -r '.patches | join(" ")')
for patch in $PATCHES; do
# shellcheck disable=SC2154
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 android solaris-amd64 freebsd-amd64 linux-amd64 linux-aarch64 macos-universal; 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
LOWER_PACKAGE=$(echo "$PACKAGE_NAME" | tr '[:upper:]' '[:lower:]')
OUTDIR="${CPM_SOURCE_CACHE}/${LOWER_PACKAGE}/${KEY}"
[ -d "$OUTDIR" ] && continue
HASH_ALGO=$(value "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
}

10
tools/cpm/fetch-all.sh Executable file
View file

@ -0,0 +1,10 @@
#!/bin/sh -e
# SPDX-FileCopyrightText: 2025 crueter
# SPDX-License-Identifier: GPL-3.0-or-later
# shellcheck disable=SC1091
. tools/cpm/common.sh
# shellcheck disable=SC2086
tools/cpm/fetch.sh $LIBS

36
tools/cpm/fetch.sh Executable file
View file

@ -0,0 +1,36 @@
#!/bin/sh -e
# SPDX-FileCopyrightText: 2025 crueter
# SPDX-License-Identifier: GPL-3.0-or-later
[ -z "$CPM_SOURCE_CACHE" ] && CPM_SOURCE_CACHE=$PWD/.cache/cpm
mkdir -p "$CPM_SOURCE_CACHE"
# shellcheck disable=SC1091
. tools/cpm/common.sh
# shellcheck disable=SC1091
. tools/cpm/download.sh
# shellcheck disable=SC2034
ROOTDIR="$PWD"
TMP=$(mktemp -d)
# shellcheck disable=SC2034
for PACKAGE in "$@"
do
export PACKAGE
# shellcheck disable=SC1091
. tools/cpm/package.sh
if [ "$CI" = "true" ]; then
ci_package
else
echo "-- Downloading regular package $PACKAGE, with key $KEY, from $DOWNLOAD"
download_package
fi
done
rm -rf "$TMP"

15
tools/cpm/format.sh Executable file
View file

@ -0,0 +1,15 @@
#!/bin/sh -e
# SPDX-FileCopyrightText: 2025 crueter
# SPDX-License-Identifier: GPL-3.0-or-later
# shellcheck disable=SC1091
. tools/cpm/common.sh
# shellcheck disable=SC2086
FILES=$(find $DIRS -maxdepth "$MAXDEPTH" -name cpmfile.json)
for file in $FILES; do
jq --indent 4 < "$file" > "$file".new
mv "$file".new "$file"
done

25
tools/cpm/hash.sh Executable file
View file

@ -0,0 +1,25 @@
#!/bin/sh -e
# SPDX-FileCopyrightText: 2025 crueter
# SPDX-License-Identifier: GPL-3.0-or-later
# usage: hash.sh repo tag-or-sha
# env vars: GIT_HOST, USE_TAG (use tag instead of sha), ARTIFACT (download artifact with that name instead of src archive)
REPO="$1"
[ -z "$GIT_HOST" ] && GIT_HOST=github.com
GIT_URL="https://$GIT_HOST/$REPO"
if [ "$USE_TAG" = "true" ]; then
if [ -z "$ARTIFACT" ] || [ "$ARTIFACT" = "null" ]; then
URL="${GIT_URL}/archive/refs/tags/$2.tar.gz"
else
URL="${GIT_URL}/releases/download/$2/${ARTIFACT}"
fi
else
URL="${GIT_URL}/archive/$2.zip"
fi
SUM=$(wget -q "$URL" -O - | sha512sum)
echo "$SUM" | cut -d " " -f1

203
tools/cpm/package.sh Executable file
View file

@ -0,0 +1,203 @@
#!/bin/sh -e
# SPDX-FileCopyrightText: 2025 crueter
# SPDX-License-Identifier: GPL-3.0-or-later
# env vars:
# - UPDATE: fix hashes if needed
# shellcheck disable=SC1091
. tools/cpm/common.sh
[ -z "$PACKAGE" ] && echo "Package was not specified" && exit 0
# shellcheck disable=SC2153
JSON=$(echo "$PACKAGES" | jq -r ".\"$PACKAGE\" | select( . != null )")
[ -z "$JSON" ] && echo "!! No cpmfile definition for $PACKAGE" && exit 1
# unset stuff
export PACKAGE_NAME="null"
export REPO="null"
export CI="null"
export GIT_HOST="null"
export EXT="null"
export NAME="null"
export DISABLED="null"
export TAG="null"
export ARTIFACT="null"
export SHA="null"
export VERSION="null"
export GIT_VERSION="null"
export DOWNLOAD="null"
export URL="null"
export KEY="null"
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 #
########
REPO=$(value "repo")
CI=$(value "ci")
PACKAGE_NAME=$(value "package")
[ "$PACKAGE_NAME" = null ] && PACKAGE_NAME="$PACKAGE"
GIT_HOST=$(value "git_host")
[ "$GIT_HOST" = null ] && GIT_HOST=github.com
export PACKAGE_NAME
export REPO
export CI
export GIT_HOST
######################
# CI Package Parsing #
######################
VERSION=$(value "version")
if [ "$CI" = "true" ]; then
EXT=$(value "extension")
[ "$EXT" = null ] && EXT="tar.zst"
NAME=$(value "name")
DISABLED=$(echo "$JSON" | jq -j '.disabled_platforms')
[ "$NAME" = null ] && NAME="$PACKAGE_NAME"
export EXT
export NAME
export DISABLED
export VERSION
return 0
fi
##############
# Versioning #
##############
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
echo "$TAG" | grep -e "%VERSION%" > /dev/null && HAS_REPLACE=true || HAS_REPLACE=false
ORIGINAL_TAG="$TAG"
TAG=$(echo "$TAG" | sed "s/%VERSION%/$VERSION_REPLACE/g")
ARTIFACT=$(echo "$ARTIFACT" | sed "s/%VERSION%/$VERSION_REPLACE/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")
if [ "$URL" != "null" ]; then
DOWNLOAD="$URL"
elif [ "$REPO" != "null" ]; then
GIT_URL="https://$GIT_HOST/$REPO"
BRANCH=$(value "branch")
if [ "$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}.zip"
else
if [ "$BRANCH" = null ]; then
BRANCH=master
fi
DOWNLOAD="${GIT_URL}/archive/refs/heads/${BRANCH}.zip"
fi
else
echo "!! No repo or URL defined for $PACKAGE"
exit 1
fi
export DOWNLOAD
export URL
###############
# Key Parsing #
###############
KEY=$(value "key")
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. Must define one of: key, sha, tag, version, git_version"
exit 1
fi
fi
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
fi
export HASH_URL
export HASH_SUFFIX
export HASH
export HASH_ALGO
export JSON

20
tools/cpm/replace.sh Executable file
View file

@ -0,0 +1,20 @@
#!/bin/sh -e
# SPDX-FileCopyrightText: 2025 crueter
# SPDX-License-Identifier: GPL-3.0-or-later
# Replace a specified package with a modified json.
# env vars:
# - PACKAGE: The package key to act on
# - NEW_JSON: The new json to use
[ -z "$PACKAGE" ] && echo "You must provide the PACKAGE environment variable." && return 1
[ -z "$NEW_JSON" ] && echo "You must provide the NEW_JSON environment variable." && return 1
FILE=$(tools/cpm/which.sh "$PACKAGE")
jq --indent 4 --argjson repl "$NEW_JSON" ".\"$PACKAGE\" *= \$repl" "$FILE" > "$FILE".new
mv "$FILE".new "$FILE"
echo "-- * -- Updated $FILE"

7
tools/cpm/url-hash.sh Executable file
View file

@ -0,0 +1,7 @@
#!/bin/sh
# SPDX-FileCopyrightText: 2025 crueter
# SPDX-License-Identifier: GPL-3.0-or-later
SUM=$(wget -q "$1" -O - | sha512sum)
echo "$SUM" | cut -d " " -f1

15
tools/cpm/which.sh Executable file
View file

@ -0,0 +1,15 @@
#!/bin/sh -e
# SPDX-FileCopyrightText: 2025 crueter
# SPDX-License-Identifier: GPL-3.0-or-later
# check which file a package is in
# shellcheck disable=SC1091
. tools/cpm/common.sh
# shellcheck disable=SC2086
JSON=$(find $DIRS -maxdepth "$MAXDEPTH" -name cpmfile.json -exec grep -l "$1" {} \;)
[ -z "$JSON" ] && echo "!! No cpmfile definition for $1"
echo "$JSON"

View file

@ -1,42 +1,59 @@
#!/usr/local/bin/bash -ex
# SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
# SPDX-License-Identifier: GPL-3.0-or-later
# Basic script to run dtrace sampling over the program (requires Flamegraph)
# Usage is either running as: ./dtrace-tool.sh pid (then input the pid of the process)
# Or just run directly with: ./dtrace-tool.sh <command>
FLAMEGRAPH_DIR=".."
function fail {
printf '%s\n' "$1" >&2
exit "${2-1}"
fail() {
printf '%s\n' "$1" >&2
exit "${2-1}"
}
[ -f $FLAMEGRAPH_DIR/FlameGraph/stackcollapse.pl ] || fail 'Where is flamegraph?'
#[ which dtrace ] || fail 'Needs DTrace installed'
read -p "Sampling Hz [800]: " TRACE_CFG_HZ
read -r "Sampling Hz [800]: " TRACE_CFG_HZ
if [ -z "${TRACE_CFG_HZ}" ]; then
TRACE_CFG_HZ=800
TRACE_CFG_HZ=800
fi
read -p "Sampling time [5] sec: " TRACE_CFG_TIME
read -r "Sampling time [5] sec: " TRACE_CFG_TIME
if [ -z "${TRACE_CFG_TIME}" ]; then
TRACE_CFG_TIME=5
TRACE_CFG_TIME=5
fi
TRACE_FILE=dtrace-out.user_stacks
TRACE_FOLD=dtrace-out.fold
TRACE_SVG=dtrace-out.svg
ps
if [[ $1 = 'pid' ]]; then
read -p "PID: " TRACE_CFG_PID
sudo echo 'Sudo!'
if [ "$1" = 'pid' ]; then
read -r "PID: " TRACE_CFG_PID
sudo echo 'Sudo!'
else
[[ -f $1 && $1 ]] || fail 'Usage: ./tools/dtrace-profile.sh <path to program>'
echo "Executing: '$@'"
sudo echo 'Sudo!'
"$@" &
TRACE_CFG_PID=$!
if [ -f "$1" ] && [ "$1" ]; then
fail 'Usage: ./tools/dtrace-profile.sh <path to program>'
fi
printf "Executing: "
echo "$@"
sudo echo 'Sudo!'
"$@" &
TRACE_CFG_PID=$!
fi
TRACE_PROBE="profile-${TRACE_CFG_HZ} /pid == ${TRACE_CFG_PID} && arg1/ { @[ustack()] = count(); } tick-${TRACE_CFG_TIME}s { exit(0); }"
rm -- $TRACE_SVG || echo 'Skip'
sudo dtrace -x ustackframes=100 -Z -n "$TRACE_PROBE" -o $TRACE_FILE 2>/dev/null || exit
perl $FLAMEGRAPH_DIR/FlameGraph/stackcollapse.pl $TRACE_FILE > $TRACE_FOLD || exit
perl $FLAMEGRAPH_DIR/FlameGraph/flamegraph.pl $TRACE_FOLD > $TRACE_SVG || exit
sudo chmod 0666 $TRACE_FILE
rm -- $TRACE_FILE $TRACE_FOLD

File diff suppressed because one or more lines are too long

View file

@ -1,6 +1,9 @@
#!/bin/sh -e
# SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
# SPDX-License-Identifier: GPL-3.0-or-later
# Optimizes assets of eden (requires OptiPng)
# Optimizes assets of Eden (requires OptiPng)
which optipng || exit
find . -type f -name *.png -exec optipng -o7 {} \;
find . -type f -name "*.png" -exec optipng -o7 {} \;

View file

@ -1,8 +0,0 @@
#!/bin/bash -ex
# SPDX-FileCopyrightText: 2024 yuzu Emulator Project
# SPDX-License-Identifier: MIT
git submodule sync
git submodule foreach --recursive git reset --hard
git submodule update --init --recursive

11
tools/shellcheck.sh Executable file
View file

@ -0,0 +1,11 @@
#!/bin/sh -e
# SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
# SPDX-License-Identifier: GPL-3.0-or-later
# fd is slightly faster on NVMe (the syntax sux though)
if command -v fd > /dev/null; then
fd . tools -esh -x shellcheck
else
find tools -name "*.sh" -exec shellcheck -s sh {} \;
fi

View file

@ -1,3 +1,6 @@
#!/bin/sh
#!/bin/sh -e
wget -O CMakeModules/CPM.cmake https://github.com/cpm-cmake/CPM.cmake/releases/latest/download/get_cpm.cmake
# SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
# SPDX-License-Identifier: GPL-3.0-or-later
wget -O CMakeModules/CPM.cmake https://github.com/cpm-cmake/CPM.cmake/releases/latest/download/CPM.cmake

View file

@ -1,8 +1,11 @@
#!/bin/sh -e
# SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
# SPDX-License-Identifier: GPL-3.0-or-later
# Updates main icons for eden
which png2icns || [ which yay && yay libicns ] || exit
which png2icns || (which yay && yay libicns) || exit
which magick || exit
export EDEN_SVG_ICO="dist/dev.eden_emu.eden.svg"

View file

@ -1,4 +0,0 @@
#!/bin/sh
SUM=`wget -q $1 -O - | sha512sum`
echo "$SUM" | cut -d " " -f1