mirror of
https://github.com/Kitware/CMake.git
synced 2026-01-02 03:39:43 -06:00
This module could be directly called from the CMake root directory but it is more convenient for projects to wrap it inside a local script and call that script instead. This updates the documentation and syncs with other modules.
143 lines
4.7 KiB
CMake
143 lines
4.7 KiB
CMake
# 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()
|