CMakeVerifyManifest.cmake 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. # Distributed under the OSI-approved BSD 3-Clause License. See accompanying
  2. # file Copyright.txt or https://cmake.org/licensing for details.
  3. #.rst:
  4. # CMakeVerifyManifest
  5. # -------------------
  6. #
  7. #
  8. #
  9. # CMakeVerifyManifest.cmake
  10. #
  11. # This script is used to verify that embedded manifests and side by side
  12. # manifests for a project match. To run this script, cd to a directory
  13. # and run the script with cmake -P. On the command line you can pass in
  14. # versions that are OK even if not found in the .manifest files. For
  15. # example, cmake -Dallow_versions=8.0.50608.0
  16. # -PCmakeVerifyManifest.cmake could be used to allow an embedded manifest
  17. # of 8.0.50608.0 to be used in a project even if that version was not
  18. # found in the .manifest file.
  19. # This script first recursively globs *.manifest files from
  20. # the current directory. Then globs *.exe and *.dll. Each
  21. # .exe and .dll is scanned for embedded manifests and the versions
  22. # of CRT are compared to those found in the .manifest files
  23. # from the first glob.
  24. # crt_version:
  25. # function to extract the CRT version from a file
  26. # this can be passed a .exe, .dll, or a .manifest file
  27. # it will put the list of versions found into the variable
  28. # specified by list_var
  29. function(crt_version file list_var)
  30. file(STRINGS "${file}" strings REGEX "Microsoft.VC...CRT" NEWLINE_CONSUME)
  31. foreach(s ${strings})
  32. set(has_match 1)
  33. string(REGEX
  34. REPLACE ".*<assembly.*\"Microsoft.VC...CRT\".*version=\"([^\"]*)\".*</assembly>.*$" "\\1"
  35. version "${s}")
  36. if(NOT "${version}" STREQUAL "")
  37. list(APPEND version_list ${version})
  38. else()
  39. message(FATAL_ERROR "Parse error could not find version in [${s}]")
  40. endif()
  41. endforeach()
  42. if(NOT DEFINED has_match)
  43. message("Information: no embedded manifest in: ${file}")
  44. return()
  45. endif()
  46. list(APPEND version_list ${${list_var}})
  47. list(REMOVE_DUPLICATES version_list)
  48. if(version_list)
  49. set(${list_var} ${version_list} PARENT_SCOPE)
  50. endif()
  51. endfunction()
  52. set(fatal_error FALSE)
  53. # check_version:
  54. #
  55. # test a file against the shipped manifest versions
  56. # for a directory
  57. function(check_version file manifest_versions)
  58. set(manifest_versions ${manifest_versions} ${allow_versions})
  59. # collect versions for a given file
  60. crt_version(${file} file_versions)
  61. # see if the versions
  62. foreach(ver ${file_versions})
  63. list(FIND manifest_versions "${ver}" found_version)
  64. if("${found_version}" EQUAL -1)
  65. message("ERROR: ${file} uses ${ver} not found in shipped manifests:[${manifest_versions}].")
  66. set(fatal_error TRUE PARENT_SCOPE)
  67. endif()
  68. endforeach()
  69. list(LENGTH file_versions len)
  70. if(${len} GREATER 1)
  71. message("WARNING: found more than one version of MICROSOFT.VC80.CRT referenced in ${file}: [${file_versions}]")
  72. endif()
  73. endfunction()
  74. # collect up the versions of CRT that are shipped
  75. # in .manifest files
  76. set(manifest_version_list )
  77. file(GLOB_RECURSE manifest_files "*.manifest")
  78. foreach(f ${manifest_files})
  79. crt_version("${f}" manifest_version_list)
  80. endforeach()
  81. list(LENGTH manifest_version_list LEN)
  82. if(LEN EQUAL 0)
  83. message(FATAL_ERROR "No .manifest files found, no version check can be done.")
  84. endif()
  85. message("Versions found in ${manifest_files}: ${manifest_version_list}")
  86. if(DEFINED allow_versions)
  87. message("Extra versions allowed: ${allow_versions}")
  88. endif()
  89. # now find all .exe and .dll files
  90. # and call check_version on each of them
  91. file(GLOB_RECURSE exe_files "*.exe")
  92. file(GLOB_RECURSE dll_files "*.dll")
  93. set(exe_files ${exe_files} ${dll_files})
  94. foreach(f ${exe_files})
  95. check_version(${f} "${manifest_version_list}")
  96. endforeach()
  97. # report a fatal error if there were any so that cmake will return
  98. # a non zero value
  99. if(fatal_error)
  100. message(FATAL_ERROR "This distribution embeds dll "
  101. " versions that it does not ship, and may not work on other machines.")
  102. endif()