Browse Source
[cmake] CPMUtil rewrite of the day number 852 (#4130)
[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>remotes/1783569874749951840/Sync-Settings
No known key found for this signature in database
GPG Key ID: 425ACD2D4830EBC6
45 changed files with 2291 additions and 2977 deletions
-
20.patch/libadrenotools/0001-linkerns-cpm.patch
-
26.patch/libadrenotools/0001-use-cpmfile-def-for-linkernsbypass.patch
-
2CMakeLists.txt
-
1310CMakeModules/CPM.cmake
-
855CMakeModules/CPMUtil.cmake
-
124cpmfile.json
-
154docs/CPMUtil.md
-
3tools/cpm/cmake/README.md
-
341tools/cpm/cmake/ScriptUtils.cmake
-
8tools/cpm/cmake/format.cmake
-
24tools/cpm/cmake/ls.cmake
-
104tools/cpm/cmake/package/add.cmake
-
33tools/cpm/cmake/package/dir.cmake
-
34tools/cpm/cmake/package/fetch.cmake
-
59tools/cpm/cmake/package/hash.cmake
-
155tools/cpm/cmake/package/patch.cmake
-
34tools/cpm/cmake/package/reset.cmake
-
31tools/cpm/cmake/package/rm.cmake
-
97tools/cpm/cmake/package/update.cmake
-
28tools/cpm/cmake/package/url.cmake
-
75tools/cpm/cmake/package/version.cmake
-
36tools/cpm/cmake/package/which.cmake
-
33tools/cpm/cmake/update.cmake
-
45tools/cpm/common.sh
-
39tools/cpm/migrate.sh
-
63tools/cpm/package.sh
-
151tools/cpm/package/add.sh
-
57tools/cpm/package/dir.sh
-
47tools/cpm/package/download.sh
-
44tools/cpm/package/fetch.sh
-
91tools/cpm/package/hash.sh
-
169tools/cpm/package/patch.sh
-
56tools/cpm/package/reset.sh
-
30tools/cpm/package/rm.sh
-
174tools/cpm/package/update.sh
-
134tools/cpm/package/util/fetch.sh
-
28tools/cpm/package/util/fix-hash.sh
-
228tools/cpm/package/util/interactive.sh
-
11tools/cpm/package/util/replace.sh
-
7tools/cpm/package/util/url-hash.sh
-
27tools/cpm/package/util/url.sh
-
158tools/cpm/package/vars.sh
-
62tools/cpm/package/version.sh
-
8tools/cpm/package/which.sh
-
53tools/cpmutil.sh
@ -1,20 +0,0 @@ |
|||
diff --git a/CMakeLists.txt b/CMakeLists.txt
|
|||
index 16c6092..9e75548 100644
|
|||
--- a/CMakeLists.txt
|
|||
+++ b/CMakeLists.txt
|
|||
@@ -8,7 +8,14 @@ project(adrenotools LANGUAGES CXX C)
|
|||
|
|||
set(GEN_INSTALL_TARGET OFF CACHE BOOL "") |
|||
|
|||
-add_subdirectory(lib/linkernsbypass)
|
|||
+include(CPM)
|
|||
+set(CPM_USE_LOCAL_PACKAGES OFF)
|
|||
+
|
|||
+CPMAddPackage(
|
|||
+ NAME linkernsbypass
|
|||
+ URL "https://github.com/bylaws/liblinkernsbypass/archive/aa3975893d.zip"
|
|||
+ URL_HASH SHA512=43d3d146facb7ec99d066a9b8990369ab7b9eec0d5f9a67131b0a0744fde0af27d884ca1f2a272cd113718a23356530ed97703c8c0659c4c25948d50c106119e
|
|||
+)
|
|||
|
|||
set(LIB_SOURCES src/bcenabler.cpp |
|||
src/driver.cpp |
|||
@ -0,0 +1,26 @@ |
|||
From 52bbc5af6523daa22ad62fe4b84bc8d623d11a53 Mon Sep 17 00:00:00 2001 |
|||
From: crueter <crueter@eden-emu.dev> |
|||
Date: Fri, 26 Jun 2026 01:09:40 -0400 |
|||
Subject: [PATCH] use cpmfile def for linkernsbypass |
|||
|
|||
---
|
|||
CMakeLists.txt | 3 ++- |
|||
1 file changed, 2 insertions(+), 1 deletion(-) |
|||
|
|||
diff --git a/CMakeLists.txt b/CMakeLists.txt
|
|||
index 16c6092..85b242c 100644
|
|||
--- a/CMakeLists.txt
|
|||
+++ b/CMakeLists.txt
|
|||
@@ -8,7 +8,8 @@ project(adrenotools LANGUAGES CXX C)
|
|||
|
|||
set(GEN_INSTALL_TARGET OFF CACHE BOOL "") |
|||
|
|||
-add_subdirectory(lib/linkernsbypass)
|
|||
+include(CPMUtil)
|
|||
+AddJsonPackage(linkernsbypass)
|
|||
|
|||
set(LIB_SOURCES src/bcenabler.cpp |
|||
src/driver.cpp |
|||
--
|
|||
2.54.0 |
|||
|
|||
1310
CMakeModules/CPM.cmake
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
855
CMakeModules/CPMUtil.cmake
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -0,0 +1,3 @@ |
|||
# CPMUtil CMake Test Scripts |
|||
|
|||
Testing out some CMake scripting functionality. |
|||
@ -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() |
|||
@ -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() |
|||
@ -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() |
|||
@ -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}") |
|||
@ -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() |
|||
@ -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() |
|||
@ -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() |
|||
@ -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() |
|||
|
|||
@ -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() |
|||
@ -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() |
|||
@ -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() |
|||
@ -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() |
|||
@ -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") |
|||
@ -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}) |
|||
@ -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}) |
|||
@ -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 |
|||
@ -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 |
|||
@ -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 |
|||
@ -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 |
|||
@ -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 |
|||
@ -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 |
|||
@ -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 |
|||
@ -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 |
|||
@ -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 |
|||
} |
|||
@ -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 |
|||
@ -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)" |
|||
@ -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" |
|||
@ -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 |
|||
@ -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 |
|||
@ -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 |
|||
@ -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" |
|||
@ -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 |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue