From 85bd5c6663dc8c663f86828d1b1a5273ee0a82fe Mon Sep 17 00:00:00 2001 From: _ov4 Date: Tue, 13 Oct 2026 11:04:35 +0000 Subject: build: extract package dependencies and prefer local libraries Co-Authored-By: Claude Fable 5.1 --- cmake/ExtractPackages.cmake | 86 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 cmake/ExtractPackages.cmake (limited to 'cmake/ExtractPackages.cmake') diff --git a/cmake/ExtractPackages.cmake b/cmake/ExtractPackages.cmake new file mode 100644 index 0000000..7b525d7 --- /dev/null +++ b/cmake/ExtractPackages.cmake @@ -0,0 +1,86 @@ +# Use CMake's libarchive support, including on hosts without dpkg or pacman. +function(cpsc_extract_archive archive destination) + file(MAKE_DIRECTORY "${destination}") + execute_process( + COMMAND "${CMAKE_COMMAND}" -E tar xf "${archive}" + WORKING_DIRECTORY "${destination}" + RESULT_VARIABLE result ERROR_VARIABLE error + ) + if(NOT result EQUAL 0) + message(FATAL_ERROR "Cannot extract dependency package ${archive}: ${error}") + endif() +endfunction() + +function(cpsc_extract_packages) + file(GLOB_RECURSE packages CONFIGURE_DEPENDS + "${CPSC_DEPS_DIR}/packages/*.deb" + "${CPSC_DEPS_DIR}/packages/*.pkg.tar.*" + "${CPSC_DEPS_DIR}/packages/*.bottle*.tar.gz" + ) + list(FILTER packages EXCLUDE REGEX "\\.sig$") + # Homebrew exposes both a cache symlink and its downloads/ target. + set(archives) + foreach(package IN LISTS packages) + get_filename_component(package "${package}" REALPATH) + list(APPEND archives "${package}") + endforeach() + list(REMOVE_DUPLICATES archives) + list(SORT archives) + + set(stamp "${CPSC_DEPS_DIR}/packages.sha256") + if(NOT archives) + if(EXISTS "${stamp}") + file(REMOVE_RECURSE "${CPSC_DEPS_ROOT}") + file(REMOVE "${stamp}") + endif() + return() + endif() + + set(signature "${CPSC_DEPS_ROOT}\n") + foreach(archive IN LISTS archives) + file(SHA256 "${archive}" hash) + string(APPEND signature "${archive}:${hash}\n") + endforeach() + foreach(module ExtractPackages LinuxPackages WindowsPackages HomebrewPackages) + file(SHA256 "${CPSC_DEPS_MODULE_DIR}/${module}.cmake" hash) + string(APPEND signature "${module}:${hash}\n") + endforeach() + if(EXISTS "${stamp}" AND IS_DIRECTORY "${CPSC_DEPS_ROOT}") + file(READ "${stamp}" previous_signature) + if(signature STREQUAL previous_signature) + return() + endif() + endif() + + # Rebuild the managed extraction directory when the package set changes. + file(REMOVE "${stamp}") + file(REMOVE_RECURSE "${CPSC_DEPS_ROOT}") + file(MAKE_DIRECTORY "${CPSC_DEPS_ROOT}") + foreach(archive IN LISTS archives) + message(STATUS "Extracting dependency package: ${archive}") + if(archive MATCHES "\\.deb$") + set(unpack "${CPSC_DEPS_DIR}/unpack") + file(REMOVE_RECURSE "${unpack}") + cpsc_extract_archive("${archive}" "${unpack}") + file(GLOB data "${unpack}/data.tar.*" "${unpack}/data.tar") + list(LENGTH data data_count) + if(NOT data_count EQUAL 1) + message(FATAL_ERROR "Dependency package ${archive} must contain one data.tar archive") + endif() + cpsc_extract_archive("${data}" "${CPSC_DEPS_ROOT}") + file(REMOVE_RECURSE "${unpack}") + elseif(archive MATCHES "\\.bottle[^/]*\\.tar\\.gz$") + cpsc_extract_archive("${archive}" "${CPSC_DEPS_ROOT}/Cellar") + else() + cpsc_extract_archive("${archive}" "${CPSC_DEPS_ROOT}") + endif() + endforeach() + if(CMAKE_HOST_APPLE) + cpsc_prepare_homebrew_packages() + elseif(CMAKE_HOST_WIN32) + cpsc_prepare_windows_packages() + else() + cpsc_prepare_linux_packages() + endif() + file(WRITE "${stamp}" "${signature}") +endfunction() -- cgit v1.3.1-4-g156e