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