Merge topic 'imported-local-target-alias'

056489d567 add_library/add_executable: allow local alias to imported targets
254f2b9058 Help: add_executable: Add TOC

Acked-by: Kitware Robot <kwrobot@kitware.com>
Merge-request: !4837
diff --git a/Help/command/add_executable.rst b/Help/command/add_executable.rst
index 0a7d7e1..e073228 100644
--- a/Help/command/add_executable.rst
+++ b/Help/command/add_executable.rst
@@ -1,8 +1,15 @@
 add_executable
 --------------
 
+.. only:: html
+
+  .. contents::
+
 Add an executable to the project using the specified source files.
 
+Normal Executables
+^^^^^^^^^^^^^^^^^^
+
 .. code-block:: cmake
 
   add_executable(<name> [WIN32] [MACOSX_BUNDLE]
@@ -45,7 +52,8 @@
 pre-processed, and you want to have the original sources reachable from
 within IDE.
 
---------------------------------------------------------------------------
+Imported Executables
+^^^^^^^^^^^^^^^^^^^^
 
 .. code-block:: cmake
 
@@ -65,7 +73,8 @@
 the main executable file on disk.  See documentation of the ``IMPORTED_*``
 properties for more information.
 
---------------------------------------------------------------------------
+Alias Executables
+^^^^^^^^^^^^^^^^^
 
 .. code-block:: cmake
 
@@ -74,8 +83,13 @@
 Creates an :ref:`Alias Target <Alias Targets>`, such that ``<name>`` can
 be used to refer to ``<target>`` in subsequent commands.  The ``<name>``
 does not appear in the generated buildsystem as a make target.  The
-``<target>`` may not be a non-``GLOBAL``
-:ref:`Imported Target <Imported Targets>` or an ``ALIAS``.
+``<target>`` may not be an ``ALIAS``.
+
+An ``ALIAS`` to a non-``GLOBAL`` :ref:`Imported Target <Imported Targets>`
+has scope in the directory in which the alias is created and below.
+The :prop_tgt:`ALIAS_GLOBAL` target property can be used to check if the
+alias is global or not.
+
 ``ALIAS`` targets can be used as targets to read properties
 from, executables for custom commands and custom targets.  They can also be
 tested for existence with the regular :command:`if(TARGET)` subcommand.
diff --git a/Help/command/add_library.rst b/Help/command/add_library.rst
index 7274e44..01c415a 100644
--- a/Help/command/add_library.rst
+++ b/Help/command/add_library.rst
@@ -139,8 +139,13 @@
 Creates an :ref:`Alias Target <Alias Targets>`, such that ``<name>`` can be
 used to refer to ``<target>`` in subsequent commands.  The ``<name>`` does
 not appear in the generated buildsystem as a make target.  The ``<target>``
-may not be a non-``GLOBAL`` :ref:`Imported Target <Imported Targets>` or an
-``ALIAS``.
+may not be an ``ALIAS``.
+
+An ``ALIAS`` to a non-``GLOBAL`` :ref:`Imported Target <Imported Targets>`
+has scope in the directory in which the alias is created and below.
+The :prop_tgt:`ALIAS_GLOBAL` target property can be used to check if the
+alias is global or not.
+
 ``ALIAS`` targets can be used as linkable targets and as targets to
 read properties from.  They can also be tested for existence with the
 regular :command:`if(TARGET)` subcommand.  The ``<name>`` may not be used
diff --git a/Help/manual/cmake-properties.7.rst b/Help/manual/cmake-properties.7.rst
index a68170a..7f7ed50 100644
--- a/Help/manual/cmake-properties.7.rst
+++ b/Help/manual/cmake-properties.7.rst
@@ -105,6 +105,7 @@
 
    /prop_tgt/ADDITIONAL_CLEAN_FILES
    /prop_tgt/AIX_EXPORT_ALL_SYMBOLS
+   /prop_tgt/ALIAS_GLOBAL
    /prop_tgt/ALIASED_TARGET
    /prop_tgt/ANDROID_ANT_ADDITIONAL_OPTIONS
    /prop_tgt/ANDROID_API
diff --git a/Help/prop_tgt/ALIAS_GLOBAL.rst b/Help/prop_tgt/ALIAS_GLOBAL.rst
new file mode 100644
index 0000000..8854f57
--- /dev/null
+++ b/Help/prop_tgt/ALIAS_GLOBAL.rst
@@ -0,0 +1,17 @@
+ALIAS_GLOBAL
+------------
+
+Read-only property indicating of whether an :ref:`ALIAS target <Alias Targets>`
+is globally visible.
+
+The boolean value of this property is ``TRUE`` for aliases to
+:ref:`IMPORTED targets <Imported Targets>` created
+with the ``GLOBAL`` options to :command:`add_executable()` or
+:command:`add_library()`, ``FALSE`` otherwise. It is undefined for
+targets built within the project.
+
+.. note::
+
+  Promoting an :ref:`IMPORTED target <Imported Targets>` from ``LOCAL``
+  to ``GLOBAL`` scope by changing the value or :prop_tgt:`IMPORTED_GLOBAL`
+  target property do not change the scope of local aliases.
diff --git a/Help/prop_tgt/IMPORTED_GLOBAL.rst b/Help/prop_tgt/IMPORTED_GLOBAL.rst
index 1feca04..1a9129f 100644
--- a/Help/prop_tgt/IMPORTED_GLOBAL.rst
+++ b/Help/prop_tgt/IMPORTED_GLOBAL.rst
@@ -16,7 +16,15 @@
 target to global scope. This promotion can only be done in the same
 directory where that ``IMPORTED`` target was created in the first place.
 
-Once an imported target has been made global, it cannot be changed back to
-non-global. Therefore, if a project sets this property, it may only
-provide a value of True. CMake will issue an error if the project tries to
-set the property to a non-True value, even if the value was already False.
+.. note::
+
+  Once an imported target has been made global, it cannot be changed back to
+  non-global. Therefore, if a project sets this property, it may only
+  provide a value of True. CMake will issue an error if the project tries to
+  set the property to a non-True value, even if the value was already False.
+
+.. note::
+
+  Local :ref:`ALIAS targets <Alias Targets>` created before promoting an
+  :ref:`IMPORTED target <Imported Targets>` from ``LOCAL`` to ``GLOBAL``, keep
+  their initial scope (see :prop_tgt:`ALIAS_GLOBAL` target property).
diff --git a/Help/release/dev/alias-local-imported-target.rst b/Help/release/dev/alias-local-imported-target.rst
new file mode 100644
index 0000000..026d793
--- /dev/null
+++ b/Help/release/dev/alias-local-imported-target.rst
@@ -0,0 +1,6 @@
+alias-local-imported-target
+---------------------------
+
+* :command:`add_library` and :command:`add_executable` gain the capability
+  to create an ``ALIAS`` to
+  non-``GLOBAL`` :ref:`Imported Target <Imported Targets>`.
diff --git a/Source/cmAddExecutableCommand.cxx b/Source/cmAddExecutableCommand.cxx
index e738bc4..9dd8a19 100644
--- a/Source/cmAddExecutableCommand.cxx
+++ b/Source/cmAddExecutableCommand.cxx
@@ -117,14 +117,9 @@
                                "\" is not an executable."));
       return false;
     }
-    if (aliasedTarget->IsImported() &&
-        !aliasedTarget->IsImportedGloballyVisible()) {
-      status.SetError(cmStrCat("cannot create ALIAS target \"", exename,
-                               "\" because target \"", aliasedName,
-                               "\" is imported but not globally visible."));
-      return false;
-    }
-    mf.AddAlias(exename, aliasedName);
+    mf.AddAlias(exename, aliasedName,
+                !aliasedTarget->IsImported() ||
+                  aliasedTarget->IsImportedGloballyVisible());
     return true;
   }
 
diff --git a/Source/cmAddLibraryCommand.cxx b/Source/cmAddLibraryCommand.cxx
index d79c04f..3e5d764 100644
--- a/Source/cmAddLibraryCommand.cxx
+++ b/Source/cmAddLibraryCommand.cxx
@@ -219,14 +219,9 @@
                                "\" is not a library."));
       return false;
     }
-    if (aliasedTarget->IsImported() &&
-        !aliasedTarget->IsImportedGloballyVisible()) {
-      status.SetError(cmStrCat("cannot create ALIAS target \"", libName,
-                               "\" because target \"", aliasedName,
-                               "\" is imported but not globally visible."));
-      return false;
-    }
-    mf.AddAlias(libName, aliasedName);
+    mf.AddAlias(libName, aliasedName,
+                !aliasedTarget->IsImported() ||
+                  aliasedTarget->IsImportedGloballyVisible());
     return true;
   }
 
diff --git a/Source/cmGeneratorExpressionNode.cxx b/Source/cmGeneratorExpressionNode.cxx
index 906df2b..e4fb67e 100644
--- a/Source/cmGeneratorExpressionNode.cxx
+++ b/Source/cmGeneratorExpressionNode.cxx
@@ -1342,6 +1342,14 @@
         }
         return std::string();
       }
+      if (propertyName == "ALIAS_GLOBAL"_s) {
+        if (context->LG->GetMakefile()->IsAlias(targetName)) {
+          return context->LG->GetGlobalGenerator()->IsAlias(targetName)
+            ? "TRUE"
+            : "FALSE";
+        }
+        return std::string();
+      }
       target = context->LG->FindGeneratorTargetToUse(targetName);
 
       if (!target) {
diff --git a/Source/cmGetPropertyCommand.cxx b/Source/cmGetPropertyCommand.cxx
index 851f426..cba7704 100644
--- a/Source/cmGetPropertyCommand.cxx
+++ b/Source/cmGetPropertyCommand.cxx
@@ -344,10 +344,20 @@
   }
 
   if (cmTarget* target = status.GetMakefile().FindTargetToUse(name)) {
-    if (propertyName == "ALIASED_TARGET") {
+    if (propertyName == "ALIASED_TARGET" || propertyName == "ALIAS_GLOBAL") {
       if (status.GetMakefile().IsAlias(name)) {
-        return StoreResult(infoType, status.GetMakefile(), variable,
-                           target->GetName().c_str());
+        if (propertyName == "ALIASED_TARGET") {
+
+          return StoreResult(infoType, status.GetMakefile(), variable,
+                             target->GetName().c_str());
+        }
+        if (propertyName == "ALIAS_GLOBAL") {
+          return StoreResult(
+            infoType, status.GetMakefile(), variable,
+            status.GetMakefile().GetGlobalGenerator()->IsAlias(name)
+              ? "TRUE"
+              : "FALSE");
+        }
       }
       return StoreResult(infoType, status.GetMakefile(), variable, nullptr);
     }
diff --git a/Source/cmGetTargetPropertyCommand.cxx b/Source/cmGetTargetPropertyCommand.cxx
index e5a3669..8a304be 100644
--- a/Source/cmGetTargetPropertyCommand.cxx
+++ b/Source/cmGetTargetPropertyCommand.cxx
@@ -5,6 +5,7 @@
 #include <sstream>
 
 #include "cmExecutionStatus.h"
+#include "cmGlobalGenerator.h"
 #include "cmListFileCache.h"
 #include "cmMakefile.h"
 #include "cmMessageType.h"
@@ -29,10 +30,17 @@
   cmMakefile& mf = status.GetMakefile();
 
   if (cmTarget* tgt = mf.FindTargetToUse(targetName)) {
-    if (args[2] == "ALIASED_TARGET") {
+    if (args[2] == "ALIASED_TARGET" || args[2] == "ALIAS_GLOBAL") {
       if (mf.IsAlias(targetName)) {
-        prop = tgt->GetName();
         prop_exists = true;
+        if (args[2] == "ALIASED_TARGET") {
+
+          prop = tgt->GetName();
+        }
+        if (args[2] == "ALIAS_GLOBAL") {
+          prop =
+            mf.GetGlobalGenerator()->IsAlias(targetName) ? "TRUE" : "FALSE";
+        }
       }
     } else if (!args[2].empty()) {
       cmProp prop_cstr = nullptr;
diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx
index 3fca2d4..f299202 100644
--- a/Source/cmLocalGenerator.cxx
+++ b/Source/cmLocalGenerator.cxx
@@ -2049,6 +2049,15 @@
     return imported->second;
   }
 
+  // find local alias to imported target
+  auto aliased = this->AliasTargets.find(name);
+  if (aliased != this->AliasTargets.end()) {
+    imported = this->ImportedGeneratorTargets.find(aliased->second);
+    if (imported != this->ImportedGeneratorTargets.end()) {
+      return imported->second;
+    }
+  }
+
   if (cmGeneratorTarget* t = this->FindLocalNonAliasGeneratorTarget(name)) {
     return t;
   }
@@ -2468,7 +2477,8 @@
           std::ostringstream e;
           e << "Variable " << flagsVar
             << " has been modified. CMake "
-               "will ignore the POSITION_INDEPENDENT_CODE target property for "
+               "will ignore the POSITION_INDEPENDENT_CODE target property "
+               "for "
                "shared libraries and will use the "
             << flagsVar
             << " variable "
@@ -2565,7 +2575,8 @@
   }
 
   for (std::string const& config : configsList) {
-    // FIXME: Refactor collection of sources to not evaluate object libraries.
+    // FIXME: Refactor collection of sources to not evaluate object
+    // libraries.
     std::vector<cmSourceFile*> sources;
     target->GetSourceFiles(sources, config);
 
@@ -3270,8 +3281,8 @@
                                          const std::string& config)
 {
   std::string featureName = feature;
-  // TODO: Define accumulation policy for features (prepend, append, replace).
-  // Currently we always replace.
+  // TODO: Define accumulation policy for features (prepend, append,
+  // replace). Currently we always replace.
   if (!config.empty()) {
     featureName += "_";
     featureName += cmSystemTools::UpperCase(config);
@@ -4120,9 +4131,9 @@
   cmImplicitDependsList no_implicit_depends;
   cmSourceFile* rule = AddCustomCommand(
     lg, lfbt, { force.Name }, byproducts, depends, no_main_dependency,
-    no_implicit_depends, commandLines, comment, workingDir, /*replace=*/false,
-    escapeOldStyle, uses_terminal, command_expand_lists, /*depfile=*/"",
-    job_pool, stdPipesUTF8);
+    no_implicit_depends, commandLines, comment, workingDir,
+    /*replace=*/false, escapeOldStyle, uses_terminal, command_expand_lists,
+    /*depfile=*/"", job_pool, stdPipesUTF8);
   if (rule) {
     lg.GetMakefile()->AddTargetByproducts(target, byproducts);
   }
diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx
index c527a49..c78b751 100644
--- a/Source/cmMakefile.cxx
+++ b/Source/cmMakefile.cxx
@@ -2035,10 +2035,13 @@
   }
 }
 
-void cmMakefile::AddAlias(const std::string& lname, std::string const& tgtName)
+void cmMakefile::AddAlias(const std::string& lname, std::string const& tgtName,
+                          bool globallyVisible)
 {
   this->AliasTargets[lname] = tgtName;
-  this->GetGlobalGenerator()->AddAlias(lname, tgtName);
+  if (globallyVisible) {
+    this->GetGlobalGenerator()->AddAlias(lname, tgtName);
+  }
 }
 
 cmTarget* cmMakefile::AddLibrary(const std::string& lname,
@@ -4286,7 +4289,15 @@
 {
   // Look for an imported target.  These take priority because they
   // are more local in scope and do not have to be globally unique.
-  auto imported = this->ImportedTargets.find(name);
+  auto targetName = name;
+  if (!excludeAliases) {
+    // Look for local alias targets.
+    auto alias = this->AliasTargets.find(name);
+    if (alias != this->AliasTargets.end()) {
+      targetName = alias->second;
+    }
+  }
+  auto imported = this->ImportedTargets.find(targetName);
   if (imported != this->ImportedTargets.end()) {
     return imported->second;
   }
diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h
index 8dfa5b0..45d7109 100644
--- a/Source/cmMakefile.h
+++ b/Source/cmMakefile.h
@@ -356,7 +356,8 @@
                        cmStateEnums::TargetType type,
                        const std::vector<std::string>& srcs,
                        bool excludeFromAll = false);
-  void AddAlias(const std::string& libname, const std::string& tgt);
+  void AddAlias(const std::string& libname, const std::string& tgt,
+                bool globallyVisible = true);
 
   //@{
   /**
diff --git a/Tests/RunCMake/GeneratorExpression/RunCMakeTest.cmake b/Tests/RunCMake/GeneratorExpression/RunCMakeTest.cmake
index 24c3642..7d3c22b 100644
--- a/Tests/RunCMake/GeneratorExpression/RunCMakeTest.cmake
+++ b/Tests/RunCMake/GeneratorExpression/RunCMakeTest.cmake
@@ -111,6 +111,7 @@
 run_cmake(TARGET_PROPERTY-INCLUDE_DIRECTORIES)
 run_cmake(TARGET_PROPERTY-LOCATION)
 run_cmake(TARGET_PROPERTY-SOURCES)
+run_cmake(TARGET_PROPERTY-ALIAS_GLOBAL)
 run_cmake(LINK_ONLY-not-linking)
 run_cmake(TARGET_EXISTS-no-arg)
 run_cmake(TARGET_EXISTS-empty-arg)
diff --git a/Tests/RunCMake/GeneratorExpression/TARGET_PROPERTY-ALIAS_GLOBAL-check.cmake b/Tests/RunCMake/GeneratorExpression/TARGET_PROPERTY-ALIAS_GLOBAL-check.cmake
new file mode 100644
index 0000000..0fbf837
--- /dev/null
+++ b/Tests/RunCMake/GeneratorExpression/TARGET_PROPERTY-ALIAS_GLOBAL-check.cmake
@@ -0,0 +1,6 @@
+file(STRINGS ${RunCMake_TEST_BINARY_DIR}/alias_global.txt alias_global)
+
+set(expected "TRUE(lib-global):TRUE;FALSE(lib-local):FALSE;TRUE(lib):FALSE")
+if(NOT alias_global STREQUAL expected)
+  set(RunCMake_TEST_FAILED "ALIAS_GLOBAL was:\n [[${alias_global}]]\nbut expected:\n [[${expected}]]")
+endif()
diff --git a/Tests/RunCMake/GeneratorExpression/TARGET_PROPERTY-ALIAS_GLOBAL.cmake b/Tests/RunCMake/GeneratorExpression/TARGET_PROPERTY-ALIAS_GLOBAL.cmake
new file mode 100644
index 0000000..212c034
--- /dev/null
+++ b/Tests/RunCMake/GeneratorExpression/TARGET_PROPERTY-ALIAS_GLOBAL.cmake
@@ -0,0 +1,16 @@
+
+cmake_minimum_required(VERSION 3.17)
+
+add_library(lib-global SHARED IMPORTED GLOBAL)
+add_library(alias-lib-global ALIAS lib-global)
+
+add_library(lib-local SHARED IMPORTED)
+add_library(alias-lib-local ALIAS lib-local)
+
+add_library(lib SHARED IMPORTED)
+add_library(alias-lib ALIAS lib)
+# switch from local to global
+set_property (TARGET lib PROPERTY IMPORTED_GLOBAL TRUE)
+
+
+file(GENERATE OUTPUT alias_global.txt CONTENT "$<TARGET_PROPERTY:lib-global,IMPORTED_GLOBAL>($<TARGET_PROPERTY:alias-lib-global,ALIASED_TARGET>):$<TARGET_PROPERTY:alias-lib-global,ALIAS_GLOBAL>\n$<TARGET_PROPERTY:lib-local,IMPORTED_GLOBAL>($<TARGET_PROPERTY:alias-lib-local,ALIASED_TARGET>):$<TARGET_PROPERTY:alias-lib-local,ALIAS_GLOBAL>\n$<TARGET_PROPERTY:lib,IMPORTED_GLOBAL>($<TARGET_PROPERTY:alias-lib,ALIASED_TARGET>):$<TARGET_PROPERTY:alias-lib,ALIAS_GLOBAL>\n")
diff --git a/Tests/RunCMake/alias_targets/RunCMakeTest.cmake b/Tests/RunCMake/alias_targets/RunCMakeTest.cmake
index 676de08..4be1b9d 100644
--- a/Tests/RunCMake/alias_targets/RunCMakeTest.cmake
+++ b/Tests/RunCMake/alias_targets/RunCMakeTest.cmake
@@ -12,6 +12,7 @@
 run_cmake(imported-target)
 run_cmake(alias-target)
 run_cmake(set_property)
+run_cmake(get_property)
 run_cmake(set_target_properties)
 run_cmake(target_link_libraries)
 run_cmake(target_include_directories)
diff --git a/Tests/RunCMake/alias_targets/get_property-subdir/CMakeLists.txt b/Tests/RunCMake/alias_targets/get_property-subdir/CMakeLists.txt
new file mode 100644
index 0000000..bfd9840
--- /dev/null
+++ b/Tests/RunCMake/alias_targets/get_property-subdir/CMakeLists.txt
@@ -0,0 +1,8 @@
+
+
+add_library(alias::import-local-subdir ALIAS import-local)
+
+check_property (alias::import-local-subdir ALIASED_TARGET "import-local")
+check_property (alias::import-local-subdir IMPORTED "TRUE")
+check_property (alias::import-local-subdir ALIAS_GLOBAL "FALSE")
+check_property (alias::import-local-subdir IMPORT_LOCAL_PROPERTY "IMPORT_LOCAL")
diff --git a/Tests/RunCMake/alias_targets/get_property.cmake b/Tests/RunCMake/alias_targets/get_property.cmake
new file mode 100644
index 0000000..8a01c6f
--- /dev/null
+++ b/Tests/RunCMake/alias_targets/get_property.cmake
@@ -0,0 +1,59 @@
+
+enable_language(CXX)
+
+function (check_property alias property value)
+  get_property (data TARGET ${alias} PROPERTY ${property})
+  if (NOT "${value}" STREQUAL "${data}")
+    message (SEND_ERROR "get_property(): Target property '${property}' from ALIAS '${alias}' has wrong value: '${data}' instead of '${value}'.")
+  endif()
+  get_target_property (data ${alias} ${property})
+  if (NOT "${value}" STREQUAL "${data}")
+    message (SEND_ERROR "get_target_property(): Target property '${property}' from ALIAS '${alias}' has wrong value: '${data}' instead of '${value}'.")
+  endif()
+endfunction()
+
+
+add_library(lib empty.cpp)
+set_property (TARGET lib PROPERTY LIB_PROPERTY "LIB")
+
+add_library(alias::lib ALIAS lib)
+
+check_property (alias::lib ALIASED_TARGET "lib")
+check_property (alias::lib IMPORTED "FALSE")
+check_property (alias::lib ALIAS_GLOBAL "TRUE")
+check_property (alias::lib LIB_PROPERTY "LIB")
+
+
+add_library(import-global SHARED IMPORTED GLOBAL)
+set_property (TARGET import-global PROPERTY IMPORT_GLOBAL_PROPERTY "IMPORT_GLOBAL")
+
+add_library(alias::import-global ALIAS import-global)
+
+check_property (alias::import-global ALIASED_TARGET "import-global")
+check_property (alias::import-global IMPORTED "TRUE")
+check_property (alias::import-global ALIAS_GLOBAL "TRUE")
+check_property (alias::import-global IMPORT_GLOBAL_PROPERTY "IMPORT_GLOBAL")
+
+
+add_library(import-local SHARED IMPORTED)
+set_property (TARGET import-local PROPERTY IMPORT_LOCAL_PROPERTY "IMPORT_LOCAL")
+
+add_library(alias::import-local ALIAS import-local)
+
+check_property (alias::import-local ALIASED_TARGET "import-local")
+check_property (alias::import-local IMPORTED "TRUE")
+check_property (alias::import-local ALIAS_GLOBAL "FALSE")
+check_property (alias::import-local IMPORT_LOCAL_PROPERTY "IMPORT_LOCAL")
+
+
+## upgrade imported target from local to global, alias stay local
+add_library(import-lib SHARED IMPORTED)
+add_library(alias::import-lib ALIAS import-lib)
+check_property (alias::import-lib IMPORTED_GLOBAL "FALSE")
+check_property (alias::import-lib ALIAS_GLOBAL "FALSE")
+set_property (TARGET import-lib PROPERTY IMPORTED_GLOBAL "TRUE")
+check_property (alias::import-lib IMPORTED_GLOBAL "TRUE")
+check_property (alias::import-lib ALIAS_GLOBAL "FALSE")
+
+
+add_subdirectory (get_property-subdir)
diff --git a/Tests/RunCMake/alias_targets/imported-target-result.txt b/Tests/RunCMake/alias_targets/imported-target-result.txt
deleted file mode 100644
index d00491f..0000000
--- a/Tests/RunCMake/alias_targets/imported-target-result.txt
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/Tests/RunCMake/alias_targets/imported-target-stderr.txt b/Tests/RunCMake/alias_targets/imported-target-stderr.txt
index 465de03..8259c80 100644
--- a/Tests/RunCMake/alias_targets/imported-target-stderr.txt
+++ b/Tests/RunCMake/alias_targets/imported-target-stderr.txt
@@ -1,15 +1,2 @@
-^CMake Error at imported-target.cmake:[0-9]+ \(add_executable\):
-  add_executable cannot create ALIAS target \"alias-test-exe\" because target
-  \"test-exe\" is imported but not globally visible.
-Call Stack \(most recent call first\):
-  CMakeLists.txt:[0-9]+ \(include\)
-+
-'alias-test-exe' does not exist![?]
-*
-CMake Error at imported-target.cmake:[0-9]+ \(add_library\):
-  add_library cannot create ALIAS target "alias-test-lib" because target
-  "test-lib" is imported but not globally visible.
-Call Stack \(most recent call first\):
-  CMakeLists.txt:[0-9]+ \(include\)
-+
-'alias-test-lib' does not exist![?]$
+^'alias-test-exe' is an alias for 'test-exe' and its name-property contains 'test-exe'.
+'alias-test-lib' is an alias for 'test-lib' and its name-property contains 'test-lib'.$
diff --git a/Tests/RunCMake/alias_targets/imported-target-subdir1/CMakeLists.txt b/Tests/RunCMake/alias_targets/imported-target-subdir1/CMakeLists.txt
new file mode 100644
index 0000000..bec05b3
--- /dev/null
+++ b/Tests/RunCMake/alias_targets/imported-target-subdir1/CMakeLists.txt
@@ -0,0 +1,6 @@
+
+add_executable(alias-test-exe-subdir1 ALIAS test-exe)
+add_executable(alias-test-exe-local ALIAS test-exe)
+
+add_library(alias-test-lib-subdir1 ALIAS test-lib)
+add_library(alias-test-lib-local ALIAS test-lib)
diff --git a/Tests/RunCMake/alias_targets/imported-target-subdir2/CMakeLists.txt b/Tests/RunCMake/alias_targets/imported-target-subdir2/CMakeLists.txt
new file mode 100644
index 0000000..23c85ba
--- /dev/null
+++ b/Tests/RunCMake/alias_targets/imported-target-subdir2/CMakeLists.txt
@@ -0,0 +1,20 @@
+
+add_executable(alias-test-exe-subdir2 ALIAS test-exe)
+add_executable(alias-test-exe-local ALIAS test-exe)
+
+add_library(alias-test-lib-subdir2 ALIAS test-lib)
+add_library(alias-test-lib-local ALIAS test-lib)
+
+
+foreach (item IN ITEMS exe lib)
+  get_property (aliasedTarget TARGET alias-test-${item}-local PROPERTY ALIASED_TARGET)
+  if (NOT aliasedTarget STREQUAL "test-${item}")
+    message (SEND_ERROR "Wrong aliased target '${aliasedTarget}' for ALIAS 'alias-test-${item}-local'.")
+  endif()
+endforeach()
+
+foreach (item IN ITEMS exe lib)
+  if (TARGET alias-test-${item}-subdir1)
+    message (SEND_ERROR "ALIAS 'alias-test-${item}-subdir1' unexpectedly defined.")
+  endif()
+endforeach()
diff --git a/Tests/RunCMake/alias_targets/imported-target.cmake b/Tests/RunCMake/alias_targets/imported-target.cmake
index bb682fe..fa6f8d3 100644
--- a/Tests/RunCMake/alias_targets/imported-target.cmake
+++ b/Tests/RunCMake/alias_targets/imported-target.cmake
@@ -44,3 +44,14 @@
 else()
     message("'alias-test-lib' does not exist!?")
 endif()
+
+add_subdirectory (imported-target-subdir1)
+add_subdirectory (imported-target-subdir2)
+
+foreach (alias IN ITEMS exe-local lib-local
+                        exe-subdir1 lib-subdir1
+                        exe-subdir2 lib-subdir2)
+  if (TARGET alias-test-${alias})
+    message (SEND_ERROR "ALIAS 'alias-test-${alias}' unexpectedly defined.")
+  endif()
+endforeach()
diff --git a/Tests/RunCMake/target_link_libraries/AliasTargets.cmake b/Tests/RunCMake/target_link_libraries/AliasTargets.cmake
new file mode 100644
index 0000000..73f8a7d
--- /dev/null
+++ b/Tests/RunCMake/target_link_libraries/AliasTargets.cmake
@@ -0,0 +1,36 @@
+
+cmake_minimum_required(VERSION 3.16...3.17)
+
+enable_language(C)
+
+add_library (func SHARED func.c)
+
+set (binary_dir "${CMAKE_BINARY_DIR}")
+get_property (is_multi_config GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
+if (is_multi_config)
+  string (APPEND binary_dir "/Release")
+endif()
+
+
+add_library(import-local SHARED IMPORTED)
+set_property(TARGET import-local PROPERTY IMPORTED_LOCATION "${binary_dir}/${CMAKE_STATIC_LIBRARY_PREFIX}func${CMAKE_SHARED_LIBRARY_SUFFIX}")
+set_property(TARGET import-local PROPERTY IMPORTED_IMPLIB "${binary_dir}/${CMAKE_STATIC_LIBRARY_PREFIX}func${CMAKE_IMPORT_LIBRARY_SUFFIX}")
+add_library(alias-local ALIAS import-local)
+
+add_library (lib-local SHARED lib.c)
+target_link_libraries (lib-local PRIVATE import-local)
+
+add_executable (main-local main.c)
+target_link_libraries (main-local PRIVATE import-local)
+
+
+add_library(import-global SHARED IMPORTED GLOBAL)
+set_property(TARGET import-global PROPERTY IMPORTED_LOCATION "${binary_dir}/${CMAKE_STATIC_LIBRARY_PREFIX}func${CMAKE_SHARED_LIBRARY_SUFFIX}")
+set_property(TARGET import-global PROPERTY IMPORTED_IMPLIB "${binary_dir}/${CMAKE_STATIC_LIBRARY_PREFIX}func${CMAKE_IMPORT_LIBRARY_SUFFIX}")
+add_library(alias-global ALIAS import-global)
+
+add_library (lib-global SHARED lib.c)
+target_link_libraries (lib-global PRIVATE import-global)
+
+add_executable (main-global main.c)
+target_link_libraries (main-global PRIVATE import-global)
diff --git a/Tests/RunCMake/target_link_libraries/RunCMakeTest.cmake b/Tests/RunCMake/target_link_libraries/RunCMakeTest.cmake
index dfa71dd..1f4077c 100644
--- a/Tests/RunCMake/target_link_libraries/RunCMakeTest.cmake
+++ b/Tests/RunCMake/target_link_libraries/RunCMakeTest.cmake
@@ -30,6 +30,29 @@
 run_cmake(StaticPrivateDepNotTarget)
 run_cmake(UNKNOWN-IMPORTED-GLOBAL)
 run_cmake(empty_keyword_args)
+
+macro(run_cmake_target test subtest target)
+  set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${test}-build)
+  set(RunCMake_TEST_NO_CLEAN 1)
+  run_cmake_command(${test}-${subtest} ${CMAKE_COMMAND} --build . --target ${target} ${ARGN})
+
+  unset(RunCMake_TEST_BINARY_DIR)
+  unset(RunCMake_TEST_NO_CLEAN)
+endmacro()
+
+set(RunCMake_TEST_OUTPUT_MERGE TRUE)
+if (NOT RunCMake_GENERATOR_IS_MULTI_CONFIG)
+  set(RunCMake_TEST_OPTIONS -DCMAKE_BUILD_TYPE=Release)
+endif()
+run_cmake(AliasTargets)
+run_cmake_target(AliasTargets func func --config Release)
+run_cmake_target(AliasTargets lib-local lib-local --config Release)
+run_cmake_target(AliasTargets main-local main-local --config Release)
+run_cmake_target(AliasTargets lib-global lib-global --config Release)
+run_cmake_target(AliasTargets main-global main-global --config Release)
+unset(RunCMake_TEST_OPTIONS)
+unset(RunCMake_TEST_OUTPUT_MERGE)
+
 run_cmake(genex_LINK_LANGUAGE-bad-usage)
 
 if (RunCMake_GENERATOR MATCHES "Makefiles|Ninja|Visual Studio|Xcode|Watcom WMake")
@@ -37,15 +60,6 @@
   run_cmake(genex_LINK_LANGUAGE-bad-mix-lang)
   run_cmake(genex_LINK_LANG_AND_ID-bad-mix-lang)
 
-  macro(run_cmake_target test subtest target)
-    set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${test}-build)
-    set(RunCMake_TEST_NO_CLEAN 1)
-    run_cmake_command(${test}-${subtest} ${CMAKE_COMMAND} --build . --target ${target} ${ARGN})
-
-    unset(RunCMake_TEST_BINARY_DIR)
-    unset(RunCMake_TEST_NO_CLEAN)
-  endmacro()
-
   set(RunCMake_TEST_OUTPUT_MERGE TRUE)
   if (NOT RunCMake_GENERATOR_IS_MULTI_CONFIG)
     set(RunCMake_TEST_OPTIONS -DCMAKE_BUILD_TYPE=Release)