# 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" "${CPSC_DEPS_DIR}/packages/pandoc-*-windows-x86_64.zip" ) 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 FindDependency DependencyPaths) 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() cpsc_dependency_paths("${CMAKE_BINARY_DIR}") 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()