aboutsummaryrefslogtreecommitdiff
path: root/tools/cpm
diff options
context:
space:
mode:
authorcrueter <crueter@eden-emu.dev>2026-07-06 23:11:39 +0200
committercrueter <crueter@eden-emu.dev>2026-07-06 23:11:39 +0200
commit66b073ab8d427d8fc06ffd715151f372cdde818c (patch)
tree667e34c22f542d809a069738bd762a23786814c7 /tools/cpm
parent4c65780f11511b20c2e0288a287faace16516d38 (diff)
[cmake] CPMUtil rewrite of the day number 852 (#4130)
Composite PR for several changes to CPMUtil, most notably: - https://git.crueter.xyz/CMake/CPMUtil/pulls/19 - https://git.crueter.xyz/CMake/CPMUtil/pulls/22 - https://git.crueter.xyz/CMake/CPMUtil/pulls/24 - https://git.crueter.xyz/CMake/CPMUtil/pulls/25 These contain a lot of changes that generally simplify control flow and improve ease-of-use. Read those descriptions and patchsets for more info. Signed-off-by: crueter <crueter@eden-emu.dev> Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4130 Reviewed-by: CamilleLaVey <camillelavey99@gmail.com> Reviewed-by: MaranBr <maranbr@eden-emu.dev>
Diffstat (limited to 'tools/cpm')
-rwxr-xr-xtools/cpm/cmake/README.md3
-rwxr-xr-xtools/cpm/cmake/ScriptUtils.cmake341
-rwxr-xr-xtools/cpm/cmake/format.cmake (renamed from tools/cpm/format.sh)8
-rwxr-xr-xtools/cpm/cmake/ls.cmake24
-rw-r--r--tools/cpm/cmake/package/add.cmake104
-rwxr-xr-xtools/cpm/cmake/package/dir.cmake33
-rwxr-xr-xtools/cpm/cmake/package/fetch.cmake34
-rwxr-xr-xtools/cpm/cmake/package/hash.cmake59
-rw-r--r--tools/cpm/cmake/package/patch.cmake155
-rwxr-xr-xtools/cpm/cmake/package/reset.cmake34
-rwxr-xr-xtools/cpm/cmake/package/rm.cmake31
-rw-r--r--tools/cpm/cmake/package/update.cmake97
-rwxr-xr-xtools/cpm/cmake/package/url.cmake28
-rwxr-xr-xtools/cpm/cmake/package/version.cmake75
-rwxr-xr-xtools/cpm/cmake/package/which.cmake36
-rwxr-xr-xtools/cpm/cmake/update.cmake33
-rwxr-xr-xtools/cpm/common.sh45
-rwxr-xr-xtools/cpm/migrate.sh39
-rwxr-xr-xtools/cpm/package.sh63
-rwxr-xr-xtools/cpm/package/add.sh151
-rwxr-xr-xtools/cpm/package/dir.sh57
-rwxr-xr-xtools/cpm/package/download.sh47
-rwxr-xr-xtools/cpm/package/fetch.sh44
-rwxr-xr-xtools/cpm/package/hash.sh91
-rwxr-xr-xtools/cpm/package/patch.sh169
-rwxr-xr-xtools/cpm/package/reset.sh56
-rwxr-xr-xtools/cpm/package/rm.sh30
-rwxr-xr-xtools/cpm/package/update.sh174
-rwxr-xr-xtools/cpm/package/util/fetch.sh134
-rwxr-xr-xtools/cpm/package/util/fix-hash.sh28
-rwxr-xr-xtools/cpm/package/util/interactive.sh228
-rwxr-xr-xtools/cpm/package/util/replace.sh11
-rwxr-xr-xtools/cpm/package/util/url-hash.sh7
-rwxr-xr-xtools/cpm/package/util/url.sh27
-rwxr-xr-xtools/cpm/package/vars.sh158
-rwxr-xr-xtools/cpm/package/version.sh62
-rwxr-xr-xtools/cpm/package/which.sh8
37 files changed, 1312 insertions, 1412 deletions
diff --git a/tools/cpm/cmake/README.md b/tools/cpm/cmake/README.md
new file mode 100755
index 0000000000..2dd6dfcbe6
--- /dev/null
+++ b/tools/cpm/cmake/README.md
@@ -0,0 +1,3 @@
+# CPMUtil CMake Test Scripts
+
+Testing out some CMake scripting functionality.
diff --git a/tools/cpm/cmake/ScriptUtils.cmake b/tools/cpm/cmake/ScriptUtils.cmake
new file mode 100755
index 0000000000..dbd908a1ea
--- /dev/null
+++ b/tools/cpm/cmake/ScriptUtils.cmake
@@ -0,0 +1,341 @@
+#!/usr/bin/env -S cmake -P
+
+# SPDX-FileCopyrightText: Copyright 2026 crueter
+# SPDX-License-Identifier: LGPL-3.0-or-later
+
+cmake_minimum_required(VERSION 3.31)
+
+# TODO: Account for CPMConfig.cmake
+list(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR})
+list(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/CMakeModules)
+set(CPMUTIL_ROOT ${CMAKE_SOURCE_DIR})
+
+include(CPMUtil)
+
+# Parse the JSON object for a given key.
+macro(parse_key key)
+ get_json_object(${key})
+ set(JSON_NAME ${key})
+ parse_object(${object})
+endmacro()
+
+# Get a package's effective URL, for an already parsed object
+function(get_package_url_object out)
+ if (${url})
+ set(${out} "${url}")
+ else()
+ get_package_url(URL_OUT "${out}"
+ GIT_HOST "${git_host}"
+ REPO "${repo}"
+ VERSION "${version}"
+ ARTIFACT "${artifact}"
+ PACKAGE "${package}")
+ endif()
+
+ return(PROPAGATE ${out})
+endfunction()
+
+# Fetch a package from an already-parsed object.
+function(fetch_package_object)
+ set(optionArgs FORCE)
+ cmake_parse_arguments(ARG "${optionArgs}" "" "" ${ARGN})
+
+ if (${url})
+ set(pkg_url "${url}")
+ else()
+ get_package_url(URL_OUT pkg_url
+ GIT_HOST "${git_host}"
+ REPO "${repo}"
+ VERSION "${version}"
+ ARTIFACT "${artifact}"
+ PACKAGE "${package}")
+ endif()
+
+ if (DEFINED CACHE_PATH_OVERRIDE)
+ set(cache_path ${CACHE_PATH_OVERRIDE})
+ else()
+ get_cache_path(${package} ${version} cache_path)
+ endif()
+
+ set(fetch_args
+ URL "${pkg_url}"
+ HASH "${hash}"
+ PATH "${cache_path}"
+ PATCHES ${patches})
+
+ if(ARG_FORCE)
+ list(APPEND fetch_args FORCE)
+ endif()
+
+ fetch_package(${fetch_args})
+endfunction()
+
+# Format the cpmfile. Requires one of: jq, python, perl
+# If you don't have any of those, sorry not sorry.
+# Maybe I should make a shell-based alternative.
+function(format_cpmfile)
+ # jq is the preferred formatter since it's the fastest
+ cpm_find_program(JQ_EXECUTABLE jq)
+ if (JQ_EXECUTABLE)
+ set(command ${JQ_EXECUTABLE} --indent 4 -S .)
+ else()
+ # Python is simple and works
+ find_package(Python 3.5 COMPONENTS Interpreter QUIET)
+ if (Python_FOUND)
+ set(command ${Python_EXECUTABLE} -m json.tool
+ --indent 4 --sort-keys)
+ else()
+ # json_pp (part of perl) also works well
+ cpm_find_program(JSONPP_EXECUTABLE json_pp)
+ if (JSONPP_EXECUTABLE)
+ set(json_opts "indent" "indent_length=4" "canonical"
+ "space_after=1" "space_before=0")
+ string(JOIN "," json_opts_str ${json_opts})
+
+ set(command ${JSONPP_EXECUTABLE} -f json -t json -json_opt
+ "${json_opts_str}")
+ else()
+ fatal("Fatal: could not find one of jq, Python, or perl"
+ "(json_pp). Install one of these packages to use"
+ "CPMUtil's tooling. If they ARE installed, your"
+ "CMake installation is broken.")
+ endif()
+ endif()
+ endif()
+
+ get_cpmfile_path(file)
+ mktempdir(TMP)
+ set(tmp_file ${TMP}/cpmfile.json)
+
+ execute_process(COMMAND ${command}
+ INPUT_FILE ${file}
+ OUTPUT_FILE ${tmp_file})
+
+ # TODO: error handling, mv, cp?
+ file(COPY_FILE ${tmp_file} ${file})
+
+ file(REMOVE_RECURSE ${TMP})
+endfunction()
+
+# Computes expected SHA512 hash of a package
+function(get_package_hash url out)
+ mktempdir(TMP)
+
+ get_filename_component(filename ${url} NAME)
+ set(file ${TMP}/${filename})
+
+ cpm_download("${url}" "${file}")
+ file(SHA512 ${file} ${out})
+
+ file(REMOVE_RECURSE ${TMP})
+ return(PROPAGATE ${out})
+endfunction()
+
+# Download and put the content into a variable.
+function(cpm_download_var url out)
+ mktempdir(TMP)
+
+ set(file ${TMP}/tmp)
+ cpm_download("${url}" "${file}")
+ file(READ ${file} ${out})
+
+ file(REMOVE_RECURSE ${TMP})
+ return(PROPAGATE ${out})
+endfunction()
+
+# Check if a URL request succeeds without actually saving anything
+function(cpm_url_exists url out)
+ foreach(i RANGE 5)
+ file(DOWNLOAD "${url}" STATUS ret LOG log TIMEOUT 10)
+ list(GET ret 0 code)
+
+ if (code EQUAL 0)
+ set(${out} TRUE)
+ break()
+ else()
+ if (log MATCHES "HTTP/[0-9.]+ (429|403)")
+ sleep(5)
+ continue()
+ endif()
+
+ set(${out} FALSE)
+ break()
+ endif()
+ endforeach()
+
+ return(PROPAGATE ${out})
+endfunction()
+
+# Get latest tag for a package.
+# Requires an already-parsed object
+function(get_latest_tag out)
+ # TODO: Ci packages
+ if (NOT repo OR ci)
+ set(${out} null)
+ return(PROPAGATE ${out})
+ endif()
+
+ # first determine if this is a tag or not
+ if (git_host STREQUAL github.com)
+ set(api "https://api.github.com/repos/${repo}")
+ set(check_endpoint "/git/refs/tags")
+ else()
+ set(api "https://${git_host}/api/v1/repos/${repo}")
+ set(check_endpoint "/tags")
+ endif()
+
+ # artifacts must only check releases
+ if ("${artifact}" STREQUAL "")
+ set(json_key name)
+ set(endpoint "/tags")
+ else()
+ set(json_key tag_name)
+ set(endpoint "/releases")
+ set(check_endpoint "/releases/tags")
+ endif()
+
+ cpm_url_exists("${api}${check_endpoint}/${version}" is_tag)
+
+ if (NOT is_tag)
+ set(${out} null)
+ return(PROPAGATE ${out})
+ endif()
+
+ # strip out prefixes e.g. boost-, openssl-, v
+ # NOTE: subrels e.g. -1 at the end may cause issues.
+ string(REGEX REPLACE "[^0-9.-]" "" t_numeric_version "${version}")
+ string(REGEX REPLACE "-$|^-" "" t_numeric_version "${numeric_version}")
+
+ # now api req
+ cpm_download_var("${api}${endpoint}" tags)
+
+ string(JSON len LENGTH ${tags})
+ math(EXPR last_index "${len} - 1")
+
+ set(greatest_version_numeric ${t_numeric_version})
+ set(greatest_version ${version})
+
+ foreach(i RANGE ${last_index})
+ string(JSON tag_obj GET "${tags}" ${i})
+ string(JSON tag_name GET "${tag_obj}" ${json_key})
+
+ # same as above
+ string(REGEX REPLACE "[^0-9.-]" "" numeric_tag "${tag_name}")
+ string(REGEX REPLACE "-$|^-" "" numeric_tag "${numeric_tag}")
+
+ if (numeric_tag VERSION_GREATER_EQUAL greatest_version_numeric)
+ set(greatest_version_numeric ${numeric_tag})
+ set(greatest_version ${tag_name})
+ endif()
+ endforeach()
+
+ # numeric version replacement
+ if (numeric_version)
+ set(${out} ${greatest_version_numeric})
+ else()
+ set(${out} ${greatest_version})
+ endif()
+
+ return(PROPAGATE ${out})
+endfunction()
+
+# TODO(crueter): Combine these
+
+# Update hash and version of a package
+# Outputs the updated object
+function(modify_package object version hash out)
+ string(JSON new_object SET "${object}" hash "\"${hash}\"")
+ string(JSON new_object SET "${new_object}" version "\"${version}\"")
+
+ set(${out} "${new_object}")
+ return(PROPAGATE ${out})
+endfunction()
+
+# Update hash and numeric_version of a package
+# Outputs the updated object
+function(modify_package_numeric object version hash out)
+ string(JSON new_object SET "${object}" hash "\"${hash}\"")
+ string(JSON new_object SET "${new_object}" numeric_version "\"${version}\"")
+
+ set(${out} "${new_object}")
+ return(PROPAGATE ${out})
+endfunction()
+
+
+function(get_cpmfile_keys out)
+ get_cpmfile_content(object)
+
+ string(JSON len LENGTH ${object})
+
+ math(EXPR last_index "${len} - 1")
+ foreach(i RANGE ${last_index})
+ string(JSON key MEMBER ${object} ${i})
+ list(APPEND ${out} ${key})
+ endforeach()
+
+ return(PROPAGATE ${out})
+endfunction()
+
+function(parse_script_args out)
+ if(PRINT_USAGE)
+ usage()
+ cmake_language(EXIT 0)
+ endif()
+
+ if(NOT CMAKE_SCRIPT_MODE_FILE OR NOT CMAKE_ARGC)
+ set(${out} "" PARENT_SCOPE)
+ return()
+ endif()
+
+ set(found_script FALSE)
+ set(idx 0)
+
+ get_filename_component(script_name "${CMAKE_SCRIPT_MODE_FILE}" NAME)
+
+ while(idx LESS CMAKE_ARGC)
+ if(found_script)
+ set(arg "${CMAKE_ARGV${idx}}")
+ if(NOT arg STREQUAL "--")
+ list(APPEND positional_args ${arg})
+ endif()
+ elseif(CMAKE_ARGV${idx} STREQUAL CMAKE_SCRIPT_MODE_FILE)
+ set(found_script TRUE)
+ else()
+ get_filename_component(arg_name "${CMAKE_ARGV${idx}}" NAME)
+ if(arg_name STREQUAL script_name)
+ set(found_script TRUE)
+ endif()
+ endif()
+ math(EXPR idx "${idx} + 1")
+ endwhile()
+
+ if(ALL_PACKAGES AND NOT NO_ALL)
+ get_cpmfile_keys(all_keys)
+ if(NO_CI)
+ set(filtered_keys)
+ foreach(key ${all_keys})
+ parse_key(${key})
+ if(NOT ci)
+ list(APPEND filtered_keys ${key})
+ endif()
+ endforeach()
+ set(positional_args ${filtered_keys})
+ else()
+ set(positional_args ${all_keys})
+ endif()
+ endif()
+
+ set(${out} ${positional_args} PARENT_SCOPE)
+endfunction()
+
+# Convert a CMake list to a JSON array
+function(list_to_array list out)
+ set(${out} "[]")
+ set(idx 0)
+ foreach(elem ${list})
+ string(JSON ${out} SET ${${out}} "${idx}" "\"${elem}\"")
+ math(EXPR idx "${idx} + 1")
+ endforeach()
+
+ return(PROPAGATE ${out})
+endfunction() \ No newline at end of file
diff --git a/tools/cpm/format.sh b/tools/cpm/cmake/format.cmake
index c1452c4cb2..7eff47655f 100755
--- a/tools/cpm/format.sh
+++ b/tools/cpm/cmake/format.cmake
@@ -1,9 +1,11 @@
-#!/bin/sh -e
+#!/usr/bin/env -S cmake -P
# SPDX-FileCopyrightText: Copyright 2026 crueter
# SPDX-License-Identifier: LGPL-3.0-or-later
-jq --indent 4 -S <cpmfile.json >cpmfile.json.new
-mv cpmfile.json.new cpmfile.json
+cmake_minimum_required(VERSION 3.31)
+
+include(${CMAKE_CURRENT_LIST_DIR}/ScriptUtils.cmake)
# TODO: Run some sanity checks e.g. patches exist, etc.
+format_cpmfile()
diff --git a/tools/cpm/cmake/ls.cmake b/tools/cpm/cmake/ls.cmake
new file mode 100755
index 0000000000..41a1d1d7af
--- /dev/null
+++ b/tools/cpm/cmake/ls.cmake
@@ -0,0 +1,24 @@
+#!/usr/bin/env -S cmake -P
+
+# SPDX-FileCopyrightText: Copyright 2026 crueter
+# SPDX-License-Identifier: LGPL-3.0-or-later
+
+cmake_minimum_required(VERSION 3.31)
+
+include(${CMAKE_CURRENT_LIST_DIR}/ScriptUtils.cmake)
+
+set(NO_ALL TRUE)
+
+function(usage)
+ echo([=[
+Usage: cpmutil.sh ls
+
+List all packages in the cpmfile.
+]=])
+endfunction()
+
+get_cpmfile_keys(keys)
+
+foreach(key ${keys})
+ echo("${key}")
+endforeach()
diff --git a/tools/cpm/cmake/package/add.cmake b/tools/cpm/cmake/package/add.cmake
new file mode 100644
index 0000000000..02c4e1d900
--- /dev/null
+++ b/tools/cpm/cmake/package/add.cmake
@@ -0,0 +1,104 @@
+#!/usr/bin/env -S cmake -P
+
+# SPDX-FileCopyrightText: Copyright 2026 crueter
+# SPDX-License-Identifier: LGPL-3.0-or-later
+
+cmake_minimum_required(VERSION 3.31)
+
+include(${CMAKE_CURRENT_LIST_DIR}/../ScriptUtils.cmake)
+
+function(usage)
+ echo([=[
+Usage: add.cmake [OPTIONS...]
+
+Internal use only.
+]=])
+endfunction()
+
+if (NOT DEFINED KEY)
+ fatal("KEY is required")
+endif()
+
+if (NOT DEFINED REPO)
+ fatal("REPO is required")
+endif()
+
+if (NOT DEFINED VERSION)
+ fatal("VERSION is required")
+endif()
+
+
+if (NOT DEFINED CI)
+ set(CI FALSE)
+endif()
+
+# construct json
+set(object "{}")
+
+macro(add key val)
+ set(${key} ${val})
+ string(JSON object SET ${object} ${key} "\"${val}\"")
+endmacro()
+
+add(repo ${REPO})
+add(version ${VERSION})
+
+if (DEFINED GIT_HOST AND NOT "${GIT_HOST}" STREQUAL github.com)
+ add(git_host ${GIT_HOST})
+else()
+ set(git_host github.com)
+endif()
+
+if (DEFINED PACKAGE)
+ add(package ${PACKAGE})
+else()
+ set(package ${KEY})
+endif()
+
+if (DEFINED FIND_ARGS)
+ add(find_args "${FIND_ARGS}")
+endif()
+
+if (DEFINED MIN_VERSION)
+ add(min_version ${MIN_VERSION})
+endif()
+
+if (DEFINED ARTIFACT)
+ add(artifact ${ARTIFACT})
+endif()
+
+if (CI)
+ add(ci true)
+
+ if (DEFINED DISABLED_PLATFORMS)
+ list_to_array(${DISABLED_PLATFORMS} json_disabled)
+ string(JSON object SET "${object}" disabled_platforms "${json_disabled}")
+ endif()
+else()
+ if (DEFINED OPTIONS)
+ list_to_array(${OPTIONS} json_options)
+ string(JSON object SET "${object}" options "${json_options}")
+ endif()
+
+ # get hash
+ get_package_url_object(pkg_url)
+ get_package_hash("${pkg_url}" pkg_hash)
+
+ add(hash ${pkg_hash})
+
+endif()
+
+echo("\"${KEY}\": ${object}")
+
+# now write
+get_cpmfile_content(cpmfile)
+
+# update cached cpmfile content
+string(JSON cpmfile SET "${cpmfile}" "${KEY}" "${object}")
+
+# write cached cpmfile
+get_cpmfile_path(file)
+file(WRITE ${file} "${cpmfile}")
+format_cpmfile()
+
+echo("-- Added ${KEY}")
diff --git a/tools/cpm/cmake/package/dir.cmake b/tools/cpm/cmake/package/dir.cmake
new file mode 100755
index 0000000000..bbbf523b31
--- /dev/null
+++ b/tools/cpm/cmake/package/dir.cmake
@@ -0,0 +1,33 @@
+#!/usr/bin/env -S cmake -P
+
+# SPDX-FileCopyrightText: Copyright 2026 crueter
+# SPDX-License-Identifier: LGPL-3.0-or-later
+
+cmake_minimum_required(VERSION 3.31)
+
+include(${CMAKE_CURRENT_LIST_DIR}/../ScriptUtils.cmake)
+
+function(usage)
+ echo([=[
+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.
+]=])
+endfunction()
+
+parse_script_args(args)
+
+# TODO: CI packages.
+
+foreach(key ${args})
+ parse_key(${key})
+
+ # Guh.
+ get_cache_path(${package} ${version} cache_path)
+
+ cmake_path(ABSOLUTE_PATH cache_path NORMALIZE OUTPUT_VARIABLE abs_path)
+ echo("${key}: ${abs_path}")
+endforeach() \ No newline at end of file
diff --git a/tools/cpm/cmake/package/fetch.cmake b/tools/cpm/cmake/package/fetch.cmake
new file mode 100755
index 0000000000..f2b678de01
--- /dev/null
+++ b/tools/cpm/cmake/package/fetch.cmake
@@ -0,0 +1,34 @@
+#!/usr/bin/env -S cmake -P
+
+# SPDX-FileCopyrightText: Copyright 2026 crueter
+# SPDX-License-Identifier: LGPL-3.0-or-later
+
+cmake_minimum_required(VERSION 3.31)
+
+include(${CMAKE_CURRENT_LIST_DIR}/../ScriptUtils.cmake)
+
+function(usage)
+ echo([=[
+Usage: cpmutil.sh package fetch [-a|--all] [PACKAGE]...
+
+Fetch the specified package or packages from their defined download locations.
+If the package is already cached, it will not be re-fetched.
+
+Options:
+ -a, --all Operate on all packages in this project.
+]=])
+endfunction()
+
+set(NO_CI TRUE)
+parse_script_args(args)
+
+foreach(key ${args})
+ if (ci)
+ continue()
+ endif()
+
+ parse_key(${key})
+ echo("-- ${key}")
+
+ fetch_package_object()
+endforeach()
diff --git a/tools/cpm/cmake/package/hash.cmake b/tools/cpm/cmake/package/hash.cmake
new file mode 100755
index 0000000000..6be23c9882
--- /dev/null
+++ b/tools/cpm/cmake/package/hash.cmake
@@ -0,0 +1,59 @@
+#!/usr/bin/env -S cmake -P
+
+# SPDX-FileCopyrightText: Copyright 2026 crueter
+# SPDX-License-Identifier: LGPL-3.0-or-later
+
+cmake_minimum_required(VERSION 3.31)
+
+include(${CMAKE_CURRENT_LIST_DIR}/../ScriptUtils.cmake)
+
+function(usage)
+ echo([=[
+Usage: cpmutil.sh package hash [-a|--all] [PACKAGE]...
+
+Check the hash of a specific package or packages.
+If a hash mismatch occurs, this script will update the package's hash.
+
+Options:
+ -a, --all Operate on all packages in this project.
+
+Note that this procedure will usually take a long time
+depending on the number and size of dependencies.
+]=])
+endfunction()
+
+set(NO_CI TRUE)
+parse_script_args(args)
+
+get_cpmfile_content(cpmfile)
+foreach(key ${args})
+ if (ci)
+ continue()
+ endif()
+
+ parse_key("${key}")
+ echo("-- ${key}")
+
+ get_package_url_object(pkg_url)
+ get_package_hash("${pkg_url}" pkg_hash)
+
+ if (pkg_hash STREQUAL hash)
+ echo("Hashes match")
+ else()
+ echo_error("Hash mismatch")
+ echo_error("Expected: ${hash}")
+ echo_error("Got: ${pkg_hash}")
+
+ modify_package("${object}" "${version}" "${pkg_hash}" new_object)
+
+ # update cached cpmfile content
+ string(JSON cpmfile SET "${cpmfile}" "${key}" "${new_object}")
+
+ echo("Corrected hash for ${key}")
+ endif()
+endforeach()
+
+# write cached cpmfile
+get_cpmfile_path(file)
+file(WRITE ${file} "${cpmfile}")
+format_cpmfile()
diff --git a/tools/cpm/cmake/package/patch.cmake b/tools/cpm/cmake/package/patch.cmake
new file mode 100644
index 0000000000..3844921827
--- /dev/null
+++ b/tools/cpm/cmake/package/patch.cmake
@@ -0,0 +1,155 @@
+#!/usr/bin/env -S cmake -P
+
+# SPDX-FileCopyrightText: Copyright 2026 crueter
+# SPDX-License-Identifier: LGPL-3.0-or-later
+
+cmake_minimum_required(VERSION 3.31)
+
+include(${CMAKE_CURRENT_LIST_DIR}/../ScriptUtils.cmake)
+
+function(usage)
+ echo([=[
+Usage: cpmutil.sh package patch [PACKAGE]
+
+Create an in-tree patch for the specified package.
+]=])
+endfunction()
+
+set(NO_ALL TRUE)
+
+# arg parsing
+parse_script_args(args)
+
+list(LENGTH args arg_len)
+if(arg_len GREATER 0)
+ list(GET args 0 KEY)
+endif()
+
+if (NOT KEY)
+ fatal("You must provide a key")
+endif()
+
+if (NOT DEFINED DESCRIPTION)
+ fatal("No description provided")
+endif()
+
+parse_key(${KEY})
+get_cache_path(${package} ${version} local_cache)
+
+if (NOT EXISTS ${local_cache})
+ fatal("${package} is not fetched locally")
+endif()
+
+# get last patch number + 1
+list(LENGTH patches patches_len)
+math(EXPR last_index "${patches_len} - 1")
+list(GET patches ${last_index} patch)
+string(REGEX MATCH "[0-9][0-9][0-9][0-9]" number "${patch}")
+math(EXPR new_patchnum "${number} + 1")
+
+# now pad it for filename usage
+set(padded "0000${new_patchnum}")
+string(LENGTH ${padded} total_len)
+math(EXPR start_index "${total_len} - 4")
+string(SUBSTRING ${padded} ${start_index} 4 padded_patch_number)
+
+# this requires Git
+find_package(Git REQUIRED)
+
+# fetch temporary package
+mktempdir(TMP)
+
+set(CACHE_PATH_OVERRIDE ${TMP}/local)
+fetch_package_object()
+
+# make patch dir
+set(patch_dir "${CPMUTIL_PATCH_DIR}/${KEY}")
+file(MAKE_DIRECTORY "${patch_dir}")
+
+# git stuff
+macro(git_cmd out out_status)
+ echo("${GIT_EXECUTABLE} ${ARGN}")
+ # TODO: error handling
+ execute_process(COMMAND ${GIT_EXECUTABLE} ${ARGN}
+ WORKING_DIRECTORY ${CACHE_PATH_OVERRIDE}
+ OUTPUT_VARIABLE ${out}
+ RESULT_VARIABLE ${out_status})
+endmacro()
+
+# initialize
+git_cmd(_ _ init)
+git_cmd(_ _ add -A)
+git_cmd(_ _ commit -m init)
+git_cmd(_ _ "--work-tree=${local_cache}" add -A)
+
+# check for diffs
+git_cmd(_ diff_status diff --cached --quiet)
+git_cmd(out _ diff)
+
+if (diff_status EQUAL 0)
+ echo(${out})
+ echo_error("No differences found between local copy and source")
+ file(REMOVE_RECURSE ${TMP})
+ cmake_language(EXIT 1)
+endif()
+
+# prompt for patch description
+git_cmd(_ commit_status commit -m "${DESCRIPTION}")
+
+# format patch
+git_cmd(patch_content _ format-patch -1 HEAD --stdout)
+
+# now get patch name...
+
+# strip out existing numeric prefix
+string(REGEX REPLACE "^[0-9][0-9][0-9][0-9]-" "" name_part "${DESCRIPTION}")
+# spaces to dashes
+string(REPLACE " " "-" name_part "${name_part}")
+# strip out non-alphanumeric or dash characters
+string(REGEX REPLACE "[^a-zA-Z0-9-]" "" name_part "${name_part}")
+# collapse consecutive dashes
+string(REGEX REPLACE "-+" "-" name_part "${name_part}")
+# strip leading/trailing dashes
+string(REGEX REPLACE "^-|-$" "" name_part "${name_part}")
+
+if (NOT name_part)
+ set(name_part "patch")
+ echo_error("Warning: could not determine patch name")
+endif()
+
+# Truncate to 49 chars (60 - num prefix - `.patch` suffix)
+string(SUBSTRING "${name_part}" 0 49 name_part)
+
+# And remove any trailing dashes
+string(REGEX REPLACE "-$" "" name_part "${name_part}")
+
+# now construct and save patch
+set(patch_name "${padded_patch_number}-${name_part}.patch")
+
+file(WRITE "${patch_dir}/${patch_name}" "${patch_content}")
+
+echo("-- Patch created at ${patch_dir}/${patch_name}")
+file(REMOVE_RECURSE ${TMP})
+
+# Now add to cpmfile.
+get_cpmfile_content(content)
+
+# Build new patches JSON array
+set(new_patches "[")
+if(patches)
+ string(JSON existing GET "${content}" "${KEY}" "patches")
+ string(JSON len LENGTH "${existing}")
+ math(EXPR range_end "${len} - 1")
+ foreach(idx RANGE ${range_end})
+ string(JSON val GET "${existing}" ${idx})
+ string(APPEND new_patches "\"${val}\",")
+ endforeach()
+endif()
+string(APPEND new_patches "\"${patch_name}\"]")
+
+# Update the cpmfile
+string(JSON content SET "${content}" "${KEY}" patches "${new_patches}")
+get_cpmfile_path(file_path)
+file(WRITE "${file_path}" "${content}")
+format_cpmfile()
+
diff --git a/tools/cpm/cmake/package/reset.cmake b/tools/cpm/cmake/package/reset.cmake
new file mode 100755
index 0000000000..2b210e4f64
--- /dev/null
+++ b/tools/cpm/cmake/package/reset.cmake
@@ -0,0 +1,34 @@
+#!/usr/bin/env -S cmake -P
+
+# SPDX-FileCopyrightText: Copyright 2026 crueter
+# SPDX-License-Identifier: LGPL-3.0-or-later
+
+cmake_minimum_required(VERSION 3.31)
+
+include(${CMAKE_CURRENT_LIST_DIR}/../ScriptUtils.cmake)
+
+function(usage)
+ echo([=[
+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.
+
+Options:
+ -a, --all Operate on all packages in this project.
+]=])
+endfunction()
+
+set(NO_CI TRUE)
+parse_script_args(args)
+
+foreach(key ${args})
+ if (ci)
+ continue()
+ endif()
+
+ parse_key(${key})
+ echo("-- ${key}")
+
+ fetch_package_object(FORCE)
+endforeach()
diff --git a/tools/cpm/cmake/package/rm.cmake b/tools/cpm/cmake/package/rm.cmake
new file mode 100755
index 0000000000..2547758920
--- /dev/null
+++ b/tools/cpm/cmake/package/rm.cmake
@@ -0,0 +1,31 @@
+#!/usr/bin/env -S cmake -P
+
+# SPDX-FileCopyrightText: Copyright 2026 crueter
+# SPDX-License-Identifier: LGPL-3.0-or-later
+
+cmake_minimum_required(VERSION 3.31)
+
+include(${CMAKE_CURRENT_LIST_DIR}/../ScriptUtils.cmake)
+
+function(usage)
+ echo([=[
+Usage: cpmutil.sh package rm [PACKAGE]...
+
+Delete a package or packages' cpmfile definition.
+]=])
+endfunction()
+
+set(NO_ALL TRUE)
+parse_script_args(args)
+
+get_cpmfile_content(object)
+
+# Remove key
+foreach(key ${args})
+ string(JSON object REMOVE "${object}" ${key})
+endforeach()
+
+# write
+get_cpmfile_path(file)
+file(WRITE ${file} "${object}")
+format_cpmfile() \ No newline at end of file
diff --git a/tools/cpm/cmake/package/update.cmake b/tools/cpm/cmake/package/update.cmake
new file mode 100644
index 0000000000..82ea70340a
--- /dev/null
+++ b/tools/cpm/cmake/package/update.cmake
@@ -0,0 +1,97 @@
+#!/usr/bin/env -S cmake -P
+
+# SPDX-FileCopyrightText: Copyright 2026 crueter
+# SPDX-License-Identifier: LGPL-3.0-or-later
+
+cmake_minimum_required(VERSION 3.31)
+
+include(${CMAKE_CURRENT_LIST_DIR}/../ScriptUtils.cmake)
+
+function(usage)
+ echo([=[
+Usage: cpmutil.sh package update [-a|--all] [-c|--commit] [PACKAGE]...
+
+Check for updates for a package or packages.
+
+Options:
+ -a, --all Operate on all packages in this project.
+ -c, --commit Automatically generate a commit message
+]=])
+endfunction()
+
+set(NO_CI TRUE)
+
+parse_script_args(args)
+
+get_cpmfile_content(cpmfile)
+set(update_log "")
+set(changed FALSE)
+
+foreach(key ${args})
+ parse_key(${key})
+
+ get_latest_tag(tag)
+
+ if (${tag} STREQUAL null)
+ continue()
+ elseif(NOT ${tag} STREQUAL ${version})
+ if (numeric_version)
+ set(old_version ${numeric_version})
+ echo("${key}: ${old_version} -> ${tag}")
+ set(numeric_version ${tag})
+ get_json_element("${object}" version version)
+ else()
+ set(old_version ${version})
+ echo("${key}: ${old_version} -> ${tag}")
+ set(version ${tag})
+ endif()
+
+ get_json_element("${object}" artifact artifact)
+
+ # Redo version replacements
+ process_version_replacements()
+
+ get_package_url_object(pkg_url)
+ get_package_hash("${pkg_url}" pkg_hash)
+
+ if (numeric_version)
+ modify_package_numeric("${object}"
+ "${tag}" "${pkg_hash}" new_object)
+ else()
+ modify_package("${object}" "${tag}" "${pkg_hash}" new_object)
+ endif()
+
+ # update cached cpmfile content
+ string(JSON cpmfile SET "${cpmfile}" "${key}" "${new_object}")
+
+ # used for commit
+ string(APPEND update_log "* ${key}: ${old_version} -> ${tag}\n")
+ set(changed TRUE)
+ else()
+ echo("${key}: Up to date")
+ endif()
+endforeach()
+
+get_cpmfile_path(file)
+file(WRITE ${file} "${cpmfile}")
+format_cpmfile()
+
+if(MAKE_COMMIT AND changed)
+ mktempdir(TMP)
+
+ find_package(Git QUIET)
+
+ if (NOT Git_FOUND)
+ fatal("Git is required to be installed for --commit,"
+ "but it could not be found.")
+ endif()
+
+ set(msg_file ${TMP}/commit_msg.txt)
+ file(WRITE ${msg_file} "Update dependencies\n\n${update_log}")
+ execute_process(COMMAND ${GIT_EXECUTABLE} add cpmfile.json
+ WORKING_DIRECTORY ${CMAKE_SOURCE_DIR})
+ execute_process(COMMAND ${GIT_EXECUTABLE} commit -F ${msg_file}
+ WORKING_DIRECTORY ${CMAKE_SOURCE_DIR})
+
+ file(REMOVE_RECURSE ${TMP})
+endif()
diff --git a/tools/cpm/cmake/package/url.cmake b/tools/cpm/cmake/package/url.cmake
new file mode 100755
index 0000000000..cfc1d41037
--- /dev/null
+++ b/tools/cpm/cmake/package/url.cmake
@@ -0,0 +1,28 @@
+#!/usr/bin/env -S cmake -P
+
+# SPDX-FileCopyrightText: Copyright 2026 crueter
+# SPDX-License-Identifier: LGPL-3.0-or-later
+
+cmake_minimum_required(VERSION 3.31)
+
+include(${CMAKE_CURRENT_LIST_DIR}/../ScriptUtils.cmake)
+
+function(usage)
+ echo([=[
+Usage: cpmutil.sh package url [-a|--all] [PACKAGE]...
+
+Get the download URL for the specified packages.
+
+Options:
+ -a, --all Operate on all packages in this project.
+]=])
+endfunction()
+
+parse_script_args(args)
+
+foreach(key ${args})
+ parse_key(${key})
+
+ get_package_url_object(pkg_url)
+ echo("${key}: ${pkg_url}")
+endforeach() \ No newline at end of file
diff --git a/tools/cpm/cmake/package/version.cmake b/tools/cpm/cmake/package/version.cmake
new file mode 100755
index 0000000000..6ce42a06cd
--- /dev/null
+++ b/tools/cpm/cmake/package/version.cmake
@@ -0,0 +1,75 @@
+#!/usr/bin/env -S cmake -P
+
+# SPDX-FileCopyrightText: Copyright 2026 crueter
+# SPDX-License-Identifier: LGPL-3.0-or-later
+
+cmake_minimum_required(VERSION 3.31)
+
+include(${CMAKE_CURRENT_LIST_DIR}/../ScriptUtils.cmake)
+
+function(usage)
+ echo([=[
+Usage: cpmutil.sh package version [PACKAGE] [VERSION]
+
+Update a package's version. If the package uses a sha, you must provide a sha,
+and if the package uses a tag, you must provide the fully qualified tag.
+]=])
+endfunction()
+
+set(NO_ALL TRUE)
+# arg parsing
+parse_script_args(args)
+
+list(LENGTH args arg_len)
+if(arg_len GREATER 0)
+ list(GET args 0 KEY)
+endif()
+
+if(arg_len GREATER 1)
+ list(GET args 1 NEW_VERSION)
+endif()
+
+# checks
+if (NOT KEY)
+ fatal("You must provide a key")
+endif()
+
+if (NOT NEW_VERSION)
+ fatal("You must provide a version")
+endif()
+
+# action
+get_cpmfile_content(cpmfile)
+parse_key("${KEY}")
+
+if (numeric_version)
+ set(numeric_version ${NEW_VERSION})
+ get_json_element("${object}" version version)
+else()
+ set(version ${NEW_VERSION})
+endif()
+
+get_json_element("${object}" artifact artifact)
+
+# Redo version replacements
+process_version_replacements()
+
+get_package_url_object(pkg_url)
+get_package_hash("${pkg_url}" pkg_hash)
+
+if (numeric_version)
+ modify_package_numeric("${object}"
+ "${NEW_VERSION}" "${pkg_hash}" new_object)
+else()
+ modify_package("${object}" "${NEW_VERSION}" "${pkg_hash}" new_object)
+endif()
+
+# update cached cpmfile content
+string(JSON cpmfile SET "${cpmfile}" "${key}" "${new_object}")
+
+# write cached cpmfile
+get_cpmfile_path(file)
+file(WRITE ${file} "${cpmfile}")
+format_cpmfile()
+
+echo("-- * Updated")
diff --git a/tools/cpm/cmake/package/which.cmake b/tools/cpm/cmake/package/which.cmake
new file mode 100755
index 0000000000..46c5dcc021
--- /dev/null
+++ b/tools/cpm/cmake/package/which.cmake
@@ -0,0 +1,36 @@
+#!/usr/bin/env -S cmake -P
+
+# SPDX-FileCopyrightText: Copyright 2026 crueter
+# SPDX-License-Identifier: LGPL-3.0-or-later
+
+cmake_minimum_required(VERSION 3.31)
+
+include(${CMAKE_CURRENT_LIST_DIR}/../ScriptUtils.cmake)
+
+function(usage)
+ echo([=[
+Usage: cpmutil.sh package which [PACKAGE]...
+
+Check if a package or packages are defined in the cpmfile.
+]=])
+endfunction()
+
+set(NO_ALL TRUE)
+parse_script_args(args)
+set(exit 0)
+
+get_cpmfile_content(object)
+
+foreach(key ${args})
+ # Check if a key exists
+ string(JSON member ERROR_VARIABLE err GET "${object}" ${key})
+
+ if (NOT err)
+ echo("${key}")
+ else()
+ echo_error("${key} not defined in cpmfile")
+ set(exit 1)
+ endif()
+endforeach()
+
+cmake_language(EXIT ${exit}) \ No newline at end of file
diff --git a/tools/cpm/cmake/update.cmake b/tools/cpm/cmake/update.cmake
new file mode 100755
index 0000000000..79c1fa1d00
--- /dev/null
+++ b/tools/cpm/cmake/update.cmake
@@ -0,0 +1,33 @@
+#!/usr/bin/env -S cmake -P
+
+# SPDX-FileCopyrightText: Copyright 2026 crueter
+# SPDX-License-Identifier: LGPL-3.0-or-later
+
+cmake_minimum_required(VERSION 3.31)
+
+include(${CMAKE_CURRENT_LIST_DIR}/ScriptUtils.cmake)
+
+# Update CPMUtil and its tooling/etc
+set(pwd ${CMAKE_SOURCE_DIR})
+
+set(host "https://git.crueter.xyz")
+set(repo "CMake/CPMUtil")
+set(release "releases/download/continuous")
+set(filename CPMUtil.tar.zst)
+
+mktempdir(TMP)
+
+# Download tarball
+set(url "${host}/${repo}/${release}/${filename}")
+set(file ${TMP}/${filename})
+
+cpm_download(${url} ${file})
+
+# Extract to current working directory
+file(ARCHIVE_EXTRACT
+ INPUT ${file}
+ DESTINATION ${pwd})
+
+# done :)
+echo("Updated CPMUtil")
+file(REMOVE_RECURSE ${TMP}) \ No newline at end of file
diff --git a/tools/cpm/common.sh b/tools/cpm/common.sh
deleted file mode 100755
index 09da6358be..0000000000
--- a/tools/cpm/common.sh
+++ /dev/null
@@ -1,45 +0,0 @@
-#!/bin/sh -e
-
-# SPDX-FileCopyrightText: Copyright 2026 crueter
-# SPDX-License-Identifier: LGPL-3.0-or-later
-
-: "${CPM_SOURCE_CACHE:=$PWD/.cache/cpm}"
-: "${CPMUTIL_PATCH_DIR:=$PWD/.patch}"
-
-# TODO: cache cpmfile defs?
-
-cmd_exists() {
- command -v "$1" >/dev/null 2>&1
-}
-
-must_install() {
- for cmd in "$@"; do
- cmd_exists "$cmd" || { echo "-- $cmd must be installed" && exit 1; }
- done
-}
-
-# Random integer between 100000 and 999999
-_randint() {
- awk 'BEGIN { srand(); print int(100000 + rand() * 900000) }'
-}
-
-# Use mktemp if available, use a local temp dir otherwise
-make_temp_dir() {
- if cmd_exists mktemp; then
- mktemp -d
- else
- TMP="$PWD/.cpm/tmp-$(_randint)"
- mkdir -p "$TMP"
- echo "$TMP"
- fi
-}
-
-# must_install jq find mktemp tar 7z unzip sha512sum git patch curl
-
-if [ ! -s cpmfile.json ]; then
- # TODO: actually make it a no-op
- echo "-- Warning: cpmfile.json does not exist or is empty, most commands will be no-ops"
-else
- LIBS=$(jq -j 'keys_unsorted | join(" ")' cpmfile.json)
- export LIBS
-fi
diff --git a/tools/cpm/migrate.sh b/tools/cpm/migrate.sh
index 8be2b1786c..fd4d6880db 100755
--- a/tools/cpm/migrate.sh
+++ b/tools/cpm/migrate.sh
@@ -6,14 +6,22 @@
SUBMODULES="$(git submodule status --recursive | cut -c2-)"
: "${SUBMODULES:?No submodules defined!}"
-tmp=$(mktemp)
-printf '{}' >"$tmp"
-
IFS="
"
for i in $SUBMODULES; do
- sha=$(echo "$i" | cut -d" " -f1 | cut -c1-10)
- ver=$(echo "$i" | cut -d" " -f3 | tr -d '()')
+ commit=$(echo "$i" -d" " -f1 | cut -c1-10)
+ short_commit=$(echo "$i" -d" " -f1 | cut -c1-7)
+
+ ref=$(echo "$i" | cut -d" " -f3 | tr -d '()')
+
+ case "$ref" in
+ # ref == commit, use commit versioning
+ "$short_commit") version="$commit" ;;
+ # ref is a branch, use commit versioning
+ heads/*) version="$commit" ;;
+ # ref is (probably) a tag, use tag versioning
+ *) version="$ref" ;;
+ esac
path=$(echo "$i" | cut -d" " -f2)
name=$(echo "$path" | awk -F/ '{print $NF}')
@@ -21,26 +29,9 @@ for i in $SUBMODULES; do
remote=$(git -C "$path" remote get-url origin)
host=$(echo "$remote" | cut -d"/" -f3)
- [ "$host" != github.com ] || host=
repo=$(echo "$remote" | cut -d"/" -f4-5 | cut -d'.' -f1)
- entry=$(jq -n --arg name "$name" \
- --arg sha "$sha" \
- --arg ver "$ver" \
- --arg repo "$repo" \
- --arg host "$host" \
- '{
- ($name): {
- sha: $sha,
- version: $ver,
- repo: $repo
- } + (if $host != "" then {git_host: $host} else {} end)
- }')
-
- jq --argjson new "$entry" '. + $new' "$tmp" >"${tmp}.new"
- mv "$tmp.new" "$tmp"
+ cmake -DKEY="$name" -DVERSION="$version" -DREPO="$repo" -DGIT_HOST="$host" \
+ -P "$CMAKE/package/add.cmake"
done
-
-jq '.' "$tmp" >cpmfile.json
-rm -f "$tmp"
diff --git a/tools/cpm/package.sh b/tools/cpm/package.sh
index bf2f3feaa7..8246222d50 100755
--- a/tools/cpm/package.sh
+++ b/tools/cpm/package.sh
@@ -12,17 +12,17 @@ Usage: cpmutil.sh package [command]
Operate on a package or packages.
Commands:
- hash Verify the hash of a package, and update it if needed
- update Check for updates for a package
- fetch Fetch a package and place it in the cache
- add Add a new package
- rm Remove a package
- version Change the version of a package
- which Check if a package is defined
- download Get the download URL for a package
- dir Get the local directory for a package
- reset Reset a fetched package to its original state
- patch Create an in-tree patch based on local modifications
+ hash Verify the hash of a package, and update it if needed
+ update Check for updates for a package
+ fetch Fetch a package and place it in the cache
+ add Add a new package
+ rm Remove a package
+ version Change the version of a package
+ which Check if a package is defined
+ url Get the download URL for a package
+ dir Get the local directory for a package
+ reset Reset a fetched package to its original state
+ patch Add a patch to a package in the cpmfile
EOF
@@ -30,11 +30,48 @@ EOF
}
SCRIPTS=$(CDPATH='' cd -- "$(dirname -- "$0")/package" && pwd)
-export SCRIPTS
+CMAKE="$CMAKE/package"
+
+export SCRIPTS CMAKE
+
+filter_args() {
+ print_usage=false
+ all_flag=false
+ commit_flag=false
+ filtered=""
+
+ for arg in "$@"; do
+ case "$arg" in
+ -h | --help) print_usage=true ;;
+ -a | --all) all_flag=true ;;
+ -c | --commit) commit_flag=true ;;
+ -ac | -ca)
+ commit_flag=true
+ all_flag=true
+ ;;
+ *) filtered="$filtered $arg" ;;
+ esac
+ done
+}
while :; do
case "$1" in
- hash | update | fetch | add | rm | version | which | download | reset | patch | dir)
+ dir | fetch | hash | reset | rm | url | version | which | update)
+ cmd="$1"
+ shift
+
+ filter_args "$@"
+ cmake_defines=""
+
+ if $print_usage; then cmake_defines="$cmake_defines -DPRINT_USAGE=TRUE"; fi
+ if $all_flag; then cmake_defines="$cmake_defines -DALL_PACKAGES=TRUE"; fi
+ if $commit_flag; then cmake_defines="$cmake_defines -DMAKE_COMMIT=TRUE"; fi
+
+ # shellcheck disable=SC2086
+ cmake $cmake_defines -P "$CMAKE/$cmd.cmake" -- $filtered
+ break
+ ;;
+ add | patch)
cmd="$1"
shift
"$SCRIPTS/$cmd".sh "$@"
diff --git a/tools/cpm/package/add.sh b/tools/cpm/package/add.sh
index 8531f524fb..0129613931 100755
--- a/tools/cpm/package/add.sh
+++ b/tools/cpm/package/add.sh
@@ -49,6 +49,153 @@ done
[ -n "$PKG" ] || die "You must specify a package name."
-export PKG
+# This reads a single-line input from the user and also gives them
+# help if needed.
+# $1: The prompt itself, without any trailing spaces or whatever
+# $2: The help text that gets shown when the user types a question mark
+# $3: This is set to "required" if it's necessary,
+# otherwise it can continue without input.
+# Stores its output in the "reply" variable
+read_single() {
+ while :; do
+ printf -- "-- %s" "$1"
+ [ -z "$2" ] || printf " (? for help, %s)" "$3"
+ printf ": "
+ if ! IFS= read -r reply; then
+ echo
+ [ "$3" = "required" ] && continue || reply=""
+ fi
+ case "$reply" in
+ "?") echo "$2" ;;
+ "") [ "$3" = "required" ] && continue || return 0 ;;
+ *) return 0 ;;
+ esac
+ done
+}
+
+# read_single, but optional
+optional() {
+ read_single "$1" "$2" "optional"
+}
+
+# a
+required() {
+ read_single "$1" "$2" "required"
+}
+
+# Basically the same as the single line function except multiline,
+# also it's never "required" so we don't need that handling.
+multi() {
+ echo "-- $1"
+ if [ -n "$2" ]; then
+ echo "-- (? on first line for help, Ctrl-D to finish)"
+ else
+ echo "-- (Ctrl-D to finish)"
+ fi
+ while :; do
+ reply=$(cat)
+ if [ "$(echo "$reply" | head -n 1)" = "?" ] && [ -n "$2" ]; then
+ echo "$2"
+ continue
+ fi
+
+ # removes trailing EOF and empty lines
+ reply=$(printf '%s\n' "$reply" |
+ sed 's/\x04$//' |
+ sed '/^[[:space:]]*$/d')
+
+ break
+ done
+}
+
+# the actual inputs :)
+
+required "Package repository (owner/repo)" \
+ "The remote repository this is stored on.
+You shouldn't include the host, just owner/repo is enough."
+
+REPO="$reply"
+
+required "Version of the bundled package" \
+ "The tag or commit hash of the bundled package."
+
+VERSION="$reply"
+
+optional "Package name for find_package" \
+ "When searching for system packages, this argument will be passed to find_package.
+For example, using \"Boost\" here will result in CPMUtil internally calling find_package(Boost).
+If unset, defaults to the JSON key."
+
+PACKAGE="$reply"
+
+optional "Minimum required version" \
+ "The minimum required version for this package if it's pulled in by the system."
+
+MIN_VERSION="$reply"
+
+optional "Additional find_package arguments, space-separated" \
+ "Extra arguments passed to find_package(), (e.g. CONFIG)"
+
+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"
+
+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."
+
+case "$reply" in
+[Yy]*) CI=true ;;
+*) CI=false ;;
+esac
+
+if [ "$CI" = "false" ]; then
+ optional "Name of the release artifact to download, if applicable.
+-- %VERSION% is replaced by the version ($VERSION)" \
+ "Download the specified artifact from the release with the previously specified tag."
+
+ ARTIFACT="$reply"
+
+ multi "Fixed options, one per line (e.g. OPUS_BUILD_TESTING OFF)" \
+ "Fixed options passed to the project's CMakeLists.txt. Variadic options
+should be set in CMake with AddJsonPackage's OPTIONS parameter."
+
+ OPTIONS="$reply"
+else
+ required "Name of the CI artifact" \
+ "CI artifacts are stored as <name>-<platform>-<version>.tar.zst. This option controls the name."
+
+ ARTIFACT="$reply"
+
+ multi "Platforms without a package (one per line)" \
+ "Valid platforms:
+windows-amd64 windows-arm64
+mingw-amd64 mingw-arm64
+android-aarch64 android-x86_64
+linux-amd64 linux-aarch64
+macos-universal ios-aarch64"
+
+ DISABLED_PLATFORMS="$reply"
+fi
+
+# invoke add.cmake for validation
+set -- "$@" \
+ -DKEY="$PKG" \
+ -DREPO="$REPO" \
+ -DVERSION="$VERSION" \
+ -DCI="$CI"
+
+[ -z "$PACKAGE" ] || set -- "$@" -DPACKAGE="$PACKAGE"
+[ -z "$GIT_HOST" ] || set -- "$@" -DGIT_HOST="$GIT_HOST"
+[ -z "$MIN_VERSION" ] || set -- "$@" -DMIN_VERSION="$MIN_VERSION"
+[ -z "$FIND_ARGS" ] || set -- "$@" -DFIND_ARGS="$FIND_ARGS"
+[ -z "$OPTIONS" ] || set -- "$@" -DOPTIONS="$(echo "$OPTIONS" | tr '\n' ';')"
+[ -z "$ARTIFACT" ] || set -- "$@" -DARTIFACT="$ARTIFACT"
+[ -z "$DISABLED_PLATFORMS" ] || set -- "$@" -DDISABLED_PLATFORMS="$(echo "$DISABLED_PLATFORMS" | tr '\n' ';')"
+
+cmake "$@" -P "$CMAKE"/add.cmake
-"$SCRIPTS"/util/interactive.sh
+echo "Added package $PKG to cpmfile.json. Include it in your project with AddJsonPackage($PKG)"
diff --git a/tools/cpm/package/dir.sh b/tools/cpm/package/dir.sh
deleted file mode 100755
index 82a220509d..0000000000
--- a/tools/cpm/package/dir.sh
+++ /dev/null
@@ -1,57 +0,0 @@
-#!/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
diff --git a/tools/cpm/package/download.sh b/tools/cpm/package/download.sh
deleted file mode 100755
index 61cfaaefae..0000000000
--- a/tools/cpm/package/download.sh
+++ /dev/null
@@ -1,47 +0,0 @@
-#!/bin/sh -e
-
-# SPDX-FileCopyrightText: Copyright 2026 crueter
-# SPDX-License-Identifier: LGPL-3.0-or-later
-
-usage() {
- cat <<EOF
-Usage: cpmutil.sh package download [-a|--all] [PACKAGE]...
-
-Get the download URL 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
-
- if [ "$CI" = "true" ]; then
- echo "-- $PACKAGE: https://$GIT_HOST/$REPO"
- else
- echo -- "$PACKAGE: $DOWNLOAD"
- fi
-done
diff --git a/tools/cpm/package/fetch.sh b/tools/cpm/package/fetch.sh
deleted file mode 100755
index 774ecc7a29..0000000000
--- a/tools/cpm/package/fetch.sh
+++ /dev/null
@@ -1,44 +0,0 @@
-#!/bin/sh -e
-
-# SPDX-FileCopyrightText: Copyright 2026 crueter
-# SPDX-License-Identifier: LGPL-3.0-or-later
-
-# shellcheck disable=SC1091
-. "$SCRIPTS/util/fetch.sh"
-
-usage() {
- cat <<EOF
-Usage: cpmutil.sh package fetch [a|--all] [PACKAGE]...
-
-Fetch the specified package or packages from their defined download locations.
-If the package is already cached, it will not be re-fetched.
-
-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
-
- fetch_package
-done
diff --git a/tools/cpm/package/hash.sh b/tools/cpm/package/hash.sh
deleted file mode 100755
index bce46ecd6c..0000000000
--- a/tools/cpm/package/hash.sh
+++ /dev/null
@@ -1,91 +0,0 @@
-#!/bin/sh -e
-
-# SPDX-FileCopyrightText: Copyright 2026 crueter
-# SPDX-License-Identifier: LGPL-3.0-or-later
-
-RETURN=0
-
-usage() {
- cat <<EOF
-Usage: cpmutil.sh package hash [-n|--dry-run] [-a|--all] [PACKAGE]...
-
-Check the hash of a specific package or packages.
-If a hash mismatch occurs, this script will update the package's hash.
-
-Options:
- -n, --dry-run Don't update the package's hash if it's a mismatch
- -a, --all Operate on all packages in this project.
-
-Note that this procedure will usually take a long time
-depending on the number and size of dependencies.
-
-EOF
-
- exit $RETURN
-}
-
-while :; do
- case "$1" in
- -[a-z]*)
- opt=$(printf '%s' "$1" | sed 's/^-//')
- while [ -n "$opt" ]; do
- # cut out first char from the optstring
- char=$(echo "$opt" | cut -c1)
- opt=$(echo "$opt" | cut -c2-)
-
- case "$char" in
- a) ALL=1 ;;
- n) DRY=1 ;;
- h) usage ;;
- *) die "Invalid option -$char" ;;
- esac
- done
- ;;
- --dry-run) DRY=1 ;;
- --all) ALL=1 ;;
- --help) usage ;;
- "$0") break ;;
- "") break ;;
- *) packages="$packages $1" ;;
- esac
-
- shift
-done
-
-[ "$ALL" != 1 ] || packages="${LIBS:-$packages}"
-[ "$DRY" = 1 ] && UPDATE=false || UPDATE=true
-[ -n "$packages" ] || usage
-
-export UPDATE
-
-for pkg in $packages; do
- unset JSON
- echo "-- Package $pkg"
-
- 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
diff --git a/tools/cpm/package/patch.sh b/tools/cpm/package/patch.sh
index 1368c70f1d..0dc58b033b 100755
--- a/tools/cpm/package/patch.sh
+++ b/tools/cpm/package/patch.sh
@@ -4,170 +4,13 @@
# 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
+printf -- "-- Enter a patch description: "
+if ! read -r description; then
+ echo "" >&2
+ echo "-- Patch cancelled" >&2
+ rm -rf "$TMP"
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"
+cmake -DDESCRIPTION="$description" -P "$CMAKE"/patch.cmake "$@"
diff --git a/tools/cpm/package/reset.sh b/tools/cpm/package/reset.sh
deleted file mode 100755
index 6e98c00d48..0000000000
--- a/tools/cpm/package/reset.sh
+++ /dev/null
@@ -1,56 +0,0 @@
-#!/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
diff --git a/tools/cpm/package/rm.sh b/tools/cpm/package/rm.sh
deleted file mode 100755
index ece1898ae0..0000000000
--- a/tools/cpm/package/rm.sh
+++ /dev/null
@@ -1,30 +0,0 @@
-#!/bin/sh -e
-
-# SPDX-FileCopyrightText: Copyright 2026 crueter
-# SPDX-License-Identifier: LGPL-3.0-or-later
-
-RETURN=0
-
-usage() {
- cat <<EOF
-Usage: cpmutil.sh package rm [PACKAGE]...
-
-Delete a package or packages' cpmfile definition.
-
-EOF
-
- exit $RETURN
-}
-
-[ $# -ge 1 ] || usage
-
-for pkg in "$@"; do
- "$SCRIPTS"/which.sh "$pkg" || {
- echo "!! No cpmfile definition for $pkg"
- continue
- }
-
- jq --indent 4 "del(.\"$pkg\")" cpmfile.json >cpmfile.json.new
- mv cpmfile.json.new cpmfile.json
- echo "-- Removed $pkg"
-done
diff --git a/tools/cpm/package/update.sh b/tools/cpm/package/update.sh
deleted file mode 100755
index 96e143f662..0000000000
--- a/tools/cpm/package/update.sh
+++ /dev/null
@@ -1,174 +0,0 @@
-#!/bin/sh -e
-
-# SPDX-FileCopyrightText: Copyright 2026 crueter
-# SPDX-License-Identifier: LGPL-3.0-or-later
-
-filter_out() {
- TAGS=$(echo "$TAGS" | jq "[.[] | select(.name | test(\"$1\"; \"i\") | not)]")
-}
-
-filter_in() {
- TAGS=$(echo "$TAGS" | jq "[.[] | select(.name | test(\"$1\"; \"i\"))]")
-}
-
-usage() {
- cat <<EOF
-Usage: cpmutil.sh package update [-n|--dry-run] [-a|--all] [PACKAGE]...
-
-Check a specific package or packages for updates.
-
-Options:
- -n, --dry-run Do not update the package if it has an update available
- -a, --all Operate on all packages in this project.
- -c, --commit Automatically generate a commit message
-
-EOF
-
- exit 0
-}
-
-while :; do
- case "$1" in
- -[a-z]*)
- opt=$(printf '%s' "$1" | sed 's/^-//')
- while [ -n "$opt" ]; do
- # cut out first char from the optstring
- char=$(echo "$opt" | cut -c1)
- opt=$(echo "$opt" | cut -c2-)
-
- case "$char" in
- a) ALL=1 ;;
- n) UPDATE=false ;;
- c) COMMIT=true ;;
- h) usage ;;
- *) die "Invalid option -$char" ;;
- esac
- done
- ;;
- --dry-run) UPDATE=false ;;
- --all) ALL=1 ;;
- --help) usage ;;
- --commit) COMMIT=true ;;
- "$0") break ;;
- "") break ;;
- *) packages="$packages $1" ;;
- esac
-
- shift
-done
-
-[ "$ALL" != 1 ] || packages="${LIBS:-$packages}"
-: "${UPDATE:=true}"
-: "${COMMIT:=false}"
-[ -n "$packages" ] || usage
-
-for pkg in $packages; do
- unset JSON
- export PACKAGE="$pkg"
-
- # shellcheck disable=SC1091
- . "$SCRIPTS"/vars.sh
-
- SKIP=$(value "skip_updates")
-
- [ "$SKIP" != "true" ] || continue
-
- [ "$REPO" != null ] || continue
- [ "$GIT_HOST" = "github.com" ] || continue # TODO
-
- [ "$CI" != "true" ] || continue
-
- # shellcheck disable=SC2153
- [ "$TAG" != null ] || continue
-
- echo "-- Package $PACKAGE"
-
- # 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")
- 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
- # TODO add more
-
- if [ "$PACKAGE" = "vulkan-validation-layers" ]; then
- filter_in vulkan-sdk
- else
- filter_out vulkan-sdk
- fi
-
- filter_out yotta # mbedtls
-
- filter_out vksc
-
- # ignore betas/alphas (remove if needed)
- filter_out alpha
- filter_out beta
- filter_out rc
-
- # 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
-
- LATEST=$(echo "$TAGS" | jq -r '.[0].name')
-
- if [ "$LATEST" = "null" ] ||
- { [ "$LATEST" = "$TAG" ] && [ "$FORCE" != "true" ]; }; then
- echo "-- * Up-to-date"
- 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 version
- if [ -z "$VERSION_PREFIX" ]; then
- NEW_VERSION="$LATEST"
- else
- NEW_VERSION=$(echo "$LATEST" | sed "s/$VERSION_PREFIX//g")
- fi
- else
- NEW_VERSION="$LATEST"
- fi
-
- _commit="$_commit
-* $PACKAGE: $VERSION -> $NEW_VERSION"
-
- echo "-- * Version $LATEST available, current is $TAG"
-
- if [ "$UPDATE" = "true" ]; then
- if [ "$HAS_REPLACE" = "true" ]; then
- JSON=$(echo "$JSON" | jq ".version = \"$NEW_VERSION\"")
- else
- JSON=$(echo "$JSON" | jq ".tag = \"$NEW_VERSION\"")
- fi
-
- echo "-- * -- Updating hash"
-
- # 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
- git add "cpmfile.json"
- git commit -m "Update dependencies
-$_commit"
-fi
diff --git a/tools/cpm/package/util/fetch.sh b/tools/cpm/package/util/fetch.sh
deleted file mode 100755
index 7db568f3e6..0000000000
--- a/tools/cpm/package/util/fetch.sh
+++ /dev/null
@@ -1,134 +0,0 @@
-#!/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
-}
diff --git a/tools/cpm/package/util/fix-hash.sh b/tools/cpm/package/util/fix-hash.sh
deleted file mode 100755
index 476b15af89..0000000000
--- a/tools/cpm/package/util/fix-hash.sh
+++ /dev/null
@@ -1,28 +0,0 @@
-#!/bin/sh -e
-
-# SPDX-FileCopyrightText: Copyright 2026 crueter
-# SPDX-License-Identifier: LGPL-3.0-or-later
-
-# shellcheck disable=SC1091
-
-: "${PACKAGE:=$1}"
-
-# re-read json files
-# shellcheck disable=SC2016
-. "$SCRIPTS"/vars.sh
-
-[ "$CI" = null ] || exit 0
-
-ACTUAL=$("$SCRIPTS"/util/url-hash.sh "$DOWNLOAD")
-
-if [ "$ACTUAL" != "$HASH" ] && [ "$QUIET" != true ]; then
- echo "-- * Expected $HASH"
- echo "-- * Got $ACTUAL"
- [ "$UPDATE" != "true" ] && exit 1
-fi
-
-if [ "$UPDATE" = "true" ] && [ "$ACTUAL" != "$HASH" ]; then
- NEW_JSON=$(echo "$JSON" | jq ".hash = \"$ACTUAL\"")
-
- "$SCRIPTS"/util/replace.sh "$PACKAGE" "$NEW_JSON"
-fi
diff --git a/tools/cpm/package/util/interactive.sh b/tools/cpm/package/util/interactive.sh
deleted file mode 100755
index 1f5a16aa07..0000000000
--- a/tools/cpm/package/util/interactive.sh
+++ /dev/null
@@ -1,228 +0,0 @@
-#!/bin/sh -e
-
-# SPDX-FileCopyrightText: Copyright 2026 crueter
-# SPDX-License-Identifier: LGPL-3.0-or-later
-
-# This reads a single-line input from the user and also gives them
-# help if needed.
-# $1: The prompt itself, without any trailing spaces or whatever
-# $2: The help text that gets shown when the user types a question mark
-# $3: This is set to "required" if it's necessary,
-# otherwise it can continue without input.
-# Stores its output in the "reply" variable
-read_single() {
- while :; do
- printf -- "-- %s" "$1"
- [ -z "$2" ] || printf " (? for help, %s)" "$3"
- printf ": "
- if ! IFS= read -r reply; then
- echo
- [ "$3" = "required" ] && continue || reply=""
- fi
- case "$reply" in
- "?") echo "$2" ;;
- "") [ "$3" = "required" ] && continue || return 0 ;;
- *) return 0 ;;
- esac
- done
-}
-
-# read_single, but optional
-optional() {
- read_single "$1" "$2" "optional"
-}
-
-# a
-required() {
- read_single "$1" "$2" "required"
-}
-
-# Basically the same as the single line function except multiline,
-# also it's never "required" so we don't need that handling.
-multi() {
- echo "-- $1"
- if [ -n "$2" ]; then
- echo "-- (? on first line for help, Ctrl-D to finish)"
- else
- echo "-- (Ctrl-D to finish)"
- fi
- while :; do
- reply=$(cat)
- if [ "$(echo "$reply" | head -n 1)" = "?" ] && [ -n "$2" ]; then
- echo "$2"
- continue
- fi
-
- # removes trailing EOF and empty lines
- reply=$(printf '%s\n' "$reply" |
- sed 's/\x04$//' |
- sed '/^[[:space:]]*$/d')
-
- break
- done
-}
-
-# the actual inputs :)
-
-required "Package repository (owner/repo)" \
- "The remote repository this is stored on.
-You shouldn't include the host, just owner/repo is enough."
-
-REPO="$reply"
-
-optional "Package name for find_package" \
- "When searching for system packages, this argument will be passed to find_package.
-For example, using \"Boost\" here will result in CPMUtil internally calling find_package(Boost)."
-
-PACKAGE="$reply"
-
-optional "Minimum required version" \
- "The minimum required version for this package if it's pulled in by the system."
-
-MIN_VERSION="$reply"
-
-optional "Additional find_package arguments, space-separated" \
- "Extra arguments passed to find_package(), (e.g. CONFIG)"
-
-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."
-
-case "$reply" in
-[Yy]*) CI=true ;;
-*) CI=false ;;
-esac
-
-if [ "$CI" = "false" ]; then
- 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"
-
- 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
- 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 ($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."
-
- ARTIFACT="$reply"
- else
- required "Commit sha" \
- "The short Git commit sha to use. You're recommended to keep this short, e.g. 10 characters."
-
- SHA="$reply"
- fi
-
- multi "Fixed options, one per line (e.g. OPUS_BUILD_TESTING OFF)" \
- "Fixed options passed to the project's CMakeLists.txt. Variadic options
-should be set in CMake with AddJsonPackage's OPTIONS parameter."
-
- OPTIONS="$reply"
-else
- required "Name of the CI artifact" \
- "CI artifacts are stored as <name>-<platform>-<version>.tar.zst. This option controls the name."
-
- ARTIFACT="$reply"
-
- multi "Platforms without a package (one per line)" \
- "Valid platforms:
-windows-amd64 windows-arm64
-mingw-amd64 mingw-arm64
-android-aarch64 android-x86_64
-linux-amd64 linux-aarch64
-macos-universal ios-aarch64"
-
- DISABLED_PLATFORMS="$reply"
-fi
-
-# now time to construct the actual json
-jq_input='{repo: "'"$REPO"'"}'
-
-# common trivial fields
-[ -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,
- artifact: \"$ARTIFACT\"
- }"
-
- # disabled platforms
- if [ -n "$DISABLED_PLATFORMS" ] && [ -n "$(printf '%s' "$DISABLED_PLATFORMS" | tr -d ' \t\n\r')" ]; then
- disabled_json=$(printf '%s\n' "$DISABLED_PLATFORMS" | jq -R . | jq -s .)
- jq_input="$jq_input + {disabled_platforms: $disabled_json}"
- fi
-else
- [ -z "$MIN_VERSION" ] || jq_input="$jq_input + {version: \"$MIN_VERSION\"}"
- jq_input="$jq_input + {hash: \"\"}"
-
- # options
- if [ -n "$OPTIONS" ] && [ -n "$(printf '%s' "$OPTIONS" | tr -d ' \t\n\r')" ]; then
- options_json=$(printf '%s\n' "$OPTIONS" | jq -R . | jq -s .)
- jq_input="$jq_input + {options: $options_json}"
- fi
-
- # versioning stuff
- 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
-
-JSON=$(jq -n "$jq_input")
-
-# shellcheck disable=SC1091
-. "$SCRIPTS"/vars.sh
-
-if [ "$CI" != true ]; then
- HASH=$("$SCRIPTS"/util/url-hash.sh "$DOWNLOAD")
- JSON=$(echo "$JSON" | jq ".hash = \"$HASH\"")
-fi
-
-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)"
diff --git a/tools/cpm/package/util/replace.sh b/tools/cpm/package/util/replace.sh
deleted file mode 100755
index 7141747a12..0000000000
--- a/tools/cpm/package/util/replace.sh
+++ /dev/null
@@ -1,11 +0,0 @@
-#!/bin/sh -e
-
-# SPDX-FileCopyrightText: Copyright 2026 crueter
-# SPDX-License-Identifier: LGPL-3.0-or-later
-
-# Replace a specified package with a modified json.
-
-jq --indent 4 --argjson repl "$2" ".\"$1\" *= \$repl" cpmfile.json >cpmfile.json.new
-mv cpmfile.json.new cpmfile.json
-
-echo "-- * -- Updated cpmfile.json"
diff --git a/tools/cpm/package/util/url-hash.sh b/tools/cpm/package/util/url-hash.sh
deleted file mode 100755
index eae784b53d..0000000000
--- a/tools/cpm/package/util/url-hash.sh
+++ /dev/null
@@ -1,7 +0,0 @@
-#!/bin/sh
-
-# SPDX-FileCopyrightText: Copyright 2025 crueter
-# SPDX-License-Identifier: LGPL-3.0-or-later
-
-SUM=$(curl -Ls "$1" -o - | sha512sum)
-echo "$SUM" | cut -d " " -f1
diff --git a/tools/cpm/package/util/url.sh b/tools/cpm/package/util/url.sh
deleted file mode 100755
index 22a69bf898..0000000000
--- a/tools/cpm/package/util/url.sh
+++ /dev/null
@@ -1,27 +0,0 @@
-#!/bin/sh -e
-
-# SPDX-FileCopyrightText: Copyright 2026 crueter
-# SPDX-License-Identifier: LGPL-3.0-or-later
-
-# Get the download URL for a package
-
-if [ "$URL" != "null" ]; then
- DOWNLOAD="$URL"
-elif [ "$REPO" != "null" ]; then
- GIT_URL="https://$GIT_HOST/$REPO"
-
- 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
- fi
-else
- echo "!! No repo or URL defined for $PACKAGE_NAME"
- exit 1
-fi
-
-export DOWNLOAD
diff --git a/tools/cpm/package/vars.sh b/tools/cpm/package/vars.sh
deleted file mode 100755
index dd497407c8..0000000000
--- a/tools/cpm/package/vars.sh
+++ /dev/null
@@ -1,158 +0,0 @@
-#!/bin/sh -e
-
-# SPDX-FileCopyrightText: Copyright 2026 crueter
-# SPDX-License-Identifier: LGPL-3.0-or-later
-
-# shellcheck disable=SC1091
-
-value() {
- echo "$JSON" | jq -r ".$1"
-}
-
-if [ -z "$JSON" ]; then
- [ -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
-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 MIN_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"
-
-########
-# 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
-
-# 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
-
-######################
-# 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"
-
- NAME=$(value "name")
- DISABLED=$(echo "$JSON" | jq -j '.disabled_platforms')
-
- [ "$NAME" != null ] || NAME="$PACKAGE_NAME"
-
- export EXT
- export NAME
- export DISABLED
-
- return 0
-fi
-
-##############
-# Versioning #
-##############
-
-TAG=$(value "tag")
-ARTIFACT=$(value "artifact")
-SHA=$(value "sha")
-
-if echo "$TAG" | grep -e "%VERSION%" >/dev/null; then
- HAS_REPLACE=true
-else
- HAS_REPLACE=false
-fi
-
-ORIGINAL_TAG="$TAG"
-
-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 ORIGINAL_TAG
-export HAS_REPLACE
-
-###############
-# URL Parsing #
-###############
-
-URL=$(value "url")
-
-. "$SCRIPTS"/util/url.sh
-
-export DOWNLOAD
-
-###############
-# Key Parsing #
-###############
-
-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
-
-################
-# Hash Parsing #
-################
-
-HASH=$(value "hash")
-
-if [ "$HASH" = null ]; then
- echo "!! No hash defined for $PACKAGE_NAME" >&2
-fi
-
-export HASH
-export JSON
diff --git a/tools/cpm/package/version.sh b/tools/cpm/package/version.sh
deleted file mode 100755
index cfeaa27f1e..0000000000
--- a/tools/cpm/package/version.sh
+++ /dev/null
@@ -1,62 +0,0 @@
-#!/bin/sh -e
-
-# SPDX-FileCopyrightText: Copyright 2026 crueter
-# SPDX-License-Identifier: LGPL-3.0-or-later
-
-# shellcheck disable=SC1091
-
-usage() {
- cat <<EOF
-Usage: cpmutil.sh package version [PACKAGE] [VERSION]
-
-Update a package's version. If the package uses a sha, you must provide a sha,
-and if the package uses a tag, you must provide the fully qualified tag.
-
-EOF
-
- exit 0
-}
-
-PACKAGE="$1"
-NEW_VERSION="$2"
-
-[ -n "$PACKAGE" ] || usage
-[ -n "$NEW_VERSION" ] || usage
-
-export PACKAGE
-
-. "$SCRIPTS"/vars.sh
-
-[ "$REPO" != null ] || exit 0
-
-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
- if [ -n "$VERSION_PREFIX" ]; then
- NEW_VERSION=$(echo "$NEW_VERSION" | sed "s/$VERSION_PREFIX//g")
- fi
-fi
-
-if [ "$SHA" != null ]; then
- JSON=$(echo "$JSON" | jq ".sha = \"$NEW_VERSION\"")
-elif [ "$CI" = "true" ] || [ "$HAS_REPLACE" = "true" ]; then
- JSON=$(echo "$JSON" | jq ".version = \"$NEW_VERSION\"")
-else
- JSON=$(echo "$JSON" | jq ".tag = \"$NEW_VERSION\"")
-fi
-
-echo "-- * Updating $PACKAGE to version $NEW_VERSION"
-
-# 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"
diff --git a/tools/cpm/package/which.sh b/tools/cpm/package/which.sh
deleted file mode 100755
index 905d055e87..0000000000
--- a/tools/cpm/package/which.sh
+++ /dev/null
@@ -1,8 +0,0 @@
-#!/bin/sh -e
-
-# SPDX-FileCopyrightText: Copyright 2026 crueter
-# SPDX-License-Identifier: LGPL-3.0-or-later
-
-# check if a package is defined
-
-echo "$LIBS" | grep "$1" >/dev/null 2>&1