# CMakeVerifyManifest.cmake # # This script is used to verify that embeded manifests and # side by side manifests for a project match. To run this # script, cd to a directory and run the script with cmake -P. # On the command line you can pass in versions that are OK even # if not found in the .manifest files. For example, # cmake -Dallow_versions=8.0.50608.0 -PCmakeVerifyManifest.cmake # could be used to allow an embeded manifest of 8.0.50608.0 # to be used in a project even if that version was not found # in the .manifest file. # This script first recursively globs *.manifest files from # the current directory. Then globs *.exe and *.dll. Each # .exe and .dll is scanned for embeded manifests and the versions # of CRT are compared to those found in the .manifest files # from the first glob. #============================================================================= # Copyright 2008-2009 Kitware, Inc. # # Distributed under the OSI-approved BSD License (the "License"); # see accompanying file Copyright.txt for details. # # This software is distributed WITHOUT ANY WARRANTY; without even the # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # See the License for more information. #============================================================================= # (To distribute this file outside of CMake, substitute the full # License text for the above reference.) # 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) file(STRINGS "${file}" strings REGEX "Microsoft.VC...CRT" NEWLINE_CONSUME) 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(s) if(NOT DEFINED has_match) message("Information: no embeded 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(crt_version) 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(ver) 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(f) 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()