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 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
|
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
# file LICENSE.rst or https://cmake.org/licensing for details.
#[=======================================================================[.rst:
CMakeVerifyManifest
-------------------
This module is intended to be used in command-line mode using the
:ref:`cmake -P <Script Processing Mode>` to verify that embedded manifests
and side-by-side manifests for a project match.
Load this module in a CMake script with:
.. code-block:: cmake
include(CMakeVerifyManifest)
This module first recursively globs ``*.manifest`` files from
the current source directory and creates a list of allowed versions.
Next, the script globs all ``*.exe`` and ``*.dll`` files. Each
``.exe`` and ``.dll`` file is scanned for embedded manifests and
the versions of CRT are checked to be in the list of allowed
versions.
Input Variables
^^^^^^^^^^^^^^^
This module accepts the following variables:
``allow_versions``
Additional versions can be passed by setting the ``allow_versions``
variable from the invocation command. This enables using additional
embedded manifest versions in a project, even if that version was not
found in a ``.manifest`` file.
Examples
^^^^^^^^
To use this module in the project, create a local command-line script (for
example, in the project's subdirectory ``cmake/scripts``) and include the
module:
.. code-block:: cmake
:caption: ``cmake/scripts/verify-manifest.cmake``
include(CMakeVerifyManifest)
Then run the local script in command-line and, for example, specify
additional embedded manifest of ``8.0.50608.0`` to be used in a project:
.. code-block:: shell
cmake -Dallow_versions=8.0.50608.0 -Pcmake/scripts/verify-manifest.cmake
#]=======================================================================]
# crt_version:
# function to extract the CRT version from a file
# this can be passed a .exe, .dll, or a .manifest file
# it will put the list of versions found into the variable
# specified by list_var
function(crt_version file list_var)
cmake_policy(PUSH)
cmake_policy(SET CMP0159 NEW) # file(STRINGS) with REGEX updates CMAKE_MATCH_<n>
file(STRINGS "${file}" strings REGEX "Microsoft.VC...CRT" NEWLINE_CONSUME)
cmake_policy(POP)
foreach(s ${strings})
set(has_match 1)
string(REGEX
REPLACE ".*<assembly.*\"Microsoft.VC...CRT\".*version=\"([^\"]*)\".*</assembly>.*$" "\\1"
version "${s}")
if(NOT "${version}" STREQUAL "")
list(APPEND version_list ${version})
else()
message(FATAL_ERROR "Parse error could not find version in [${s}]")
endif()
endforeach()
if(NOT DEFINED has_match)
message("Information: no embedded manifest in: ${file}")
return()
endif()
list(APPEND version_list ${${list_var}})
list(REMOVE_DUPLICATES version_list)
if(version_list)
set(${list_var} ${version_list} PARENT_SCOPE)
endif()
endfunction()
set(fatal_error FALSE)
# check_version:
#
# test a file against the shipped manifest versions
# for a directory
function(check_version file manifest_versions)
set(manifest_versions ${manifest_versions} ${allow_versions})
# collect versions for a given file
crt_version(${file} file_versions)
# see if the versions
foreach(ver ${file_versions})
list(FIND manifest_versions "${ver}" found_version)
if("${found_version}" EQUAL -1)
message("ERROR: ${file} uses ${ver} not found in shipped manifests:[${manifest_versions}].")
set(fatal_error TRUE PARENT_SCOPE)
endif()
endforeach()
list(LENGTH file_versions len)
if(${len} GREATER 1)
message("WARNING: found more than one version of MICROSOFT.VC80.CRT referenced in ${file}: [${file_versions}]")
endif()
endfunction()
# collect up the versions of CRT that are shipped
# in .manifest files
set(manifest_version_list )
file(GLOB_RECURSE manifest_files "*.manifest")
foreach(f ${manifest_files})
crt_version("${f}" manifest_version_list)
endforeach()
list(LENGTH manifest_version_list LEN)
if(LEN EQUAL 0)
message(FATAL_ERROR "No .manifest files found, no version check can be done.")
endif()
message("Versions found in ${manifest_files}: ${manifest_version_list}")
if(DEFINED allow_versions)
message("Extra versions allowed: ${allow_versions}")
endif()
# now find all .exe and .dll files
# and call check_version on each of them
file(GLOB_RECURSE exe_files "*.exe")
file(GLOB_RECURSE dll_files "*.dll")
set(exe_files ${exe_files} ${dll_files})
foreach(f ${exe_files})
check_version(${f} "${manifest_version_list}")
endforeach()
# report a fatal error if there were any so that cmake will return
# a non zero value
if(fatal_error)
message(FATAL_ERROR "This distribution embeds dll "
" versions that it does not ship, and may not work on other machines.")
endif()
|