# SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project # SPDX-License-Identifier: GPL-3.0-or-later # Created-By: crueter # Docs will come at a later date, mostly this is to just reduce boilerplate # and some cmake magic to allow for runtime viewing of dependency versions include(CMakeDependentOption) if (MSVC OR ANDROID) set(SYSTEM_DEFAULT OFF) else() set(SYSTEM_DEFAULT ON) endif() CMAKE_DEPENDENT_OPTION(CPMUTIL_DEFAULT_SYSTEM "Allow usage of system packages for CPM dependencies" ${SYSTEM_DEFAULT} "NOT ANDROID" OFF) cmake_minimum_required(VERSION 3.22) include(CPM) function(cpm_utils_message level name message) message(${level} "[CPMUtil] ${name}: ${message}") endfunction() function(AddPackage) cpm_set_policies() # TODO(crueter): docs, git clone #[[ URL configurations, descending order of precedence: - URL [+ GIT_URL] -> bare URL fetch - REPO + TAG + ARTIFACT -> github release artifact - REPO + TAG -> github release archive - REPO + SHA -> github commit archive - REPO + BRANCH -> github branch Hash configurations, descending order of precedence: - HASH -> bare sha512sum - HASH_SUFFIX -> hash grabbed from the URL + this suffix - HASH_URL -> hash grabbed from a URL * technically this is unsafe since a hacker can attack that url NOTE: hash algo defaults to sha512 #]] set(oneValueArgs NAME VERSION GIT_VERSION REPO TAG ARTIFACT SHA BRANCH HASH HASH_SUFFIX HASH_URL HASH_ALGO URL GIT_URL KEY DOWNLOAD_ONLY FIND_PACKAGE_ARGUMENTS SYSTEM_PACKAGE BUNDLED_PACKAGE ) set(multiValueArgs OPTIONS PATCHES) cmake_parse_arguments(PKG_ARGS "" "${oneValueArgs}" "${multiValueArgs}" "${ARGN}") if (NOT DEFINED PKG_ARGS_NAME) cpm_utils_message(FATAL_ERROR "package" "No package name defined") endif() if (DEFINED PKG_ARGS_URL) set(pkg_url ${PKG_ARGS_URL}) if (DEFINED PKG_ARGS_REPO) set(pkg_git_url https://github.com/${PKG_ARGS_REPO}) else() if (DEFINED PKG_ARGS_GIT_URL) set(pkg_git_url ${PKG_ARGS_GIT_URL}) else() set(pkg_git_url ${pkg_url}) endif() endif() elseif (DEFINED PKG_ARGS_REPO) set(pkg_git_url https://github.com/${PKG_ARGS_REPO}) if (DEFINED PKG_ARGS_TAG) set(pkg_key ${PKG_ARGS_TAG}) if(DEFINED PKG_ARGS_ARTIFACT) set(pkg_url ${pkg_git_url}/releases/download/${PKG_ARGS_TAG}/${PKG_ARGS_ARTIFACT}) else() set(pkg_url ${pkg_git_url}/archive/refs/tags/${PKG_ARGS_TAG}.tar.gz) endif() elseif (DEFINED PKG_ARGS_SHA) set(pkg_url "${pkg_git_url}/archive/${PKG_ARGS_SHA}.zip") else() if (DEFINED PKG_ARGS_BRANCH) set(PKG_BRANCH ${PKG_ARGS_BRANCH}) else() cpm_utils_message(WARNING ${PKG_ARGS_NAME} "REPO defined but no TAG, SHA, BRANCH, or URL specified, defaulting to master") set(PKG_BRANCH master) endif() set(pkg_url ${pkg_git_url}/archive/refs/heads/${PKG_BRANCH}.zip) endif() else() cpm_utils_message(FATAL_ERROR ${PKG_ARGS_NAME} "No URL or repository defined") endif() cpm_utils_message(STATUS ${PKG_ARGS_NAME} "Download URL is ${pkg_url}") if (DEFINED PKG_ARGS_GIT_VERSION) set(git_version ${PKG_ARGS_VERSION}) elseif(DEFINED PKG_ARGS_VERSION) set(git_version ${PKG_ARGS_GIT_VERSION}) endif() if (NOT DEFINED PKG_ARGS_KEY) if (DEFINED PKG_ARGS_SHA) string(SUBSTRING ${PKG_ARGS_SHA} 0 4 pkg_key) cpm_utils_message(DEBUG ${PKG_ARGS_NAME} "No custom key defined, using ${pkg_key} from sha") elseif (DEFINED git_version) set(pkg_key ${git_version}) cpm_utils_message(DEBUG ${PKG_ARGS_NAME} "No custom key defined, using ${pkg_key}") elseif (DEFINED PKG_ARGS_TAG) set(pkg_key ${PKG_ARGS_TAG}) cpm_utils_message(DEBUG ${PKG_ARGS_NAME} "No custom key defined, using ${pkg_key}") else() cpm_utils_message(WARNING ${PKG_ARGS_NAME} "Could not determine cache key, using CPM defaults") endif() else() set(pkg_key ${PKG_ARGS_KEY}) endif() if (DEFINED PKG_ARGS_HASH_ALGO) set(hash_algo ${PKG_ARGS_HASH_ALGO}) else() set(hash_algo SHA512) endif() if (DEFINED PKG_ARGS_HASH) set(pkg_hash "${hash_algo}=${PKG_ARGS_HASH}") elseif (DEFINED PKG_ARGS_HASH_SUFFIX) # funny sanity check string(TOLOWER ${hash_algo} hash_algo_lower) string(TOLOWER ${PKG_ARGS_HASH_SUFFIX} suffix_lower) if (NOT ${suffix_lower} MATCHES ${hash_algo_lower}) cpm_utils_message(WARNING "Hash algorithm and hash suffix do not match, errors may occur") endif() set(hash_url ${pkg_url}.${PKG_ARGS_HASH_SUFFIX}) elseif (DEFINED PKG_ARGS_HASH_URL) set(hash_url ${PKG_ARGS_HASH_URL}) else() cpm_utils_message(WARNING ${PKG_ARGS_NAME} "No hash or hash URL found") endif() if (DEFINED hash_url) set(outfile ${CMAKE_CURRENT_BINARY_DIR}/${PKG_ARGS_NAME}.hash) file(DOWNLOAD ${hash_url} ${outfile}) file(READ ${outfile} pkg_hash_tmp) file(REMOVE ${outfile}) set(pkg_hash "${hash_algo}=${pkg_hash_tmp}") endif() if (NOT CPMUTIL_DEFAULT_SYSTEM) set(CPM_USE_LOCAL_PACKAGES OFF) elseif (DEFINED PKG_ARGS_SYSTEM_PACKAGE) set(CPM_USE_LOCAL_PACKAGES ${PKG_ARGS_SYSTEM_PACKAGE}) elseif (DEFINED PKG_ARGS_BUNDLED_PACKAGE) if (PKG_ARGS_BUNDLED_PACKAGE) set(CPM_USE_LOCAL_PACKAGES OFF) else() set(CPM_USE_LOCAL_PACKAGES ON) endif() else() set(CPM_USE_LOCAL_PACKAGES ON) endif() CPMAddPackage( NAME ${PKG_ARGS_NAME} VERSION ${PKG_ARGS_VERSION} URL ${pkg_url} URL_HASH ${pkg_hash} CUSTOM_CACHE_KEY ${pkg_key} DOWNLOAD_ONLY ${PKG_ARGS_DOWNLOAD_ONLY} FIND_PACKAGE_ARGUMENTS ${PKG_ARGS_FIND_PACKAGE_ARGUMENTS} OPTIONS ${PKG_ARGS_OPTIONS} PATCHES ${PKG_ARGS_PATCHES} ${PKG_ARGS_UNPARSED_ARGUMENTS} ) set_property(GLOBAL APPEND PROPERTY CPM_PACKAGE_NAMES ${PKG_ARGS_NAME}) set_property(GLOBAL APPEND PROPERTY CPM_PACKAGE_URLS ${pkg_git_url}) if (${PKG_ARGS_NAME}_ADDED) if (DEFINED PKG_ARGS_SHA) set_property(GLOBAL APPEND PROPERTY CPM_PACKAGE_SHAS ${PKG_ARGS_SHA}) elseif(DEFINED git_version) set_property(GLOBAL APPEND PROPERTY CPM_PACKAGE_SHAS ${git_version}) elseif (DEFINED PKG_ARGS_TAG) set_property(GLOBAL APPEND PROPERTY CPM_PACKAGE_SHAS ${PKG_ARGS_TAG}) else() cpm_utils_message(WARNING ${PKG_ARGS_NAME} "Package has no specified sha, tag, or version") set_property(GLOBAL APPEND PROPERTY CPM_PACKAGE_SHAS "unknown") endif() else() if (DEFINED CPM_PACKAGE_${PKG_ARGS_NAME}_VERSION AND NOT "${CPM_PACKAGE_${PKG_ARGS_NAME}_VERSION}" STREQUAL "") set_property(GLOBAL APPEND PROPERTY CPM_PACKAGE_SHAS "${CPM_PACKAGE_${PKG_ARGS_NAME}_VERSION} (system)") else() set_property(GLOBAL APPEND PROPERTY CPM_PACKAGE_SHAS "unknown (system)") endif() endif() # pass stuff to parent scope set(${PKG_ARGS_NAME}_ADDED "${${PKG_ARGS_NAME}_ADDED}" PARENT_SCOPE) set(${PKG_ARGS_NAME}_SOURCE_DIR "${${PKG_ARGS_NAME}_SOURCE_DIR}" PARENT_SCOPE) set(${PKG_ARGS_NAME}_BINARY_DIR "${${PKG_ARGS_NAME}_BINARY_DIR}" PARENT_SCOPE) endfunction()