aboutsummaryrefslogtreecommitdiff
path: root/cmake/ExtractPackages.cmake
blob: 375c5cd813273f85faa560fc3cd7bd719287dcc8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88

# 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()