find_package: Add support for default GLOBAL imported targets

Allow find package to promote scope of imported targets by specifying
an argument to `find_package` or by specifying a CMake variable.
    * Add support for CMAKE_GLOBAL_IMPORT_SCOPE variable
    * Add support for GLOBAL argument to find_package

Additionally add testing for above features.
diff --git a/Help/command/find_package.rst b/Help/command/find_package.rst
index 1a79a8a..4a381fb 100644
--- a/Help/command/find_package.rst
+++ b/Help/command/find_package.rst
@@ -79,7 +79,8 @@
   find_package(<PackageName> [version] [EXACT] [QUIET] [MODULE]
                [REQUIRED] [[COMPONENTS] [components...]]
                [OPTIONAL_COMPONENTS components...]
-               [NO_POLICY_SCOPE])
+               [NO_POLICY_SCOPE]
+               [GLOBAL])
 
 The basic signature is supported by both Module and Config modes.
 The ``MODULE`` keyword implies that only Module mode can be used to find
@@ -115,6 +116,11 @@
 should find all components, no components or some well-defined subset of the
 available components.
 
+Specifying the ``GLOBAL`` keyword will promote all imported targets to
+a global scope in the importing project. Alternatively this functionality
+can be enabled by setting the variable
+:variable:`CMAKE_FIND_PACKAGE_TARGETS_GLOBAL`
+
 .. _FIND_PACKAGE_VERSION_FORMAT:
 
 The ``[version]`` argument requests a version with which the package found
diff --git a/Help/manual/cmake-variables.7.rst b/Help/manual/cmake-variables.7.rst
index da892dd..8d20ae2 100644
--- a/Help/manual/cmake-variables.7.rst
+++ b/Help/manual/cmake-variables.7.rst
@@ -198,6 +198,7 @@
    /variable/CMAKE_FIND_PACKAGE_NO_SYSTEM_PACKAGE_REGISTRY
    /variable/CMAKE_FIND_PACKAGE_PREFER_CONFIG
    /variable/CMAKE_FIND_PACKAGE_RESOLVE_SYMLINKS
+   /variable/CMAKE_FIND_PACKAGE_TARGETS_GLOBAL
    /variable/CMAKE_FIND_PACKAGE_WARN_NO_MODULE
    /variable/CMAKE_FIND_ROOT_PATH
    /variable/CMAKE_FIND_ROOT_PATH_MODE_INCLUDE
diff --git a/Help/release/dev/find_package-global-imported.rst b/Help/release/dev/find_package-global-imported.rst
new file mode 100644
index 0000000..b32d18d
--- /dev/null
+++ b/Help/release/dev/find_package-global-imported.rst
@@ -0,0 +1,9 @@
+find_package-global-imported
+----------------------------
+
+* The :command:`find_package` command gained a `GLOBAL` option that
+  allows for the promotion of imported targets to global scope fur the
+  duration of the :command:`find_package` call.
+
+* Adds support for :variable:`CMAKE_FIND_PACKAGE_TARGETS_GLOBAL` to
+  toggle behavior of the :command:`find_package` command's new GLOBAL option
diff --git a/Help/variable/CMAKE_FIND_PACKAGE_TARGETS_GLOBAL.rst b/Help/variable/CMAKE_FIND_PACKAGE_TARGETS_GLOBAL.rst
new file mode 100644
index 0000000..58efccf
--- /dev/null
+++ b/Help/variable/CMAKE_FIND_PACKAGE_TARGETS_GLOBAL.rst
@@ -0,0 +1,10 @@
+CMAKE_FIND_PACKAGE_TARGETS_GLOBAL
+---------------------------------
+
+Setting to ``TRUE`` promotes all :prop_tgt:`IMPORTED` targets discoverd
+by :command:`find_package` to a ``GLOBAL`` scope.
+
+
+Setting this to ``TRUE`` is akin to specifying ``GLOBAL``
+as an argument to :command:`find_package`.
+Default value is ``OFF``.
diff --git a/Source/cmAddExecutableCommand.cxx b/Source/cmAddExecutableCommand.cxx
index 9dd8a19..16a8965 100644
--- a/Source/cmAddExecutableCommand.cxx
+++ b/Source/cmAddExecutableCommand.cxx
@@ -54,6 +54,10 @@
     }
   }
 
+  if (importTarget && !importGlobal) {
+    importGlobal = mf.IsImportedTargetGlobalScope();
+  }
+
   bool nameOk = cmGeneratorExpression::IsValidTargetName(exename) &&
     !cmGlobalGenerator::IsReservedTarget(exename);
 
diff --git a/Source/cmAddLibraryCommand.cxx b/Source/cmAddLibraryCommand.cxx
index a5d1f6a..29fc09b 100644
--- a/Source/cmAddLibraryCommand.cxx
+++ b/Source/cmAddLibraryCommand.cxx
@@ -131,6 +131,10 @@
     }
   }
 
+  if (importTarget && !importGlobal) {
+    importGlobal = mf.IsImportedTargetGlobalScope();
+  }
+
   if (type == cmStateEnums::INTERFACE_LIBRARY) {
     if (importGlobal && !importTarget) {
       status.SetError(
diff --git a/Source/cmFindPackageCommand.cxx b/Source/cmFindPackageCommand.cxx
index f55d838..18457a7 100644
--- a/Source/cmFindPackageCommand.cxx
+++ b/Source/cmFindPackageCommand.cxx
@@ -262,6 +262,9 @@
     } else if (args[i] == "EXACT") {
       this->VersionExact = true;
       doing = DoingNone;
+    } else if (args[i] == "GLOBAL") {
+      this->GlobalScope = true;
+      doing = DoingNone;
     } else if (args[i] == "MODULE") {
       moduleArgs.insert(i);
       doing = DoingNone;
@@ -364,6 +367,12 @@
     }
   }
 
+  if (!this->GlobalScope) {
+    cmValue value(
+      this->Makefile->GetDefinition("CMAKE_FIND_PACKAGE_TARGETS_GLOBAL"));
+    this->GlobalScope = value.IsOn();
+  }
+
   std::vector<std::string> doubledComponents;
   std::set_intersection(requiredComponents.begin(), requiredComponents.end(),
                         optionalComponents.begin(), optionalComponents.end(),
@@ -1200,6 +1209,11 @@
                                         PolicyScopeRule psr)
 {
   const bool noPolicyScope = !this->PolicyScope || psr == NoPolicyScope;
+
+  using ITScope = cmMakefile::ImportedTargetScope;
+  ITScope scope = this->GlobalScope ? ITScope::Global : ITScope::Local;
+  cmMakefile::SetGlobalTargetImportScope globScope(this->Makefile, scope);
+
   if (this->Makefile->ReadDependentFile(f, noPolicyScope)) {
     return true;
   }
diff --git a/Source/cmFindPackageCommand.h b/Source/cmFindPackageCommand.h
index f921bb0..b9f19e4 100644
--- a/Source/cmFindPackageCommand.h
+++ b/Source/cmFindPackageCommand.h
@@ -199,6 +199,7 @@
   bool UseLibx32Paths = false;
   bool UseRealPath = false;
   bool PolicyScope = true;
+  bool GlobalScope = false;
   std::string LibraryArchitecture;
   std::vector<std::string> Names;
   std::vector<std::string> Configs;
diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx
index be189a6..f0a96a8 100644
--- a/Source/cmMakefile.cxx
+++ b/Source/cmMakefile.cxx
@@ -458,6 +458,11 @@
   return result;
 }
 
+bool cmMakefile::IsImportedTargetGlobalScope() const
+{
+  return this->CurrentImportedTargetScope == ImportedTargetScope::Global;
+}
+
 class cmMakefile::IncludeScope
 {
 public:
diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h
index ad8a014..99cc89f 100644
--- a/Source/cmMakefile.h
+++ b/Source/cmMakefile.h
@@ -860,6 +860,44 @@
   void PushLoopBlockBarrier();
   void PopLoopBlockBarrier();
 
+  bool IsImportedTargetGlobalScope() const;
+
+  enum class ImportedTargetScope
+  {
+    Local,
+    Global,
+  };
+
+  /** Helper class to manage whether imported packages
+   * should be globally scoped based off the find package command
+   */
+  class SetGlobalTargetImportScope
+  {
+  public:
+    SetGlobalTargetImportScope(cmMakefile* mk, ImportedTargetScope const scope)
+      : Makefile(mk)
+    {
+      if (scope == ImportedTargetScope::Global &&
+          !this->Makefile->IsImportedTargetGlobalScope()) {
+        this->Makefile->CurrentImportedTargetScope = scope;
+        this->Set = true;
+      } else {
+        this->Set = false;
+      }
+    }
+    ~SetGlobalTargetImportScope()
+    {
+      if (this->Set) {
+        this->Makefile->CurrentImportedTargetScope =
+          ImportedTargetScope::Local;
+      }
+    }
+
+  private:
+    cmMakefile* Makefile;
+    bool Set;
+  };
+
   /** Helper class to push and pop scopes automatically.  */
   class ScopePushPop
   {
@@ -1124,4 +1162,5 @@
   std::set<std::string> WarnedCMP0074;
   bool IsSourceFileTryCompile;
   mutable bool SuppressSideEffects;
+  ImportedTargetScope CurrentImportedTargetScope;
 };
diff --git a/Tests/RunCMake/find_package/GlobalImportTarget-stdout.txt b/Tests/RunCMake/find_package/GlobalImportTarget-stdout.txt
new file mode 100644
index 0000000..bd06873
--- /dev/null
+++ b/Tests/RunCMake/find_package/GlobalImportTarget-stdout.txt
@@ -0,0 +1,31 @@
+-- IMPORTED TARGET imported_local_target has GLOBAL scope: TRUE
+-- IMPORTED TARGET imported_global_target has GLOBAL scope: TRUE
+-- IMPORTED TARGET imported_local_ex has GLOBAL scope: TRUE
+-- IMPORTED TARGET imported_global_ex has GLOBAL scope: TRUE
+-- IMPORTED TARGET Foo1 has GLOBAL scope: TRUE
+-- IMPORTED TARGET Foo2 has GLOBAL scope: TRUE
+-- IMPORTED TARGET imported_var_local_target has GLOBAL scope: TRUE
+-- IMPORTED TARGET imported_var_global_target has GLOBAL scope: TRUE
+-- IMPORTED TARGET imported_var_local_ex has GLOBAL scope: TRUE
+-- IMPORTED TARGET imported_var_global_ex has GLOBAL scope: TRUE
+-- IMPORTED TARGET imported_global_lib has GLOBAL scope: TRUE
+-- IMPORTED TARGET imported_explicit_global_ex has GLOBAL scope: TRUE
+-- IMPORTED TARGET imported_local_lib has GLOBAL scope: FALSE
+-- IMPORTED TARGET imported_implied_local_ex has GLOBAL scope: FALSE
+-- IMPORTED TARGET imported_no_var_local_target has GLOBAL scope: TRUE
+-- IMPORTED TARGET imported_no_var_global_target has GLOBAL scope: TRUE
+-- IMPORTED TARGET imported_no_var_local_ex has GLOBAL scope: TRUE
+-- IMPORTED TARGET imported_no_var_global_ex has GLOBAL scope: TRUE
+-- IMPORTED TARGET not_imported_not_global has GLOBAL scope: FALSE
+-- IMPORTED TARGET PackName has GLOBAL scope: TRUE
+-- IMPORTED TARGET PackNameExe has GLOBAL scope: TRUE
+-- IMPORTED TARGET PackName1 has GLOBAL scope: TRUE
+-- IMPORTED TARGET PackNameExe1 has GLOBAL scope: TRUE
+-- IMPORTED TARGET local_lib_glob has GLOBAL scope: TRUE
+-- IMPORTED TARGET local_exe_glob has GLOBAL scope: TRUE
+-- IMPORTED TARGET local_lib has GLOBAL scope: FALSE
+-- IMPORTED TARGET local_exe has GLOBAL scope: FALSE
+-- IMPORTED TARGET LT1 has GLOBAL scope: TRUE
+-- IMPORTED TARGET LT2 has GLOBAL scope: TRUE
+-- IMPORTED TARGET LT3 has GLOBAL scope: TRUE
+-- IMPORTED TARGET LT4 has GLOBAL scope: TRUE
diff --git a/Tests/RunCMake/find_package/GlobalImportTarget.cmake b/Tests/RunCMake/find_package/GlobalImportTarget.cmake
new file mode 100644
index 0000000..7e6d2b8
--- /dev/null
+++ b/Tests/RunCMake/find_package/GlobalImportTarget.cmake
@@ -0,0 +1,57 @@
+function (assess_target_property target)
+  get_target_property(target_val "${target}" IMPORTED_GLOBAL)
+  message(STATUS "IMPORTED TARGET ${target} has GLOBAL scope: ${target_val}")
+endfunction ()
+
+list(INSERT CMAKE_MODULE_PATH 0 ${CMAKE_CURRENT_SOURCE_DIR}/PackageRoot)
+
+find_package(GlobalTarget GLOBAL REQUIRED)
+assess_target_property(imported_local_target)
+assess_target_property(imported_global_target)
+assess_target_property(imported_local_ex)
+assess_target_property(imported_global_ex)
+assess_target_property(Foo1)
+assess_target_property(Foo2)
+
+set(CMAKE_FIND_PACKAGE_TARGETS_GLOBAL TRUE)
+find_package(GlobalVarTarget)
+assess_target_property(imported_var_local_target)
+assess_target_property(imported_var_global_target)
+assess_target_property(imported_var_local_ex)
+assess_target_property(imported_var_global_ex)
+set(CMAKE_FIND_PACKAGE_TARGETS_GLOBAL OFF)
+
+find_package(LocalTarget)
+assess_target_property(imported_global_lib)
+assess_target_property(imported_explicit_global_ex)
+assess_target_property(imported_local_lib)
+assess_target_property(imported_implied_local_ex)
+
+find_package(GlobalTargetNoVar GLOBAL)
+assess_target_property(imported_no_var_local_target)
+assess_target_property(imported_no_var_global_target)
+assess_target_property(imported_no_var_local_ex)
+assess_target_property(imported_no_var_global_ex)
+assess_target_property(not_imported_not_global)
+
+set(Baz_DIR "${CMAKE_CURRENT_SOURCE_DIR}/PackageRoot")
+find_package(Baz GLOBAL REQUIRED)
+assess_target_property(PackName)
+assess_target_property(PackNameExe)
+assess_target_property(PackName1)
+assess_target_property(PackNameExe1)
+
+set(Biz_DIR "${CMAKE_CURRENT_SOURCE_DIR}/PackageRoot")
+find_package(Biz REQUIRED)
+assess_target_property(local_lib_glob)
+assess_target_property(local_exe_glob)
+assess_target_property(local_lib)
+assess_target_property(local_exe)
+
+set(CMAKE_FIND_PACKAGE_TARGETS_GLOBAL TRUE)
+set(Simple_DIR "${CMAKE_CURRENT_SOURCE_DIR}/PackageRoot")
+find_package(Simple REQUIRED)
+assess_target_property(LT1)
+assess_target_property(LT2)
+assess_target_property(LT3)
+assess_target_property(LT4)
diff --git a/Tests/RunCMake/find_package/PackageRoot/BazConfig.cmake b/Tests/RunCMake/find_package/PackageRoot/BazConfig.cmake
new file mode 100644
index 0000000..cca95a2
--- /dev/null
+++ b/Tests/RunCMake/find_package/PackageRoot/BazConfig.cmake
@@ -0,0 +1,3 @@
+include(CMakeFindDependencyMacro)
+
+find_dependency(PackName PATHS ${CMAKE_CURRENT_LIST_DIR})
diff --git a/Tests/RunCMake/find_package/PackageRoot/BizConfig.cmake b/Tests/RunCMake/find_package/PackageRoot/BizConfig.cmake
new file mode 100644
index 0000000..5b0e398
--- /dev/null
+++ b/Tests/RunCMake/find_package/PackageRoot/BizConfig.cmake
@@ -0,0 +1,3 @@
+include(CMakeFindDependencyMacro)
+
+find_dependency(LocalPack PATHS ${CMAKE_CURRENT_LIST_DIR})
diff --git a/Tests/RunCMake/find_package/PackageRoot/FindGlobalTarget.cmake b/Tests/RunCMake/find_package/PackageRoot/FindGlobalTarget.cmake
new file mode 100644
index 0000000..9e34613
--- /dev/null
+++ b/Tests/RunCMake/find_package/PackageRoot/FindGlobalTarget.cmake
@@ -0,0 +1,7 @@
+add_library(imported_global_target SHARED IMPORTED GLOBAL)
+add_executable(imported_global_ex IMPORTED GLOBAL)
+
+add_library(imported_local_target SHARED IMPORTED)
+add_executable(imported_local_ex IMPORTED)
+
+find_package(SimpleTarget)
diff --git a/Tests/RunCMake/find_package/PackageRoot/FindGlobalTargetNoVar.cmake b/Tests/RunCMake/find_package/PackageRoot/FindGlobalTargetNoVar.cmake
new file mode 100644
index 0000000..a156f90
--- /dev/null
+++ b/Tests/RunCMake/find_package/PackageRoot/FindGlobalTargetNoVar.cmake
@@ -0,0 +1,7 @@
+add_library(imported_no_var_global_target SHARED IMPORTED GLOBAL)
+add_executable(imported_no_var_global_ex IMPORTED GLOBAL)
+
+add_library(imported_no_var_local_target SHARED IMPORTED)
+add_executable(imported_no_var_local_ex IMPORTED)
+
+add_library(not_imported_not_global INTERFACE)
diff --git a/Tests/RunCMake/find_package/PackageRoot/FindGlobalVarTarget.cmake b/Tests/RunCMake/find_package/PackageRoot/FindGlobalVarTarget.cmake
new file mode 100644
index 0000000..2e96a6c
--- /dev/null
+++ b/Tests/RunCMake/find_package/PackageRoot/FindGlobalVarTarget.cmake
@@ -0,0 +1,5 @@
+add_library(imported_var_global_target SHARED IMPORTED GLOBAL)
+add_executable(imported_var_global_ex IMPORTED GLOBAL)
+
+add_library(imported_var_local_target SHARED IMPORTED)
+add_executable(imported_var_local_ex IMPORTED)
diff --git a/Tests/RunCMake/find_package/PackageRoot/FindLocalTarget.cmake b/Tests/RunCMake/find_package/PackageRoot/FindLocalTarget.cmake
new file mode 100644
index 0000000..d533405
--- /dev/null
+++ b/Tests/RunCMake/find_package/PackageRoot/FindLocalTarget.cmake
@@ -0,0 +1,5 @@
+add_library(imported_global_lib SHARED IMPORTED GLOBAL)
+add_executable(imported_explicit_global_ex IMPORTED GLOBAL)
+
+add_library(imported_local_lib SHARED IMPORTED)
+add_executable(imported_implied_local_ex IMPORTED)
diff --git a/Tests/RunCMake/find_package/PackageRoot/FindSimpleTarget.cmake b/Tests/RunCMake/find_package/PackageRoot/FindSimpleTarget.cmake
new file mode 100644
index 0000000..cd58004
--- /dev/null
+++ b/Tests/RunCMake/find_package/PackageRoot/FindSimpleTarget.cmake
@@ -0,0 +1,2 @@
+add_library(Foo1 SHARED IMPORTED)
+add_executable(Foo2 IMPORTED)
diff --git a/Tests/RunCMake/find_package/PackageRoot/LTConfig.cmake b/Tests/RunCMake/find_package/PackageRoot/LTConfig.cmake
new file mode 100644
index 0000000..f451eb6
--- /dev/null
+++ b/Tests/RunCMake/find_package/PackageRoot/LTConfig.cmake
@@ -0,0 +1,5 @@
+add_library(LT1 INTERFACE IMPORTED)
+add_executable(LT2 IMPORTED)
+
+add_library(LT3 INTERFACE IMPORTED GLOBAL)
+add_executable(LT4 IMPORTED GLOBAL)
diff --git a/Tests/RunCMake/find_package/PackageRoot/LocalPackConfig.cmake b/Tests/RunCMake/find_package/PackageRoot/LocalPackConfig.cmake
new file mode 100644
index 0000000..a962849
--- /dev/null
+++ b/Tests/RunCMake/find_package/PackageRoot/LocalPackConfig.cmake
@@ -0,0 +1,5 @@
+add_library(local_lib_glob SHARED IMPORTED GLOBAL)
+add_executable(local_exe_glob IMPORTED GLOBAL)
+
+add_library(local_lib SHARED IMPORTED)
+add_executable(local_exe IMPORTED)
diff --git a/Tests/RunCMake/find_package/PackageRoot/PackNameConfig.cmake b/Tests/RunCMake/find_package/PackageRoot/PackNameConfig.cmake
new file mode 100644
index 0000000..38dd2f8
--- /dev/null
+++ b/Tests/RunCMake/find_package/PackageRoot/PackNameConfig.cmake
@@ -0,0 +1,5 @@
+add_library(PackName INTERFACE IMPORTED GLOBAL)
+add_executable(PackNameExe IMPORTED GLOBAL)
+
+add_library(PackName1 INTERFACE IMPORTED)
+add_executable(PackNameExe1 IMPORTED)
diff --git a/Tests/RunCMake/find_package/PackageRoot/SimpleConfig.cmake b/Tests/RunCMake/find_package/PackageRoot/SimpleConfig.cmake
new file mode 100644
index 0000000..44059c6
--- /dev/null
+++ b/Tests/RunCMake/find_package/PackageRoot/SimpleConfig.cmake
@@ -0,0 +1,3 @@
+include(CMakeFindDependencyMacro)
+
+find_dependency(LT PATHS ${CMAKE_CURRENT_LIST_DIR})
diff --git a/Tests/RunCMake/find_package/RunCMakeTest.cmake b/Tests/RunCMake/find_package/RunCMakeTest.cmake
index 5f4c6cb..2b5fb1f 100644
--- a/Tests/RunCMake/find_package/RunCMakeTest.cmake
+++ b/Tests/RunCMake/find_package/RunCMakeTest.cmake
@@ -6,6 +6,7 @@
 run_cmake(FromPATHEnv)
 run_cmake_with_options(FromPATHEnvDebugPkg --debug-find-pkg=Resolved)
 run_cmake(FromPrefixPath)
+run_cmake(GlobalImportTarget)
 run_cmake(MissingNormal)
 run_cmake(MissingNormalForceRequired)
 run_cmake(MissingNormalRequired)