Files
docview/cmake/InstallWindowsWorker.cmake
T
2026-09-21 13:41:40 +09:00

96 lines
4.8 KiB
CMake

# Verify the complete inventory before installation and again at the destination.
include("${CMAKE_CURRENT_LIST_DIR}/WriteWindowsRuntimeManifest.cmake")
function(docview_verify_windows_worker executable output_files)
docview_runtime_file_info("${executable}" EXE worker_name worker_size)
get_filename_component(worker_directory "${executable}" DIRECTORY)
set(manifest "${executable}.runtime.json")
if(NOT EXISTS "${manifest}" OR IS_SYMLINK "${manifest}" OR IS_DIRECTORY "${manifest}")
message(FATAL_ERROR "Build the worker runtime manifest before installing: ${manifest}")
endif()
file(SIZE "${manifest}" manifest_size)
if(manifest_size LESS 1 OR manifest_size GREATER 131072)
message(FATAL_ERROR "Worker runtime manifest exceeds its size limit or is empty")
endif()
file(READ "${manifest}" inventory)
string(JSON root_type TYPE "${inventory}")
string(JSON fields LENGTH "${inventory}")
string(JSON version_type TYPE "${inventory}" schemaVersion)
string(JSON executable_type TYPE "${inventory}" executable)
string(JSON files_type TYPE "${inventory}" files)
string(JSON version GET "${inventory}" schemaVersion)
string(JSON declared_executable GET "${inventory}" executable)
string(JSON count LENGTH "${inventory}" files)
if(NOT root_type STREQUAL "OBJECT" OR NOT fields EQUAL 3 OR
NOT version_type STREQUAL "NUMBER" OR NOT version STREQUAL "1" OR
NOT executable_type STREQUAL "STRING" OR NOT declared_executable STREQUAL worker_name OR
NOT files_type STREQUAL "ARRAY" OR count LESS 1 OR count GREATER 128)
message(FATAL_ERROR "Invalid worker runtime inventory schema")
endif()
math(EXPR last "${count} - 1")
set(files)
set(names)
set(total 0)
set(found_executable FALSE)
foreach(index RANGE 0 ${last})
string(JSON entry_type TYPE "${inventory}" files ${index})
string(JSON fields LENGTH "${inventory}" files ${index})
string(JSON name_type TYPE "${inventory}" files ${index} path)
string(JSON hash_type TYPE "${inventory}" files ${index} sha256)
string(JSON size_type TYPE "${inventory}" files ${index} size)
string(JSON name GET "${inventory}" files ${index} path)
string(JSON expected_hash GET "${inventory}" files ${index} sha256)
string(JSON expected_size GET "${inventory}" files ${index} size)
string(LENGTH "${expected_hash}" hash_length)
if(NOT entry_type STREQUAL "OBJECT" OR NOT fields EQUAL 3 OR
NOT name_type STREQUAL "STRING" OR NOT hash_type STREQUAL "STRING" OR
NOT size_type STREQUAL "NUMBER" OR NOT expected_size MATCHES "^[1-9][0-9]*$" OR
NOT hash_length EQUAL 64 OR NOT expected_hash MATCHES "^[0-9a-f]+$")
message(FATAL_ERROR "Invalid worker runtime file record")
endif()
if(name STREQUAL worker_name)
set(kind EXE)
set(found_executable TRUE)
else()
set(kind DLL)
endif()
get_filename_component(basename "${name}" NAME)
if(NOT name STREQUAL basename)
message(FATAL_ERROR "Runtime manifest contains a non-basename path")
endif()
set(path "${worker_directory}/${name}")
docview_runtime_file_info("${path}" "${kind}" checked_name size)
string(TOLOWER "${name}" folded)
if(folded IN_LIST names)
message(FATAL_ERROR "Runtime manifest has a duplicate name")
endif()
list(APPEND names "${folded}")
math(EXPR total "${total} + ${size}")
if(NOT size EQUAL expected_size OR total GREATER 536870912)
message(FATAL_ERROR "Runtime file size no longer matches its build inventory: ${name}")
endif()
file(SHA256 "${path}" actual_hash)
if(NOT actual_hash STREQUAL expected_hash)
message(FATAL_ERROR "Runtime file no longer matches its build inventory: ${name}")
endif()
list(APPEND files "${path}")
endforeach()
if(NOT found_executable)
message(FATAL_ERROR "Runtime manifest is missing its worker executable")
endif()
set(${output_files} "${files}" PARENT_SCOPE)
endfunction()
docview_verify_windows_worker("${WORKER_EXECUTABLE}" verified_files)
if(NOT WORKER_VERIFY_ONLY)
if(NOT IS_ABSOLUTE "${WORKER_INSTALL_DIRECTORY}")
message(FATAL_ERROR "An absolute worker installation directory is required")
endif()
# file(INSTALL) applies DESTDIR itself. Its input must retain the unstaged
# install prefix; native tools and the verification below need the real path.
file(INSTALL DESTINATION "${WORKER_INSTALL_DIRECTORY}" TYPE FILE
FILES ${verified_files} "${WORKER_EXECUTABLE}.runtime.json")
get_filename_component(worker_name "${WORKER_EXECUTABLE}" NAME)
docview_verify_windows_worker("$ENV{DESTDIR}${WORKER_INSTALL_DIRECTORY}/${worker_name}" installed_files)
endif()