Merge branch 'FindMPI-imported-link-flags' into release-3.15

Merge-request: !3449
diff --git a/Help/manual/cmake-file-api.7.rst b/Help/manual/cmake-file-api.7.rst
index f3e0208..04b6ed2 100644
--- a/Help/manual/cmake-file-api.7.rst
+++ b/Help/manual/cmake-file-api.7.rst
@@ -379,6 +379,8 @@
 a new reply.  The client may simply start again by reading the new
 reply index file.
 
+.. _`file-api object kinds`:
+
 Object Kinds
 ============
 
diff --git a/Help/manual/cmake-properties.7.rst b/Help/manual/cmake-properties.7.rst
index 25aab8d..77b1ae8 100644
--- a/Help/manual/cmake-properties.7.rst
+++ b/Help/manual/cmake-properties.7.rst
@@ -62,7 +62,6 @@
    :maxdepth: 1
 
    /prop_dir/ADDITIONAL_CLEAN_FILES
-   /prop_dir/ADDITIONAL_MAKE_CLEAN_FILES
    /prop_dir/BINARY_DIR
    /prop_dir/BUILDSYSTEM_TARGETS
    /prop_dir/CACHE_VARIABLES
@@ -505,6 +504,7 @@
 .. toctree::
    :maxdepth: 1
 
+   /prop_dir/ADDITIONAL_MAKE_CLEAN_FILES
    /prop_dir/COMPILE_DEFINITIONS_CONFIG
    /prop_dir/TEST_INCLUDE_FILE
 
diff --git a/Help/manual/cmake.1.rst b/Help/manual/cmake.1.rst
index f1d02eb..13cba71 100644
--- a/Help/manual/cmake.1.rst
+++ b/Help/manual/cmake.1.rst
@@ -423,6 +423,22 @@
       A list of strings with all the extra generators compatible with
       the generator.
 
+  ``fileApi``
+    Optional member that is present when the :manual:`cmake-file-api(7)`
+    is available.  The value is a JSON object with one member:
+
+    ``requests``
+      A JSON array containing zero or more supported file-api requests.
+      Each request is a JSON object with members:
+
+      ``kind``
+        Specifies one of the supported :ref:`file-api object kinds`.
+
+      ``version``
+        A JSON array whose elements are each a JSON object containing
+        ``major`` and ``minor`` members specifying non-negative integer
+        version components.
+
   ``serverMode``
     ``true`` if cmake supports server-mode and ``false`` otherwise.
 
diff --git a/Help/prop_dir/ADDITIONAL_CLEAN_FILES.rst b/Help/prop_dir/ADDITIONAL_CLEAN_FILES.rst
index 54a78ef..051d22a 100644
--- a/Help/prop_dir/ADDITIONAL_CLEAN_FILES.rst
+++ b/Help/prop_dir/ADDITIONAL_CLEAN_FILES.rst
@@ -1,16 +1,21 @@
 ADDITIONAL_CLEAN_FILES
 ----------------------
 
-Additional files to remove during the clean stage.
+A :ref:`;-list <CMake Language Lists>` of files or directories that will be
+removed as a part of the global ``clean`` target.  It is useful for
+specifying generated files or directories that are used by multiple targets
+or by CMake itself, or that are generated in ways which cannot be captured as
+outputs or byproducts of custom commands.
 
-A :ref:`;-list <CMake Language Lists>` of files that will be removed as a
-part of the ``clean`` target.
+If an additional clean file is specific to a single target only, then the
+:prop_tgt:`ADDITIONAL_CLEAN_FILES` target property would usually be a better
+choice than this directory property.
 
 Relative paths are allowed and are interpreted relative to the
 current binary directory.
 
-Arguments to :prop_dir:`ADDITIONAL_CLEAN_FILES` may use
+Contents of ``ADDITIONAL_CLEAN_FILES`` may use
 :manual:`generator expressions <cmake-generator-expressions(7)>`.
 
 This property only works for the :generator:`Ninja` and the Makefile
-generators.  It is ignored on other generators.
+generators.  It is ignored by other generators.
diff --git a/Help/prop_tgt/ADDITIONAL_CLEAN_FILES.rst b/Help/prop_tgt/ADDITIONAL_CLEAN_FILES.rst
index 856bb38..3b9d965 100644
--- a/Help/prop_tgt/ADDITIONAL_CLEAN_FILES.rst
+++ b/Help/prop_tgt/ADDITIONAL_CLEAN_FILES.rst
@@ -1,16 +1,23 @@
 ADDITIONAL_CLEAN_FILES
 ----------------------
 
-Additional files to remove during the clean stage.
+A :ref:`;-list <CMake Language Lists>` of files or directories that will be
+removed as a part of the global ``clean`` target.  It can be used to specify
+files and directories that are generated as part of building the target or
+that are directly associated with the target in some way (e.g. created as a
+result of running the target).
 
-A :ref:`;-list <CMake Language Lists>` of files that will be removed as a
-part of the ``clean`` target.
+For custom targets, if such files can be captured as outputs or byproducts
+instead, then that should be preferred over adding them to this property.
+If an additional clean file is used by multiple targets or isn't
+target-specific, then the :prop_dir:`ADDITIONAL_CLEAN_FILES` directory
+property may be the more appropriate property to use.
 
 Relative paths are allowed and are interpreted relative to the
 current binary directory.
 
-Arguments to :prop_tgt:`ADDITIONAL_CLEAN_FILES` may use
+Contents of ``ADDITIONAL_CLEAN_FILES`` may use
 :manual:`generator expressions <cmake-generator-expressions(7)>`.
 
 This property only works for the :generator:`Ninja` and the Makefile
-generators.  It is ignored on other generators.
+generators.  It is ignored by other generators.
diff --git a/Help/variable/CMAKE_LANG_COMPILER_ID.rst b/Help/variable/CMAKE_LANG_COMPILER_ID.rst
index 16d97ee..8eb4fb6 100644
--- a/Help/variable/CMAKE_LANG_COMPILER_ID.rst
+++ b/Help/variable/CMAKE_LANG_COMPILER_ID.rst
@@ -35,6 +35,7 @@
   TI = Texas Instruments (ti.com)
   TinyCC = Tiny C Compiler (tinycc.org)
   XL, VisualAge, zOS = IBM XL (ibm.com)
+  XLClang = IBM Clang-based XL (ibm.com)
 
 This variable is not guaranteed to be defined for all compilers or
 languages.
diff --git a/Help/variable/CMAKE_PROJECT_INCLUDE.rst b/Help/variable/CMAKE_PROJECT_INCLUDE.rst
index 7de767a..965c94e 100644
--- a/Help/variable/CMAKE_PROJECT_INCLUDE.rst
+++ b/Help/variable/CMAKE_PROJECT_INCLUDE.rst
@@ -1,6 +1,9 @@
 CMAKE_PROJECT_INCLUDE
 ---------------------
 
-A CMake language file or module to be included by the :command:`project`
-command.  This is intended for injecting custom code into project
-builds without modifying their source.
+A CMake language file or module to be included as the last step of all
+:command:`project` command calls.  This is intended for injecting custom code
+into project builds without modifying their source.
+
+See also the :variable:`CMAKE_PROJECT_<PROJECT-NAME>_INCLUDE` and
+:variable:`CMAKE_PROJECT_INCLUDE_BEFORE` variables.
diff --git a/Help/variable/CMAKE_PROJECT_INCLUDE_BEFORE.rst b/Help/variable/CMAKE_PROJECT_INCLUDE_BEFORE.rst
index 12a5263..70b15e6 100644
--- a/Help/variable/CMAKE_PROJECT_INCLUDE_BEFORE.rst
+++ b/Help/variable/CMAKE_PROJECT_INCLUDE_BEFORE.rst
@@ -1,6 +1,9 @@
 CMAKE_PROJECT_INCLUDE_BEFORE
 ----------------------------
 
-A CMake language file or module to be included before processing the
-:command:`project` command. This is intended for injecting custom code into
-project builds without modifying their source.
+A CMake language file or module to be included as the first step of all
+:command:`project` command calls.  This is intended for injecting custom code
+into project builds without modifying their source.
+
+See also the :variable:`CMAKE_PROJECT_<PROJECT-NAME>_INCLUDE` and
+:variable:`CMAKE_PROJECT_INCLUDE` variables.
diff --git a/Help/variable/CMAKE_PROJECT_PROJECT-NAME_INCLUDE.rst b/Help/variable/CMAKE_PROJECT_PROJECT-NAME_INCLUDE.rst
index 5ca40a3..3485c38 100644
--- a/Help/variable/CMAKE_PROJECT_PROJECT-NAME_INCLUDE.rst
+++ b/Help/variable/CMAKE_PROJECT_PROJECT-NAME_INCLUDE.rst
@@ -1,6 +1,10 @@
 CMAKE_PROJECT_<PROJECT-NAME>_INCLUDE
 ------------------------------------
 
-A CMake language file or module to be included by the :command:`project`
-command.  This is intended for injecting custom code into project
-builds without modifying their source.
+A CMake language file or module to be included as the last step of any
+:command:`project` command calls that specify ``<PROJECT-NAME>`` as the project
+name.  This is intended for injecting custom code into project builds without
+modifying their source.
+
+See also the :variable:`CMAKE_PROJECT_INCLUDE` and
+:variable:`CMAKE_PROJECT_INCLUDE_BEFORE` variables.
diff --git a/Modules/CheckCXXSymbolExists.cmake b/Modules/CheckCXXSymbolExists.cmake
index 970e301..2cccd09 100644
--- a/Modules/CheckCXXSymbolExists.cmake
+++ b/Modules/CheckCXXSymbolExists.cmake
@@ -24,7 +24,7 @@
   as a function or variable then the symbol must also be available for
   linking.  If the symbol is a type or enum value it will not be
   recognized (consider using :module:`CheckTypeSize`
-  or :module:`CheckCSourceCompiles`).
+  or :module:`CheckCXXSourceCompiles`).
 
 The following variables may be set before calling this macro to modify
 the way the check is run:
diff --git a/Modules/FindBLAS.cmake b/Modules/FindBLAS.cmake
index 65e5d1c..77f9d0e 100644
--- a/Modules/FindBLAS.cmake
+++ b/Modules/FindBLAS.cmake
@@ -152,7 +152,9 @@
 
   foreach(_library ${_list})
     set(_combined_name ${_combined_name}_${_library})
-
+    if(NOT "${_thread}" STREQUAL "")
+      set(_combined_name ${_combined_name}_thread)
+    endif()
     if(_libraries_work)
       if (BLA_STATIC)
         if (WIN32)
@@ -479,6 +481,18 @@
       ""
       )
   endif()
+  if(NOT BLAS_LIBRARIES)
+    find_package(Threads)
+    # OpenBLAS (http://www.openblas.net)
+    check_fortran_libraries(
+      BLAS_LIBRARIES
+      BLAS
+      sgemm
+      ""
+      "openblas"
+      "${CMAKE_THREAD_LIBS_INIT}"
+      )
+  endif()
 endif ()
 
 if (BLA_VENDOR STREQUAL "FLAME" OR BLA_VENDOR STREQUAL "All")
diff --git a/Modules/FindBoost.cmake b/Modules/FindBoost.cmake
index a059589..25dd397 100644
--- a/Modules/FindBoost.cmake
+++ b/Modules/FindBoost.cmake
@@ -249,6 +249,155 @@
 cmake_policy(PUSH)
 cmake_policy(SET CMP0057 NEW) # if IN_LIST
 
+function(_boost_get_existing_target component target_var)
+  set(names "${component}")
+  if(component MATCHES "^([a-z_]*)(python|numpy)([1-9])\\.?([0-9])?$")
+    # handle pythonXY and numpyXY versioned components and also python X.Y, mpi_python etc.
+    list(APPEND names
+      "${CMAKE_MATCH_1}${CMAKE_MATCH_2}" # python
+      "${CMAKE_MATCH_1}${CMAKE_MATCH_2}${CMAKE_MATCH_3}" # pythonX
+      "${CMAKE_MATCH_1}${CMAKE_MATCH_2}${CMAKE_MATCH_3}${CMAKE_MATCH_4}" #pythonXY
+    )
+  endif()
+  # https://github.com/boost-cmake/boost-cmake uses boost::file_system etc.
+  # So handle similar constructions of target names
+  string(TOLOWER "${component}" lower_component)
+  list(APPEND names "${lower_component}")
+  foreach(prefix Boost boost)
+    foreach(name IN LISTS names)
+      if(TARGET "${prefix}::${name}")
+        set(${target_var} "${prefix}::${name}" PARENT_SCOPE)
+        return()
+      endif()
+    endforeach()
+  endforeach()
+  set(${target_var} "" PARENT_SCOPE)
+endfunction()
+
+function(_boost_get_canonical_target_name component target_var)
+  string(TOLOWER "${component}" component)
+  if(component MATCHES "^([a-z_]*)(python|numpy)([1-9])\\.?([0-9])?$")
+    # handle pythonXY and numpyXY versioned components and also python X.Y, mpi_python etc.
+    set(${target_var} "Boost::${CMAKE_MATCH_1}${CMAKE_MATCH_2}" PARENT_SCOPE)
+  else()
+    set(${target_var} "Boost::${component}" PARENT_SCOPE)
+  endif()
+endfunction()
+
+macro(_boost_set_in_parent_scope name value)
+  # Set a variable in parent scope and make it visibile in current scope
+  set(${name} "${value}" PARENT_SCOPE)
+  set(${name} "${value}")
+endmacro()
+
+macro(_boost_set_if_unset name value)
+  if(NOT ${name})
+    _boost_set_in_parent_scope(${name} "${value}")
+  endif()
+endmacro()
+
+macro(_boost_set_cache_if_unset name value)
+  if(NOT ${name})
+    set(${name} "${value}" CACHE STRING "" FORCE)
+  endif()
+endmacro()
+
+macro(_boost_append_include_dir target)
+  get_target_property(inc "${target}" INTERFACE_INCLUDE_DIRECTORIES)
+  if(inc)
+    list(APPEND include_dirs "${inc}")
+  endif()
+endmacro()
+
+function(_boost_set_legacy_variables_from_config)
+  # Set legacy variables for compatibility if not set
+  set(include_dirs "")
+  set(library_dirs "")
+  set(libraries "")
+  # Header targets Boost::headers or Boost::boost
+  foreach(comp headers boost)
+    _boost_get_existing_target(${comp} target)
+    if(target)
+      _boost_append_include_dir("${target}")
+    endif()
+  endforeach()
+  # Library targets
+  foreach(comp IN LISTS Boost_FIND_COMPONENTS)
+    string(TOUPPER ${comp} uppercomp)
+    # Overwrite if set
+    _boost_set_in_parent_scope(Boost_${uppercomp}_FOUND "${Boost_${comp}_FOUND}")
+    if(Boost_${comp}_FOUND)
+      _boost_get_existing_target(${comp} target)
+      if(NOT target)
+        if(Boost_DEBUG OR Boost_VERBOSE)
+          message(WARNING "Could not find imported target for required component '${comp}'. Standard variables for this component might be missing. Refer to the documentation of your Boost installation for help on variables to use.")
+        endif()
+        continue()
+      endif()
+      _boost_append_include_dir("${target}")
+      _boost_set_if_unset(Boost_${uppercomp}_LIBRARY "${target}")
+      _boost_set_if_unset(Boost_${uppercomp}_LIBRARIES "${target}") # Very old legacy variable
+      list(APPEND libraries "${target}")
+      foreach(cfg RELEASE DEBUG)
+        get_target_property(lib ${target} IMPORTED_LOCATION_${cfg})
+        if(lib)
+          get_filename_component(lib_dir "${lib}" DIRECTORY)
+          list(APPEND library_dirs ${lib_dir})
+          _boost_set_cache_if_unset(Boost_${uppercomp}_LIBRARY_${cfg} "${lib}")
+        endif()
+      endforeach()
+      _boost_get_canonical_target_name("${comp}" canonical_target)
+      if(NOT TARGET "${canonical_target}")
+        add_library("${canonical_target}" INTERFACE IMPORTED)
+        target_link_libraries("${canonical_target}" INTERFACE "${target}")
+      endif()
+    endif()
+  endforeach()
+  list(REMOVE_DUPLICATES include_dirs)
+  list(REMOVE_DUPLICATES library_dirs)
+  _boost_set_if_unset(Boost_INCLUDE_DIRS "${include_dirs}")
+  _boost_set_if_unset(Boost_LIBRARY_DIRS "${library_dirs}")
+  _boost_set_if_unset(Boost_LIBRARIES "${libraries}")
+  _boost_set_if_unset(Boost_VERSION_STRING "${Boost_VERSION_MAJOR}.${Boost_VERSION_MINOR}.${Boost_VERSION_PATCH}")
+  find_path(Boost_INCLUDE_DIR
+    NAMES boost/version.hpp boost/config.hpp
+    HINTS ${Boost_INCLUDE_DIRS}
+    NO_DEFAULT_PATH
+  )
+  if(NOT Boost_VERSION_MACRO OR NOT Boost_LIB_VERSION)
+    set(version_file ${Boost_INCLUDE_DIR}/boost/version.hpp)
+    if(EXISTS "${version_file}")
+      file(STRINGS "${version_file}" contents REGEX "#define BOOST_(LIB_)?VERSION ")
+      if(contents MATCHES "#define BOOST_VERSION ([0-9]+)")
+        _boost_set_if_unset(Boost_VERSION_MACRO "${CMAKE_MATCH_1}")
+      endif()
+      if(contents MATCHES "#define BOOST_LIB_VERSION \"([0-9_]+)\"")
+        _boost_set_if_unset(Boost_LIB_VERSION "${CMAKE_MATCH_1}")
+      endif()
+    endif()
+  endif()
+  _boost_set_if_unset(Boost_MAJOR_VERSION ${Boost_VERSION_MAJOR})
+  _boost_set_if_unset(Boost_MINOR_VERSION ${Boost_VERSION_MINOR})
+  _boost_set_if_unset(Boost_SUBMINOR_VERSION ${Boost_VERSION_PATCH})
+  if(WIN32)
+    _boost_set_if_unset(Boost_LIB_DIAGNOSTIC_DEFINITIONS "-DBOOST_LIB_DIAGNOSTIC")
+  endif()
+  if(NOT TARGET Boost::headers)
+    add_library(Boost::headers INTERFACE IMPORTED)
+    target_include_directories(Boost::headers INTERFACE ${Boost_INCLUDE_DIRS})
+  endif()
+  # Legacy targets w/o functionality as all handled by defined targets
+  foreach(lib diagnostic_definitions disable_autolinking dynamic_linking)
+    if(NOT TARGET Boost::${lib})
+      add_library(Boost::${lib} INTERFACE IMPORTED)
+    endif()
+  endforeach()
+  if(NOT TARGET Boost::boost)
+    add_library(Boost::boost INTERFACE IMPORTED)
+    target_link_libraries(Boost::boost INTERFACE Boost::headers)
+  endif()
+endfunction()
+
 #-------------------------------------------------------------------------------
 # Before we go searching, check whether a boost cmake package is available, unless
 # the user specifically asked NOT to search for one.
@@ -276,21 +425,24 @@
   # If we found a boost cmake package, then we're done. Print out what we found.
   # Otherwise let the rest of the module try to find it.
   if(Boost_FOUND)
-    # Neither the legacy boost-cmake nor the new builtin BoostConfig (as in 1.70)
-    # report the found components in the standard variables, so we need to convert
-    # them here
+    # Convert component found variables to standard variables if required
+    # Necessary for legacy boost-cmake and 1.70 builtin BoostConfig
     if(Boost_FIND_COMPONENTS)
       foreach(_comp IN LISTS Boost_FIND_COMPONENTS)
+        if(DEFINED Boost_${_comp}_FOUND)
+          continue()
+        endif()
         string(TOUPPER ${_comp} _uppercomp)
-        if(DEFINED Boost${_comp}_FOUND)
+        if(DEFINED Boost${_comp}_FOUND) # legacy boost-cmake project
           set(Boost_${_comp}_FOUND ${Boost${_comp}_FOUND})
-        elseif(DEFINED Boost_${_uppercomp}_FOUND)
+        elseif(DEFINED Boost_${_uppercomp}_FOUND) # Boost 1.70
           set(Boost_${_comp}_FOUND ${Boost_${_uppercomp}_FOUND})
         endif()
       endforeach()
     endif()
 
     find_package_handle_standard_args(Boost HANDLE_COMPONENTS CONFIG_MODE)
+    _boost_set_legacy_variables_from_config()
 
     # Restore project's policies
     cmake_policy(POP)
diff --git a/Modules/FindEnvModules.cmake b/Modules/FindEnvModules.cmake
index e39ec97..4dd5116 100644
--- a/Modules/FindEnvModules.cmake
+++ b/Modules/FindEnvModules.cmake
@@ -53,7 +53,7 @@
 This module will set the following variables in your project:
 
 ``EnvModules_FOUND``
-  Found the a compatible environment modules framework
+  True if a compatible environment modules framework was found.
 
 Cache Variables
 ^^^^^^^^^^^^^^^
@@ -61,7 +61,7 @@
 The following cache variable will be set:
 
 ``EnvModules_COMMAND``
-  The low level module command to use.  Currently supported are
+  The low level module command to use.  Currently supported
   implementations are the Lua based Lmod and TCL based EnvironmentModules.
 
 Environment Variables
@@ -74,7 +74,7 @@
 Provided Functions
 ^^^^^^^^^^^^^^^^^^
 
-This defines the following cmake functions for interacting with environment
+This defines the following CMake functions for interacting with environment
 modules:
 
 .. command:: env_module
diff --git a/Modules/Internal/CPack/CPackNuGet.cmake b/Modules/Internal/CPack/CPackNuGet.cmake
index 198ccad..4b2ce92 100644
--- a/Modules/Internal/CPack/CPackNuGet.cmake
+++ b/Modules/Internal/CPack/CPackNuGet.cmake
@@ -276,7 +276,7 @@
     set(_CPACK_NUGET_FILES_TAG "<files>\n${_files}    </files>" PARENT_SCOPE)
 endfunction()
 
-find_program(NUGET_EXECUTABLE NuGet)
+find_program(NUGET_EXECUTABLE nuget)
 _cpack_nuget_debug_var(NUGET_EXECUTABLE)
 if(NOT NUGET_EXECUTABLE)
     message(FATAL_ERROR "NuGet executable not found")
diff --git a/Source/QtDialog/CMakeSetupDialog.cxx b/Source/QtDialog/CMakeSetupDialog.cxx
index 5f6ccca..e98cdcf 100644
--- a/Source/QtDialog/CMakeSetupDialog.cxx
+++ b/Source/QtDialog/CMakeSetupDialog.cxx
@@ -862,7 +862,7 @@
     "built using Qt %2 (qt-project.org).\n"
 #ifdef USE_LGPL
     "\n"
-    "The Qt Toolkit is Copyright (C) Digia Plc and/or its subsidiary(-ies).\n"
+    "The Qt Toolkit is Copyright (C) The Qt Company Ltd.\n"
     "Qt is licensed under terms of the GNU LGPLv" USE_LGPL ", available at:\n"
     " \"%3\""
 #endif
diff --git a/Source/cmFileAPI.cxx b/Source/cmFileAPI.cxx
index 34b6b33..ba42669 100644
--- a/Source/cmFileAPI.cxx
+++ b/Source/cmFileAPI.cxx
@@ -413,6 +413,14 @@
   return name;
 }
 
+Json::Value cmFileAPI::BuildVersion(unsigned int major, unsigned int minor)
+{
+  Json::Value version;
+  version["major"] = major;
+  version["minor"] = minor;
+  return version;
+}
+
 Json::Value cmFileAPI::BuildObject(Object const& object)
 {
   Json::Value value;
@@ -680,10 +688,9 @@
   Json::Value codemodel = cmFileAPICodemodelDump(*this, object.Version);
   codemodel["kind"] = this->ObjectKindName(object.Kind);
 
-  Json::Value& version = codemodel["version"] = Json::objectValue;
+  Json::Value& version = codemodel["version"];
   if (object.Version == 2) {
-    version["major"] = 2;
-    version["minor"] = CodeModelV2Minor;
+    version = BuildVersion(2, CodeModelV2Minor);
   } else {
     return codemodel; // should be unreachable
   }
@@ -716,10 +723,9 @@
   Json::Value cache = cmFileAPICacheDump(*this, object.Version);
   cache["kind"] = this->ObjectKindName(object.Kind);
 
-  Json::Value& version = cache["version"] = Json::objectValue;
+  Json::Value& version = cache["version"];
   if (object.Version == 2) {
-    version["major"] = 2;
-    version["minor"] = CacheV2Minor;
+    version = BuildVersion(2, CacheV2Minor);
   } else {
     return cache; // should be unreachable
   }
@@ -752,10 +758,9 @@
   Json::Value cmakeFiles = cmFileAPICMakeFilesDump(*this, object.Version);
   cmakeFiles["kind"] = this->ObjectKindName(object.Kind);
 
-  Json::Value& version = cmakeFiles["version"] = Json::objectValue;
+  Json::Value& version = cmakeFiles["version"];
   if (object.Version == 1) {
-    version["major"] = 1;
-    version["minor"] = CMakeFilesV1Minor;
+    version = BuildVersion(1, CMakeFilesV1Minor);
   } else {
     return cmakeFiles; // should be unreachable
   }
@@ -788,13 +793,43 @@
 {
   Json::Value test = Json::objectValue;
   test["kind"] = this->ObjectKindName(object.Kind);
-  Json::Value& version = test["version"] = Json::objectValue;
+  Json::Value& version = test["version"];
   if (object.Version == 2) {
-    version["major"] = 2;
-    version["minor"] = InternalTestV2Minor;
+    version = BuildVersion(2, InternalTestV2Minor);
   } else {
-    version["major"] = 1;
-    version["minor"] = InternalTestV1Minor;
+    version = BuildVersion(1, InternalTestV1Minor);
   }
   return test;
 }
+
+Json::Value cmFileAPI::ReportCapabilities()
+{
+  Json::Value capabilities = Json::objectValue;
+  Json::Value& requests = capabilities["requests"] = Json::arrayValue;
+
+  {
+    Json::Value request = Json::objectValue;
+    request["kind"] = ObjectKindName(ObjectKind::CodeModel);
+    Json::Value& versions = request["version"] = Json::arrayValue;
+    versions.append(BuildVersion(2, CodeModelV2Minor));
+    requests.append(std::move(request)); // NOLINT(*)
+  }
+
+  {
+    Json::Value request = Json::objectValue;
+    request["kind"] = ObjectKindName(ObjectKind::Cache);
+    Json::Value& versions = request["version"] = Json::arrayValue;
+    versions.append(BuildVersion(2, CacheV2Minor));
+    requests.append(std::move(request)); // NOLINT(*)
+  }
+
+  {
+    Json::Value request = Json::objectValue;
+    request["kind"] = ObjectKindName(ObjectKind::CMakeFiles);
+    Json::Value& versions = request["version"] = Json::arrayValue;
+    versions.append(BuildVersion(1, CMakeFilesV1Minor));
+    requests.append(std::move(request)); // NOLINT(*)
+  }
+
+  return capabilities;
+}
diff --git a/Source/cmFileAPI.h b/Source/cmFileAPI.h
index 341b072..602efa8 100644
--- a/Source/cmFileAPI.h
+++ b/Source/cmFileAPI.h
@@ -36,6 +36,9 @@
       and holding the original object.  Other JSON types are unchanged.  */
   Json::Value MaybeJsonFile(Json::Value in, std::string const& prefix);
 
+  /** Report file-api capabilities for cmake -E capabilities.  */
+  static Json::Value ReportCapabilities();
+
 private:
   cmake* CMakeInstance;
 
@@ -162,6 +165,8 @@
   static const char* ObjectKindName(ObjectKind kind);
   static std::string ObjectName(Object const& o);
 
+  static Json::Value BuildVersion(unsigned int major, unsigned int minor);
+
   Json::Value BuildObject(Object const& object);
 
   ClientRequests BuildClientRequests(Json::Value const& requests);
diff --git a/Source/cmFindPackageCommand.cxx b/Source/cmFindPackageCommand.cxx
index 8eefaa7..828488f 100644
--- a/Source/cmFindPackageCommand.cxx
+++ b/Source/cmFindPackageCommand.cxx
@@ -502,8 +502,13 @@
   if (this->Makefile->IsOn("CMAKE_FIND_PACKAGE_PREFER_CONFIG")) {
     if (this->UseConfigFiles && this->FindPackageUsingConfigMode()) {
       loadedPackage = true;
-    } else if (this->FindPackageUsingModuleMode()) {
-      loadedPackage = true;
+    } else {
+      if (this->FindPackageUsingModuleMode()) {
+        loadedPackage = true;
+      } else {
+        // The package was not loaded. Report errors.
+        HandlePackageMode(HandlePackageModeType::Module);
+      }
     }
   } else {
     if (this->UseFindModules && this->FindPackageUsingModuleMode()) {
@@ -603,7 +608,7 @@
   this->IgnoredPaths.insert(ignored.begin(), ignored.end());
 
   // Find and load the package.
-  return this->HandlePackageMode();
+  return this->HandlePackageMode(HandlePackageModeType::Config);
 }
 
 void cmFindPackageCommand::SetModuleVariables(const std::string& components)
@@ -722,7 +727,8 @@
   return true;
 }
 
-bool cmFindPackageCommand::HandlePackageMode()
+bool cmFindPackageCommand::HandlePackageMode(
+  HandlePackageModeType handlePackageModeType)
 {
   this->ConsideredConfigs.clear();
 
@@ -817,6 +823,12 @@
     }
   }
 
+  if (this->Makefile->IsOn("CMAKE_FIND_PACKAGE_PREFER_CONFIG") && !found &&
+      handlePackageModeType == HandlePackageModeType::Config) {
+    // Config mode failed. Allow Module case.
+    result = false;
+  }
+
   // package not found
   if (result && !found) {
     // warn if package required or neither quiet nor in config mode
diff --git a/Source/cmFindPackageCommand.h b/Source/cmFindPackageCommand.h
index 4f6d97c..316ca0f 100644
--- a/Source/cmFindPackageCommand.h
+++ b/Source/cmFindPackageCommand.h
@@ -103,7 +103,14 @@
   bool FindModule(bool& found);
   void AddFindDefinition(const std::string& var, const char* val);
   void RestoreFindDefinitions();
-  bool HandlePackageMode();
+
+  enum /*class*/ HandlePackageModeType
+  {
+    Module,
+    Config
+  };
+  bool HandlePackageMode(HandlePackageModeType type);
+
   bool FindConfig();
   bool FindPrefixedConfig();
   bool FindFrameworkConfig();
diff --git a/Source/cmQtAutoGenInitializer.cxx b/Source/cmQtAutoGenInitializer.cxx
index 265daf6..9985f93 100644
--- a/Source/cmQtAutoGenInitializer.cxx
+++ b/Source/cmQtAutoGenInitializer.cxx
@@ -721,9 +721,9 @@
       MUFile const& muf = *pair.second;
       if (muf.MocIt || muf.UicIt) {
         // Search for the default header file and a private header
-        std::string const& realPath = muf.RealPath;
-        std::string basePath = cmQtAutoGen::SubDirPrefix(realPath);
-        basePath += cmSystemTools::GetFilenameWithoutLastExtension(realPath);
+        std::string const& srcPath = muf.SF->GetFullPath();
+        std::string basePath = cmQtAutoGen::SubDirPrefix(srcPath);
+        basePath += cmSystemTools::GetFilenameWithoutLastExtension(srcPath);
         for (auto const& suffix : suffixes) {
           std::string const suffixedPath = basePath + suffix;
           for (auto const& ext : exts) {
diff --git a/Source/cmServerProtocol.cxx b/Source/cmServerProtocol.cxx
index dad8821..558391f 100644
--- a/Source/cmServerProtocol.cxx
+++ b/Source/cmServerProtocol.cxx
@@ -630,7 +630,7 @@
   Json::Value obj = Json::objectValue;
 
   // Capabilities information:
-  obj[kCAPABILITIES_KEY] = cm->ReportCapabilitiesJson(true);
+  obj[kCAPABILITIES_KEY] = cm->ReportCapabilitiesJson();
 
   obj[kDEBUG_OUTPUT_KEY] = cm->GetDebugOutput();
   obj[kTRACE_KEY] = cm->GetTrace();
diff --git a/Source/cmake.cxx b/Source/cmake.cxx
index f0b53f4..3772f09 100644
--- a/Source/cmake.cxx
+++ b/Source/cmake.cxx
@@ -248,7 +248,7 @@
   return version;
 }
 
-Json::Value cmake::ReportCapabilitiesJson(bool haveServerMode) const
+Json::Value cmake::ReportCapabilitiesJson() const
 {
   Json::Value obj = Json::objectValue;
 
@@ -284,18 +284,19 @@
     generators.append(i.second);
   }
   obj["generators"] = generators;
-  obj["serverMode"] = haveServerMode;
+  obj["fileApi"] = cmFileAPI::ReportCapabilities();
+  obj["serverMode"] = true;
 
   return obj;
 }
 #endif
 
-std::string cmake::ReportCapabilities(bool haveServerMode) const
+std::string cmake::ReportCapabilities() const
 {
   std::string result;
 #if defined(CMAKE_BUILD_WITH_CMAKE)
   Json::FastWriter writer;
-  result = writer.write(this->ReportCapabilitiesJson(haveServerMode));
+  result = writer.write(this->ReportCapabilitiesJson());
 #else
   result = "Not supported";
 #endif
diff --git a/Source/cmake.h b/Source/cmake.h
index 4de9d28..fa4409a 100644
--- a/Source/cmake.h
+++ b/Source/cmake.h
@@ -136,9 +136,9 @@
 
 #if defined(CMAKE_BUILD_WITH_CMAKE)
   Json::Value ReportVersionJson() const;
-  Json::Value ReportCapabilitiesJson(bool haveServerMode) const;
+  Json::Value ReportCapabilitiesJson() const;
 #endif
-  std::string ReportCapabilities(bool haveServerMode) const;
+  std::string ReportCapabilities() const;
 
   //@{
   /**
diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx
index a983d30..86082e5 100644
--- a/Source/cmcmd.cxx
+++ b/Source/cmcmd.cxx
@@ -734,11 +734,7 @@
         return 1;
       }
       cmake cm(cmake::RoleInternal, cmState::Unknown);
-#if defined(CMAKE_BUILD_WITH_CMAKE)
-      std::cout << cm.ReportCapabilities(true);
-#else
-      std::cout << cm.ReportCapabilities(false);
-#endif
+      std::cout << cm.ReportCapabilities();
       return 0;
     }
 
diff --git a/Tests/FindBoost/Test/CMakeLists.txt b/Tests/FindBoost/Test/CMakeLists.txt
index 39e92c1..f60ccfa 100644
--- a/Tests/FindBoost/Test/CMakeLists.txt
+++ b/Tests/FindBoost/Test/CMakeLists.txt
@@ -2,6 +2,7 @@
 project(TestFindBoost CXX)
 include(CTest)
 
+set(Boost_NO_BOOST_CMAKE ON)
 find_package(Boost REQUIRED COMPONENTS filesystem thread
                    OPTIONAL_COMPONENTS program_options foobar)
 
diff --git a/Tests/FindPackageTest/CMakeLists.txt b/Tests/FindPackageTest/CMakeLists.txt
index 8802b73..affe5d5 100644
--- a/Tests/FindPackageTest/CMakeLists.txt
+++ b/Tests/FindPackageTest/CMakeLists.txt
@@ -579,3 +579,16 @@
 
 set(CMAKE_FIND_PACKAGE_PREFER_CONFIG OFF)
 set(CMAKE_PREFIX_PATH)
+
+############################################################################
+##Test find_package CMAKE_FIND_PACKAGE_PREFER_CONFIG with module fallback
+
+set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/PreferConfigOnlyModule)
+
+set(CMAKE_FIND_PACKAGE_PREFER_CONFIG ON)
+
+find_package(ACME REQUIRED)
+
+if(NOT ACME_FOUND)
+    message(SEND_ERROR "Did not find ACME package")
+endif()
diff --git a/Tests/FindPackageTest/PreferConfigOnlyModule/FindACME.cmake b/Tests/FindPackageTest/PreferConfigOnlyModule/FindACME.cmake
new file mode 100644
index 0000000..7a4e1b3
--- /dev/null
+++ b/Tests/FindPackageTest/PreferConfigOnlyModule/FindACME.cmake
@@ -0,0 +1 @@
+set(ACME_FOUND TRUE)
diff --git a/Tests/RunCMake/CommandLine/E_capabilities-stdout.txt b/Tests/RunCMake/CommandLine/E_capabilities-stdout.txt
index 6c5ea44..b4b170e 100644
--- a/Tests/RunCMake/CommandLine/E_capabilities-stdout.txt
+++ b/Tests/RunCMake/CommandLine/E_capabilities-stdout.txt
@@ -1 +1 @@
-^{.*}$
+^{"fileApi":{"requests":\[{"kind":"codemodel","version":\[{"major":2,"minor":0}]},{"kind":"cache","version":\[{"major":2,"minor":0}]},{"kind":"cmakeFiles","version":\[{"major":1,"minor":0}]}]},"generators":\[.*\],"serverMode":true,"version":{.*}}$
diff --git a/Tests/RunCMake/FindBoost/CMakePackage/BoostConfig.cmake b/Tests/RunCMake/FindBoost/CMakePackage/BoostConfig.cmake
index d13bbf3..36a9abd 100644
--- a/Tests/RunCMake/FindBoost/CMakePackage/BoostConfig.cmake
+++ b/Tests/RunCMake/FindBoost/CMakePackage/BoostConfig.cmake
@@ -1 +1,4 @@
 set(Boost_DATE_TIME_FOUND 1)
+add_library(Boost::boost INTERFACE IMPORTED)
+add_library(Boost::headers INTERFACE IMPORTED)
+add_library(Boost::date_time UNKNOWN IMPORTED)
diff --git a/Tests/RunCMake/FindBoost/CMakePackage_LowerCaseTargetPrefix/BoostConfig.cmake b/Tests/RunCMake/FindBoost/CMakePackage_LowerCaseTargetPrefix/BoostConfig.cmake
new file mode 100644
index 0000000..cf13b4a
--- /dev/null
+++ b/Tests/RunCMake/FindBoost/CMakePackage_LowerCaseTargetPrefix/BoostConfig.cmake
@@ -0,0 +1,26 @@
+# No boost::boost target and all targets start with lowercase letters
+# Similar to https://github.com/boost-cmake/boost-cmake
+
+add_library(boost::headers INTERFACE IMPORTED)
+target_include_directories(boost::headers INTERFACE "${CMAKE_CURRENT_LIST_DIR}/include")
+
+set(Boost_date_time_FOUND 1)
+add_library(boost::date_time UNKNOWN IMPORTED)
+set_target_properties(boost::date_time PROPERTIES
+  IMPORTED_CONFIGURATIONS RELEASE
+  IMPORTED_LOCATION_RELEASE "${CMAKE_CURRENT_LIST_DIR}/lib/libboost_date_time.a"
+  )
+set(Boost_python37_FOUND 1)
+add_library(boost::python UNKNOWN IMPORTED)
+set_target_properties(boost::python PROPERTIES
+  IMPORTED_CONFIGURATIONS "RELEASE;DEBUG"
+  IMPORTED_LOCATION_RELEASE "${CMAKE_CURRENT_LIST_DIR}/lib/libboost_python_release.a"
+  IMPORTED_LOCATION_DEBUG "${CMAKE_CURRENT_LIST_DIR}/lib/libboost_python.a"
+  )
+set(Boost_mpi_python2_FOUND 1)
+add_library(boost::mpi_python UNKNOWN IMPORTED)
+set_target_properties(boost::mpi_python PROPERTIES
+  IMPORTED_CONFIGURATIONS "RELEASE;DEBUG"
+  IMPORTED_LOCATION_RELEASE "${CMAKE_CURRENT_LIST_DIR}/lib/libboost_mpi_python.a"
+  IMPORTED_LOCATION_DEBUG "${CMAKE_CURRENT_LIST_DIR}/lib/libboost_mpi_python.a"
+  )
diff --git a/Tests/RunCMake/FindBoost/CMakePackage_LowerCaseTargetPrefix/BoostConfigVersion.cmake b/Tests/RunCMake/FindBoost/CMakePackage_LowerCaseTargetPrefix/BoostConfigVersion.cmake
new file mode 100644
index 0000000..b4b6060
--- /dev/null
+++ b/Tests/RunCMake/FindBoost/CMakePackage_LowerCaseTargetPrefix/BoostConfigVersion.cmake
@@ -0,0 +1,7 @@
+set(PACKAGE_VERSION 1.70.42)
+if(PACKAGE_FIND_VERSION_MAJOR EQUAL 1)
+  set(PACKAGE_VERSION_COMPATIBLE 1)
+  if(PACKAGE_FIND_VERSION_MINOR EQUAL 70 AND PACKAGE_FIND_VERSION_PATCH EQUAL 42)
+    set(PACKAGE_VERSION_EXACT 1)
+  endif()
+endif()
diff --git a/Tests/RunCMake/FindBoost/CMakePackage_LowerCaseTargetPrefix/include/boost/version.hpp b/Tests/RunCMake/FindBoost/CMakePackage_LowerCaseTargetPrefix/include/boost/version.hpp
new file mode 100644
index 0000000..fe8e72c
--- /dev/null
+++ b/Tests/RunCMake/FindBoost/CMakePackage_LowerCaseTargetPrefix/include/boost/version.hpp
@@ -0,0 +1,34 @@
+//  Boost version.hpp configuration header file
+//  ------------------------------//
+
+//  (C) Copyright John maddock 1999. Distributed under the Boost
+//  Software License, Version 1.0. (See accompanying file
+//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org/libs/config for documentation
+
+#ifndef BOOST_VERSION_HPP
+#define BOOST_VERSION_HPP
+
+//
+//  Caution: this is the only Boost header that is guaranteed
+//  to change with every Boost release. Including this header
+//  will cause a recompile every time a new Boost version is
+//  used.
+//
+//  BOOST_VERSION % 100 is the patch level
+//  BOOST_VERSION / 100 % 1000 is the minor version
+//  BOOST_VERSION / 100000 is the major version
+
+#define BOOST_VERSION 1070042
+
+//
+//  BOOST_LIB_VERSION must be defined to be the same as BOOST_VERSION
+//  but as a *string* in the form "x_y[_z]" where x is the major version
+//  number, y is the minor version number, and z is the patch level if not 0.
+//  This is used by <config/auto_link.hpp> to select which library version to
+//  link to.
+
+#define BOOST_LIB_VERSION "1_70_42"
+
+#endif
diff --git a/Tests/RunCMake/FindBoost/CMakePackage_MissingTarget/BoostConfig.cmake b/Tests/RunCMake/FindBoost/CMakePackage_MissingTarget/BoostConfig.cmake
new file mode 100644
index 0000000..97d4c79
--- /dev/null
+++ b/Tests/RunCMake/FindBoost/CMakePackage_MissingTarget/BoostConfig.cmake
@@ -0,0 +1,7 @@
+# Don't have targets
+set(Boost_INCLUDE_DIRS "${CMAKE_CURRENT_LIST_DIR}/include")
+
+set(Boost_DATE_TIME_FOUND 1)
+set(Boost_DATE_TIME_LIBRARY "${CMAKE_CURRENT_LIST_DIR}/lib/libboost_date_time.a")
+
+set(Boost_LIBRARIES ${Boost_DATE_TIME_LIBRARY})
diff --git a/Tests/RunCMake/FindBoost/CMakePackage_MissingTarget/BoostConfigVersion.cmake b/Tests/RunCMake/FindBoost/CMakePackage_MissingTarget/BoostConfigVersion.cmake
new file mode 100644
index 0000000..b4b6060
--- /dev/null
+++ b/Tests/RunCMake/FindBoost/CMakePackage_MissingTarget/BoostConfigVersion.cmake
@@ -0,0 +1,7 @@
+set(PACKAGE_VERSION 1.70.42)
+if(PACKAGE_FIND_VERSION_MAJOR EQUAL 1)
+  set(PACKAGE_VERSION_COMPATIBLE 1)
+  if(PACKAGE_FIND_VERSION_MINOR EQUAL 70 AND PACKAGE_FIND_VERSION_PATCH EQUAL 42)
+    set(PACKAGE_VERSION_EXACT 1)
+  endif()
+endif()
diff --git a/Tests/RunCMake/FindBoost/CMakePackage_MissingTarget/include/boost/version.hpp b/Tests/RunCMake/FindBoost/CMakePackage_MissingTarget/include/boost/version.hpp
new file mode 100644
index 0000000..fe8e72c
--- /dev/null
+++ b/Tests/RunCMake/FindBoost/CMakePackage_MissingTarget/include/boost/version.hpp
@@ -0,0 +1,34 @@
+//  Boost version.hpp configuration header file
+//  ------------------------------//
+
+//  (C) Copyright John maddock 1999. Distributed under the Boost
+//  Software License, Version 1.0. (See accompanying file
+//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org/libs/config for documentation
+
+#ifndef BOOST_VERSION_HPP
+#define BOOST_VERSION_HPP
+
+//
+//  Caution: this is the only Boost header that is guaranteed
+//  to change with every Boost release. Including this header
+//  will cause a recompile every time a new Boost version is
+//  used.
+//
+//  BOOST_VERSION % 100 is the patch level
+//  BOOST_VERSION / 100 % 1000 is the minor version
+//  BOOST_VERSION / 100000 is the major version
+
+#define BOOST_VERSION 1070042
+
+//
+//  BOOST_LIB_VERSION must be defined to be the same as BOOST_VERSION
+//  but as a *string* in the form "x_y[_z]" where x is the major version
+//  number, y is the minor version number, and z is the patch level if not 0.
+//  This is used by <config/auto_link.hpp> to select which library version to
+//  link to.
+
+#define BOOST_LIB_VERSION "1_70_42"
+
+#endif
diff --git a/Tests/RunCMake/FindBoost/CMakePackage_New/BoostConfig.cmake b/Tests/RunCMake/FindBoost/CMakePackage_New/BoostConfig.cmake
new file mode 100644
index 0000000..3a88f26
--- /dev/null
+++ b/Tests/RunCMake/FindBoost/CMakePackage_New/BoostConfig.cmake
@@ -0,0 +1,24 @@
+add_library(Boost::boost INTERFACE IMPORTED)
+add_library(Boost::headers INTERFACE IMPORTED)
+target_include_directories(Boost::headers INTERFACE "${CMAKE_CURRENT_LIST_DIR}/include")
+
+set(Boost_date_time_FOUND 1)
+add_library(Boost::date_time UNKNOWN IMPORTED)
+set_target_properties(Boost::date_time PROPERTIES
+  IMPORTED_CONFIGURATIONS RELEASE
+  IMPORTED_LOCATION_RELEASE "${CMAKE_CURRENT_LIST_DIR}/lib/libboost_date_time.a"
+  )
+set(Boost_python37_FOUND 1)
+add_library(Boost::python UNKNOWN IMPORTED)
+set_target_properties(Boost::python PROPERTIES
+  IMPORTED_CONFIGURATIONS "RELEASE;DEBUG"
+  IMPORTED_LOCATION_RELEASE "${CMAKE_CURRENT_LIST_DIR}/lib/libboost_python_release.a"
+  IMPORTED_LOCATION_DEBUG "${CMAKE_CURRENT_LIST_DIR}/lib/libboost_python.a"
+  )
+set(Boost_mpi_python2_FOUND 1)
+add_library(Boost::mpi_python UNKNOWN IMPORTED)
+set_target_properties(Boost::mpi_python PROPERTIES
+  IMPORTED_CONFIGURATIONS "RELEASE;DEBUG"
+  IMPORTED_LOCATION_RELEASE "${CMAKE_CURRENT_LIST_DIR}/lib/libboost_mpi_python.a"
+  IMPORTED_LOCATION_DEBUG "${CMAKE_CURRENT_LIST_DIR}/lib/libboost_mpi_python.a"
+  )
diff --git a/Tests/RunCMake/FindBoost/CMakePackage_New/BoostConfigVersion.cmake b/Tests/RunCMake/FindBoost/CMakePackage_New/BoostConfigVersion.cmake
new file mode 100644
index 0000000..b4b6060
--- /dev/null
+++ b/Tests/RunCMake/FindBoost/CMakePackage_New/BoostConfigVersion.cmake
@@ -0,0 +1,7 @@
+set(PACKAGE_VERSION 1.70.42)
+if(PACKAGE_FIND_VERSION_MAJOR EQUAL 1)
+  set(PACKAGE_VERSION_COMPATIBLE 1)
+  if(PACKAGE_FIND_VERSION_MINOR EQUAL 70 AND PACKAGE_FIND_VERSION_PATCH EQUAL 42)
+    set(PACKAGE_VERSION_EXACT 1)
+  endif()
+endif()
diff --git a/Tests/RunCMake/FindBoost/CMakePackage_New/include/boost/version.hpp b/Tests/RunCMake/FindBoost/CMakePackage_New/include/boost/version.hpp
new file mode 100644
index 0000000..fe8e72c
--- /dev/null
+++ b/Tests/RunCMake/FindBoost/CMakePackage_New/include/boost/version.hpp
@@ -0,0 +1,34 @@
+//  Boost version.hpp configuration header file
+//  ------------------------------//
+
+//  (C) Copyright John maddock 1999. Distributed under the Boost
+//  Software License, Version 1.0. (See accompanying file
+//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org/libs/config for documentation
+
+#ifndef BOOST_VERSION_HPP
+#define BOOST_VERSION_HPP
+
+//
+//  Caution: this is the only Boost header that is guaranteed
+//  to change with every Boost release. Including this header
+//  will cause a recompile every time a new Boost version is
+//  used.
+//
+//  BOOST_VERSION % 100 is the patch level
+//  BOOST_VERSION / 100 % 1000 is the minor version
+//  BOOST_VERSION / 100000 is the major version
+
+#define BOOST_VERSION 1070042
+
+//
+//  BOOST_LIB_VERSION must be defined to be the same as BOOST_VERSION
+//  but as a *string* in the form "x_y[_z]" where x is the major version
+//  number, y is the minor version number, and z is the patch level if not 0.
+//  This is used by <config/auto_link.hpp> to select which library version to
+//  link to.
+
+#define BOOST_LIB_VERSION "1_70_42"
+
+#endif
diff --git a/Tests/RunCMake/FindBoost/CMakePackage_New/lib/libboost_date_time.a b/Tests/RunCMake/FindBoost/CMakePackage_New/lib/libboost_date_time.a
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Tests/RunCMake/FindBoost/CMakePackage_New/lib/libboost_date_time.a
diff --git a/Tests/RunCMake/FindBoost/CMakePackage_New/lib/libboost_mpi_python.a b/Tests/RunCMake/FindBoost/CMakePackage_New/lib/libboost_mpi_python.a
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Tests/RunCMake/FindBoost/CMakePackage_New/lib/libboost_mpi_python.a
diff --git a/Tests/RunCMake/FindBoost/CMakePackage_New/lib/libboost_python.a b/Tests/RunCMake/FindBoost/CMakePackage_New/lib/libboost_python.a
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Tests/RunCMake/FindBoost/CMakePackage_New/lib/libboost_python.a
diff --git a/Tests/RunCMake/FindBoost/CMakePackage_New/lib/libboost_python_release.a b/Tests/RunCMake/FindBoost/CMakePackage_New/lib/libboost_python_release.a
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Tests/RunCMake/FindBoost/CMakePackage_New/lib/libboost_python_release.a
diff --git a/Tests/RunCMake/FindBoost/CMakePackage_NoHeaderTarget/BoostConfig.cmake b/Tests/RunCMake/FindBoost/CMakePackage_NoHeaderTarget/BoostConfig.cmake
new file mode 100644
index 0000000..ba2269a
--- /dev/null
+++ b/Tests/RunCMake/FindBoost/CMakePackage_NoHeaderTarget/BoostConfig.cmake
@@ -0,0 +1,25 @@
+# UPPER_CASE FOUND vars and no header targets
+
+set(Boost_DATE_TIME_FOUND 1)
+add_library(Boost::date_time UNKNOWN IMPORTED)
+set_target_properties(Boost::date_time PROPERTIES
+  IMPORTED_CONFIGURATIONS RELEASE
+  IMPORTED_LOCATION_RELEASE "${CMAKE_CURRENT_LIST_DIR}/lib/libboost_date_time.a"
+  INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_LIST_DIR}/include"
+  )
+set(Boost_PYTHON37_FOUND 1)
+add_library(Boost::python UNKNOWN IMPORTED)
+set_target_properties(Boost::python PROPERTIES
+  IMPORTED_CONFIGURATIONS "RELEASE;DEBUG"
+  IMPORTED_LOCATION_RELEASE "${CMAKE_CURRENT_LIST_DIR}/lib/libboost_python_release.a"
+  IMPORTED_LOCATION_DEBUG "${CMAKE_CURRENT_LIST_DIR}/lib/libboost_python.a"
+  INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_LIST_DIR}/include"
+  )
+set(Boost_MPI_PYTHON2_FOUND 1)
+add_library(Boost::mpi_python UNKNOWN IMPORTED)
+set_target_properties(Boost::mpi_python PROPERTIES
+  IMPORTED_CONFIGURATIONS "RELEASE;DEBUG"
+  IMPORTED_LOCATION_RELEASE "${CMAKE_CURRENT_LIST_DIR}/lib/libboost_mpi_python.a"
+  IMPORTED_LOCATION_DEBUG "${CMAKE_CURRENT_LIST_DIR}/lib/libboost_mpi_python.a"
+  INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_LIST_DIR}/include"
+  )
diff --git a/Tests/RunCMake/FindBoost/CMakePackage_NoHeaderTarget/BoostConfigVersion.cmake b/Tests/RunCMake/FindBoost/CMakePackage_NoHeaderTarget/BoostConfigVersion.cmake
new file mode 100644
index 0000000..b4b6060
--- /dev/null
+++ b/Tests/RunCMake/FindBoost/CMakePackage_NoHeaderTarget/BoostConfigVersion.cmake
@@ -0,0 +1,7 @@
+set(PACKAGE_VERSION 1.70.42)
+if(PACKAGE_FIND_VERSION_MAJOR EQUAL 1)
+  set(PACKAGE_VERSION_COMPATIBLE 1)
+  if(PACKAGE_FIND_VERSION_MINOR EQUAL 70 AND PACKAGE_FIND_VERSION_PATCH EQUAL 42)
+    set(PACKAGE_VERSION_EXACT 1)
+  endif()
+endif()
diff --git a/Tests/RunCMake/FindBoost/CMakePackage_NoHeaderTarget/include/boost/version.hpp b/Tests/RunCMake/FindBoost/CMakePackage_NoHeaderTarget/include/boost/version.hpp
new file mode 100644
index 0000000..fe8e72c
--- /dev/null
+++ b/Tests/RunCMake/FindBoost/CMakePackage_NoHeaderTarget/include/boost/version.hpp
@@ -0,0 +1,34 @@
+//  Boost version.hpp configuration header file
+//  ------------------------------//
+
+//  (C) Copyright John maddock 1999. Distributed under the Boost
+//  Software License, Version 1.0. (See accompanying file
+//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org/libs/config for documentation
+
+#ifndef BOOST_VERSION_HPP
+#define BOOST_VERSION_HPP
+
+//
+//  Caution: this is the only Boost header that is guaranteed
+//  to change with every Boost release. Including this header
+//  will cause a recompile every time a new Boost version is
+//  used.
+//
+//  BOOST_VERSION % 100 is the patch level
+//  BOOST_VERSION / 100 % 1000 is the minor version
+//  BOOST_VERSION / 100000 is the major version
+
+#define BOOST_VERSION 1070042
+
+//
+//  BOOST_LIB_VERSION must be defined to be the same as BOOST_VERSION
+//  but as a *string* in the form "x_y[_z]" where x is the major version
+//  number, y is the minor version number, and z is the patch level if not 0.
+//  This is used by <config/auto_link.hpp> to select which library version to
+//  link to.
+
+#define BOOST_LIB_VERSION "1_70_42"
+
+#endif
diff --git a/Tests/RunCMake/FindBoost/LegacyVars-LowercaseTargetPrefix-stdout.txt b/Tests/RunCMake/FindBoost/LegacyVars-LowercaseTargetPrefix-stdout.txt
new file mode 100644
index 0000000..a781dce
--- /dev/null
+++ b/Tests/RunCMake/FindBoost/LegacyVars-LowercaseTargetPrefix-stdout.txt
@@ -0,0 +1,34 @@
+-- Found Boost: [^
+]* \(found suitable version "1\.70\.42", minimum required is "1\.70"\) found components:  date_time python37 mpi_python2 *
+-- Boost_FOUND: TRUE
+-- Boost_INCLUDE_DIRS: [^
+]*/Tests/RunCMake/FindBoost/CMakePackage[^/]*/include
+-- Boost_LIBRARY_DIRS: [^
+]*/Tests/RunCMake/FindBoost/CMakePackage[^/]*/lib
+-- Boost_LIBRARIES: boost::date_time;boost::python;boost::mpi_python
+-- Boost_DATE_TIME_FOUND: 1
+-- Boost_DATE_TIME_LIBRARY: boost::date_time
+-- Boost_PYTHON37_FOUND: 1
+-- Boost_PYTHON37_LIBRARY: boost::python
+-- Boost_MPI_PYTHON2_FOUND: 1
+-- Boost_MPI_PYTHON2_LIBRARY: boost::mpi_python
+-- Boost_VERSION_MACRO: 1070042
+-- Boost_VERSION_STRING: 1.70.42
+-- Boost_VERSION: 1.70.42
+-- Boost_LIB_VERSION: 1_70_42
+-- Boost_MAJOR_VERSION: 1
+-- Boost_MINOR_VERSION: 70
+-- Boost_SUBMINOR_VERSION: 42
+-- Boost_INCLUDE_DIR: [^
+]*/Tests/RunCMake/FindBoost/CMakePackage[^/]*/include
+-- Boost_DATE_TIME_LIBRARY_DEBUG: *
+-- Boost_DATE_TIME_LIBRARY_RELEASE: [^
+]*/Tests/RunCMake/FindBoost/CMakePackage[^/]*/lib/libboost_date_time.a
+-- Boost_PYTHON37_LIBRARY_DEBUG: [^
+]*/Tests/RunCMake/FindBoost/CMakePackage[^/]*/lib/libboost_python.a
+-- Boost_PYTHON37_LIBRARY_RELEASE: [^
+]*/Tests/RunCMake/FindBoost/CMakePackage[^/]*/lib/libboost_python_release.a
+-- Boost_MPI_PYTHON2_LIBRARY_DEBUG: [^
+]*/Tests/RunCMake/FindBoost/CMakePackage[^/]*/lib/libboost_mpi_python.a
+-- Boost_MPI_PYTHON2_LIBRARY_RELEASE: [^
+]*/Tests/RunCMake/FindBoost/CMakePackage[^/]*/lib/libboost_mpi_python.a
diff --git a/Tests/RunCMake/FindBoost/LegacyVars-LowercaseTargetPrefix.cmake b/Tests/RunCMake/FindBoost/LegacyVars-LowercaseTargetPrefix.cmake
new file mode 100644
index 0000000..a398c2d
--- /dev/null
+++ b/Tests/RunCMake/FindBoost/LegacyVars-LowercaseTargetPrefix.cmake
@@ -0,0 +1,6 @@
+# Use a (made up) modern style BoostConfig that defines all targets
+# as boost::<component> with appropriate properties set
+# No legacy variables defined in the BoostConfig
+set(Boost_DIR ${CMAKE_CURRENT_SOURCE_DIR}/CMakePackage_LowerCaseTargetPrefix)
+
+include(${CMAKE_CURRENT_SOURCE_DIR}/LegacyVars.cmake)
diff --git a/Tests/RunCMake/FindBoost/LegacyVars-NoHeaderTarget.cmake b/Tests/RunCMake/FindBoost/LegacyVars-NoHeaderTarget.cmake
new file mode 100644
index 0000000..edb6dda
--- /dev/null
+++ b/Tests/RunCMake/FindBoost/LegacyVars-NoHeaderTarget.cmake
@@ -0,0 +1,6 @@
+# Use a (made up?) BoostConfig that defines all targets
+# as Boost::<component> with appropriate properties set
+# But no Boost::headers or Boost::boost target is defined
+set(Boost_DIR ${CMAKE_CURRENT_SOURCE_DIR}/CMakePackage_NoHeaderTarget)
+
+include(${CMAKE_CURRENT_SOURCE_DIR}/LegacyVars.cmake)
diff --git a/Tests/RunCMake/FindBoost/LegacyVars-TargetsDefined-stdout.txt b/Tests/RunCMake/FindBoost/LegacyVars-TargetsDefined-stdout.txt
new file mode 100644
index 0000000..a4e9c6a
--- /dev/null
+++ b/Tests/RunCMake/FindBoost/LegacyVars-TargetsDefined-stdout.txt
@@ -0,0 +1,34 @@
+-- Found Boost: [^
+]* \(found suitable version "1\.70\.42", minimum required is "1\.70"\) found components:  date_time python37 mpi_python2 *
+-- Boost_FOUND: TRUE
+-- Boost_INCLUDE_DIRS: [^
+]*/Tests/RunCMake/FindBoost/CMakePackage[^/]*/include
+-- Boost_LIBRARY_DIRS: [^
+]*/Tests/RunCMake/FindBoost/CMakePackage[^/]*/lib
+-- Boost_LIBRARIES: Boost::date_time;Boost::python;Boost::mpi_python
+-- Boost_DATE_TIME_FOUND: 1
+-- Boost_DATE_TIME_LIBRARY: Boost::date_time
+-- Boost_PYTHON37_FOUND: 1
+-- Boost_PYTHON37_LIBRARY: Boost::python
+-- Boost_MPI_PYTHON2_FOUND: 1
+-- Boost_MPI_PYTHON2_LIBRARY: Boost::mpi_python
+-- Boost_VERSION_MACRO: 1070042
+-- Boost_VERSION_STRING: 1.70.42
+-- Boost_VERSION: 1.70.42
+-- Boost_LIB_VERSION: 1_70_42
+-- Boost_MAJOR_VERSION: 1
+-- Boost_MINOR_VERSION: 70
+-- Boost_SUBMINOR_VERSION: 42
+-- Boost_INCLUDE_DIR: [^
+]*/Tests/RunCMake/FindBoost/CMakePackage[^/]*/include
+-- Boost_DATE_TIME_LIBRARY_DEBUG: *
+-- Boost_DATE_TIME_LIBRARY_RELEASE: [^
+]*/Tests/RunCMake/FindBoost/CMakePackage[^/]*/lib/libboost_date_time.a
+-- Boost_PYTHON37_LIBRARY_DEBUG: [^
+]*/Tests/RunCMake/FindBoost/CMakePackage[^/]*/lib/libboost_python.a
+-- Boost_PYTHON37_LIBRARY_RELEASE: [^
+]*/Tests/RunCMake/FindBoost/CMakePackage[^/]*/lib/libboost_python_release.a
+-- Boost_MPI_PYTHON2_LIBRARY_DEBUG: [^
+]*/Tests/RunCMake/FindBoost/CMakePackage[^/]*/lib/libboost_mpi_python.a
+-- Boost_MPI_PYTHON2_LIBRARY_RELEASE: [^
+]*/Tests/RunCMake/FindBoost/CMakePackage[^/]*/lib/libboost_mpi_python.a
diff --git a/Tests/RunCMake/FindBoost/LegacyVars-TargetsDefined.cmake b/Tests/RunCMake/FindBoost/LegacyVars-TargetsDefined.cmake
new file mode 100644
index 0000000..19ad49f
--- /dev/null
+++ b/Tests/RunCMake/FindBoost/LegacyVars-TargetsDefined.cmake
@@ -0,0 +1,6 @@
+# Use a modern style BoostConfig that defines all targets
+# as Boost::<component> with appropriate properties set
+# No legacy variables defined in the BoostConfig
+set(Boost_DIR ${CMAKE_CURRENT_SOURCE_DIR}/CMakePackage_New)
+
+include(${CMAKE_CURRENT_SOURCE_DIR}/LegacyVars.cmake)
diff --git a/Tests/RunCMake/FindBoost/LegacyVars.cmake b/Tests/RunCMake/FindBoost/LegacyVars.cmake
new file mode 100644
index 0000000..d0d5ee0
--- /dev/null
+++ b/Tests/RunCMake/FindBoost/LegacyVars.cmake
@@ -0,0 +1,28 @@
+find_package(Boost 1.70 COMPONENTS date_time python37 mpi_python2)
+
+foreach(var Boost_FOUND Boost_INCLUDE_DIRS Boost_LIBRARY_DIRS Boost_LIBRARIES
+  Boost_DATE_TIME_FOUND Boost_DATE_TIME_LIBRARY
+  Boost_PYTHON37_FOUND Boost_PYTHON37_LIBRARY
+  Boost_MPI_PYTHON2_FOUND Boost_MPI_PYTHON2_LIBRARY
+  Boost_VERSION_MACRO Boost_VERSION_STRING Boost_VERSION Boost_LIB_VERSION
+  Boost_MAJOR_VERSION Boost_MINOR_VERSION Boost_SUBMINOR_VERSION
+)
+  message(STATUS "${var}: ${${var}}")
+endforeach()
+
+foreach(cachevar Boost_INCLUDE_DIR
+  Boost_DATE_TIME_LIBRARY_DEBUG Boost_DATE_TIME_LIBRARY_RELEASE
+  Boost_PYTHON37_LIBRARY_DEBUG Boost_PYTHON37_LIBRARY_RELEASE
+  Boost_MPI_PYTHON2_LIBRARY_DEBUG Boost_MPI_PYTHON2_LIBRARY_RELEASE
+)
+  unset(${cachevar})
+  message(STATUS "${cachevar}: ${${cachevar}}")
+endforeach()
+
+foreach(lib Boost::headers Boost::date_time Boost::python Boost::mpi_python
+  Boost::boost Boost::diagnostic_definitions Boost::disable_autolinking Boost::dynamic_linking
+)
+  if(NOT TARGET ${lib})
+    message(FATAL_ERROR "Missing target ${lib}")
+  endif()
+endforeach()
diff --git a/Tests/RunCMake/FindBoost/MissingTarget-stdout.txt b/Tests/RunCMake/FindBoost/MissingTarget-stdout.txt
new file mode 100644
index 0000000..8e9d684
--- /dev/null
+++ b/Tests/RunCMake/FindBoost/MissingTarget-stdout.txt
@@ -0,0 +1,22 @@
+-- Found Boost: [^
+]* \(found suitable version "1\.70\.42", minimum required is "1\.70"\) found components:  date_time *
+-- Boost_FOUND: TRUE
+-- Boost_INCLUDE_DIRS: [^
+]*/Tests/RunCMake/FindBoost/CMakePackage_MissingTarget/include
+-- Boost_LIBRARY_DIRS: *
+-- Boost_LIBRARIES: [^
+]*/Tests/RunCMake/FindBoost/CMakePackage_MissingTarget/lib/libboost_date_time.a
+-- Boost_DATE_TIME_FOUND: 1
+-- Boost_DATE_TIME_LIBRARY: [^
+]*/Tests/RunCMake/FindBoost/CMakePackage_MissingTarget/lib/libboost_date_time.a
+-- Boost_VERSION_MACRO: 1070042
+-- Boost_VERSION_STRING: 1.70.42
+-- Boost_VERSION: 1.70.42
+-- Boost_LIB_VERSION: 1_70_42
+-- Boost_MAJOR_VERSION: 1
+-- Boost_MINOR_VERSION: 70
+-- Boost_SUBMINOR_VERSION: 42
+-- Boost_INCLUDE_DIR: [^
+]*/Tests/RunCMake/FindBoost/CMakePackage_MissingTarget/include
+-- Boost_DATE_TIME_LIBRARY_DEBUG: *
+-- Boost_DATE_TIME_LIBRARY_RELEASE: *
diff --git a/Tests/RunCMake/FindBoost/MissingTarget.cmake b/Tests/RunCMake/FindBoost/MissingTarget.cmake
new file mode 100644
index 0000000..581e006
--- /dev/null
+++ b/Tests/RunCMake/FindBoost/MissingTarget.cmake
@@ -0,0 +1,25 @@
+set(Boost_DIR ${CMAKE_CURRENT_SOURCE_DIR}/CMakePackage_MissingTarget)
+find_package(Boost 1.70 COMPONENTS date_time)
+
+foreach(var Boost_FOUND Boost_INCLUDE_DIRS Boost_LIBRARY_DIRS Boost_LIBRARIES
+  Boost_DATE_TIME_FOUND Boost_DATE_TIME_LIBRARY
+  Boost_VERSION_MACRO Boost_VERSION_STRING Boost_VERSION Boost_LIB_VERSION
+  Boost_MAJOR_VERSION Boost_MINOR_VERSION Boost_SUBMINOR_VERSION
+)
+  message(STATUS "${var}: ${${var}}")
+endforeach()
+
+foreach(cachevar Boost_INCLUDE_DIR
+  Boost_DATE_TIME_LIBRARY_DEBUG Boost_DATE_TIME_LIBRARY_RELEASE
+)
+  unset(${cachevar})
+  message(STATUS "${cachevar}: ${${cachevar}}")
+endforeach()
+
+foreach(lib Boost::headers
+  Boost::boost Boost::diagnostic_definitions Boost::disable_autolinking Boost::dynamic_linking
+)
+  if(NOT TARGET ${lib})
+    message(FATAL_ERROR "Missing target ${lib}")
+  endif()
+endforeach()
diff --git a/Tests/RunCMake/FindBoost/RunCMakeTest.cmake b/Tests/RunCMake/FindBoost/RunCMakeTest.cmake
index 3916890..851a996 100644
--- a/Tests/RunCMake/FindBoost/RunCMakeTest.cmake
+++ b/Tests/RunCMake/FindBoost/RunCMakeTest.cmake
@@ -4,6 +4,14 @@
 run_cmake(CMakePackage)
 run_cmake(NoCXX)
 
+run_cmake(LegacyVars-TargetsDefined) # "Good" BoostConfig
+run_cmake(LegacyVars-LowercaseTargetPrefix)
+set(RunCMake-stdout-file LegacyVars-TargetsDefined-stdout.txt)
+run_cmake(LegacyVars-NoHeaderTarget)
+
+unset(RunCMake-stdout-file)
+run_cmake(MissingTarget)
+
 set(RunCMake-stdout-file CommonResults-stdout.txt)
 run_cmake(ConfigMode)
 run_cmake(ModuleMode)