瀏覽代碼

add_library/add_executable: allow local alias to imported targets

Fixes: #20641
Marc Chevrier 5 年之前
父節點
當前提交
056489d567
共有 27 個文件被更改,包括 310 次插入65 次删除
  1. 7 2
      Help/command/add_executable.rst
  2. 7 2
      Help/command/add_library.rst
  3. 1 0
      Help/manual/cmake-properties.7.rst
  4. 17 0
      Help/prop_tgt/ALIAS_GLOBAL.rst
  5. 12 4
      Help/prop_tgt/IMPORTED_GLOBAL.rst
  6. 6 0
      Help/release/dev/alias-local-imported-target.rst
  7. 3 8
      Source/cmAddExecutableCommand.cxx
  8. 3 8
      Source/cmAddLibraryCommand.cxx
  9. 8 0
      Source/cmGeneratorExpressionNode.cxx
  10. 13 3
      Source/cmGetPropertyCommand.cxx
  11. 10 2
      Source/cmGetTargetPropertyCommand.cxx
  12. 18 7
      Source/cmLocalGenerator.cxx
  13. 14 3
      Source/cmMakefile.cxx
  14. 2 1
      Source/cmMakefile.h
  15. 1 0
      Tests/RunCMake/GeneratorExpression/RunCMakeTest.cmake
  16. 6 0
      Tests/RunCMake/GeneratorExpression/TARGET_PROPERTY-ALIAS_GLOBAL-check.cmake
  17. 16 0
      Tests/RunCMake/GeneratorExpression/TARGET_PROPERTY-ALIAS_GLOBAL.cmake
  18. 1 0
      Tests/RunCMake/alias_targets/RunCMakeTest.cmake
  19. 8 0
      Tests/RunCMake/alias_targets/get_property-subdir/CMakeLists.txt
  20. 59 0
      Tests/RunCMake/alias_targets/get_property.cmake
  21. 0 1
      Tests/RunCMake/alias_targets/imported-target-result.txt
  22. 2 15
      Tests/RunCMake/alias_targets/imported-target-stderr.txt
  23. 6 0
      Tests/RunCMake/alias_targets/imported-target-subdir1/CMakeLists.txt
  24. 20 0
      Tests/RunCMake/alias_targets/imported-target-subdir2/CMakeLists.txt
  25. 11 0
      Tests/RunCMake/alias_targets/imported-target.cmake
  26. 36 0
      Tests/RunCMake/target_link_libraries/AliasTargets.cmake
  27. 23 9
      Tests/RunCMake/target_link_libraries/RunCMakeTest.cmake

+ 7 - 2
Help/command/add_executable.rst

@@ -83,8 +83,13 @@ Alias Executables
 Creates an :ref:`Alias Target <Alias Targets>`, such that ``<name>`` can
 Creates an :ref:`Alias Target <Alias Targets>`, such that ``<name>`` can
 be used to refer to ``<target>`` in subsequent commands.  The ``<name>``
 be used to refer to ``<target>`` in subsequent commands.  The ``<name>``
 does not appear in the generated buildsystem as a make target.  The
 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
 ``ALIAS`` targets can be used as targets to read properties
 from, executables for custom commands and custom targets.  They can also be
 from, executables for custom commands and custom targets.  They can also be
 tested for existence with the regular :command:`if(TARGET)` subcommand.
 tested for existence with the regular :command:`if(TARGET)` subcommand.

+ 7 - 2
Help/command/add_library.rst

@@ -139,8 +139,13 @@ Alias Libraries
 Creates an :ref:`Alias Target <Alias Targets>`, such that ``<name>`` can be
 Creates an :ref:`Alias Target <Alias Targets>`, such that ``<name>`` can be
 used to refer to ``<target>`` in subsequent commands.  The ``<name>`` does
 used to refer to ``<target>`` in subsequent commands.  The ``<name>`` does
 not appear in the generated buildsystem as a make target.  The ``<target>``
 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
 ``ALIAS`` targets can be used as linkable targets and as targets to
 read properties from.  They can also be tested for existence with the
 read properties from.  They can also be tested for existence with the
 regular :command:`if(TARGET)` subcommand.  The ``<name>`` may not be used
 regular :command:`if(TARGET)` subcommand.  The ``<name>`` may not be used

+ 1 - 0
Help/manual/cmake-properties.7.rst

@@ -105,6 +105,7 @@ Properties on Targets
 
 
    /prop_tgt/ADDITIONAL_CLEAN_FILES
    /prop_tgt/ADDITIONAL_CLEAN_FILES
    /prop_tgt/AIX_EXPORT_ALL_SYMBOLS
    /prop_tgt/AIX_EXPORT_ALL_SYMBOLS
+   /prop_tgt/ALIAS_GLOBAL
    /prop_tgt/ALIASED_TARGET
    /prop_tgt/ALIASED_TARGET
    /prop_tgt/ANDROID_ANT_ADDITIONAL_OPTIONS
    /prop_tgt/ANDROID_ANT_ADDITIONAL_OPTIONS
    /prop_tgt/ANDROID_API
    /prop_tgt/ANDROID_API

+ 17 - 0
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.

+ 12 - 4
Help/prop_tgt/IMPORTED_GLOBAL.rst

@@ -16,7 +16,15 @@ property for such a locally ``IMPORTED`` target to True promotes that
 target to global scope. This promotion can only be done in the same
 target to global scope. This promotion can only be done in the same
 directory where that ``IMPORTED`` target was created in the first place.
 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).

+ 6 - 0
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>`.

+ 3 - 8
Source/cmAddExecutableCommand.cxx

@@ -117,14 +117,9 @@ bool cmAddExecutableCommand(std::vector<std::string> const& args,
                                "\" is not an executable."));
                                "\" is not an executable."));
       return false;
       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;
     return true;
   }
   }
 
 

+ 3 - 8
Source/cmAddLibraryCommand.cxx

@@ -219,14 +219,9 @@ bool cmAddLibraryCommand(std::vector<std::string> const& args,
                                "\" is not a library."));
                                "\" is not a library."));
       return false;
       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;
     return true;
   }
   }
 
 

+ 8 - 0
Source/cmGeneratorExpressionNode.cxx

@@ -1342,6 +1342,14 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
         }
         }
         return std::string();
         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);
       target = context->LG->FindGeneratorTargetToUse(targetName);
 
 
       if (!target) {
       if (!target) {

+ 13 - 3
Source/cmGetPropertyCommand.cxx

@@ -344,10 +344,20 @@ bool HandleTargetMode(cmExecutionStatus& status, const std::string& name,
   }
   }
 
 
   if (cmTarget* target = status.GetMakefile().FindTargetToUse(name)) {
   if (cmTarget* target = status.GetMakefile().FindTargetToUse(name)) {
-    if (propertyName == "ALIASED_TARGET") {
+    if (propertyName == "ALIASED_TARGET" || propertyName == "ALIAS_GLOBAL") {
       if (status.GetMakefile().IsAlias(name)) {
       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);
       return StoreResult(infoType, status.GetMakefile(), variable, nullptr);
     }
     }

+ 10 - 2
Source/cmGetTargetPropertyCommand.cxx

@@ -5,6 +5,7 @@
 #include <sstream>
 #include <sstream>
 
 
 #include "cmExecutionStatus.h"
 #include "cmExecutionStatus.h"
+#include "cmGlobalGenerator.h"
 #include "cmListFileCache.h"
 #include "cmListFileCache.h"
 #include "cmMakefile.h"
 #include "cmMakefile.h"
 #include "cmMessageType.h"
 #include "cmMessageType.h"
@@ -29,10 +30,17 @@ bool cmGetTargetPropertyCommand(std::vector<std::string> const& args,
   cmMakefile& mf = status.GetMakefile();
   cmMakefile& mf = status.GetMakefile();
 
 
   if (cmTarget* tgt = mf.FindTargetToUse(targetName)) {
   if (cmTarget* tgt = mf.FindTargetToUse(targetName)) {
-    if (args[2] == "ALIASED_TARGET") {
+    if (args[2] == "ALIASED_TARGET" || args[2] == "ALIAS_GLOBAL") {
       if (mf.IsAlias(targetName)) {
       if (mf.IsAlias(targetName)) {
-        prop = tgt->GetName();
         prop_exists = true;
         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()) {
     } else if (!args[2].empty()) {
       cmProp prop_cstr = nullptr;
       cmProp prop_cstr = nullptr;

+ 18 - 7
Source/cmLocalGenerator.cxx

@@ -2049,6 +2049,15 @@ cmGeneratorTarget* cmLocalGenerator::FindGeneratorTargetToUse(
     return imported->second;
     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)) {
   if (cmGeneratorTarget* t = this->FindLocalNonAliasGeneratorTarget(name)) {
     return t;
     return t;
   }
   }
@@ -2468,7 +2477,8 @@ bool cmLocalGenerator::GetShouldUseOldFlags(bool shared,
           std::ostringstream e;
           std::ostringstream e;
           e << "Variable " << flagsVar
           e << "Variable " << flagsVar
             << " has been modified. CMake "
             << " 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 "
                "shared libraries and will use the "
             << flagsVar
             << flagsVar
             << " variable "
             << " variable "
@@ -2565,7 +2575,8 @@ void cmLocalGenerator::AddPchDependencies(cmGeneratorTarget* target)
   }
   }
 
 
   for (std::string const& config : configsList) {
   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;
     std::vector<cmSourceFile*> sources;
     target->GetSourceFiles(sources, config);
     target->GetSourceFiles(sources, config);
 
 
@@ -3270,8 +3281,8 @@ const char* cmLocalGenerator::GetFeature(const std::string& feature,
                                          const std::string& config)
                                          const std::string& config)
 {
 {
   std::string featureName = feature;
   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()) {
   if (!config.empty()) {
     featureName += "_";
     featureName += "_";
     featureName += cmSystemTools::UpperCase(config);
     featureName += cmSystemTools::UpperCase(config);
@@ -4120,9 +4131,9 @@ void AddUtilityCommand(cmLocalGenerator& lg, const cmListFileBacktrace& lfbt,
   cmImplicitDependsList no_implicit_depends;
   cmImplicitDependsList no_implicit_depends;
   cmSourceFile* rule = AddCustomCommand(
   cmSourceFile* rule = AddCustomCommand(
     lg, lfbt, { force.Name }, byproducts, depends, no_main_dependency,
     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) {
   if (rule) {
     lg.GetMakefile()->AddTargetByproducts(target, byproducts);
     lg.GetMakefile()->AddTargetByproducts(target, byproducts);
   }
   }

+ 14 - 3
Source/cmMakefile.cxx

@@ -2035,10 +2035,13 @@ void cmMakefile::AddGlobalLinkInformation(cmTarget& target)
   }
   }
 }
 }
 
 
-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->AliasTargets[lname] = tgtName;
-  this->GetGlobalGenerator()->AddAlias(lname, tgtName);
+  if (globallyVisible) {
+    this->GetGlobalGenerator()->AddAlias(lname, tgtName);
+  }
 }
 }
 
 
 cmTarget* cmMakefile::AddLibrary(const std::string& lname,
 cmTarget* cmMakefile::AddLibrary(const std::string& lname,
@@ -4286,7 +4289,15 @@ cmTarget* cmMakefile::FindTargetToUse(const std::string& name,
 {
 {
   // Look for an imported target.  These take priority because they
   // Look for an imported target.  These take priority because they
   // are more local in scope and do not have to be globally unique.
   // 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()) {
   if (imported != this->ImportedTargets.end()) {
     return imported->second;
     return imported->second;
   }
   }

+ 2 - 1
Source/cmMakefile.h

@@ -356,7 +356,8 @@ public:
                        cmStateEnums::TargetType type,
                        cmStateEnums::TargetType type,
                        const std::vector<std::string>& srcs,
                        const std::vector<std::string>& srcs,
                        bool excludeFromAll = false);
                        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);
 
 
   //@{
   //@{
   /**
   /**

+ 1 - 0
Tests/RunCMake/GeneratorExpression/RunCMakeTest.cmake

@@ -111,6 +111,7 @@ run_cmake(TARGET_LINKER_FILE_BASE_NAME-non-valid-target)
 run_cmake(TARGET_PROPERTY-INCLUDE_DIRECTORIES)
 run_cmake(TARGET_PROPERTY-INCLUDE_DIRECTORIES)
 run_cmake(TARGET_PROPERTY-LOCATION)
 run_cmake(TARGET_PROPERTY-LOCATION)
 run_cmake(TARGET_PROPERTY-SOURCES)
 run_cmake(TARGET_PROPERTY-SOURCES)
+run_cmake(TARGET_PROPERTY-ALIAS_GLOBAL)
 run_cmake(LINK_ONLY-not-linking)
 run_cmake(LINK_ONLY-not-linking)
 run_cmake(TARGET_EXISTS-no-arg)
 run_cmake(TARGET_EXISTS-no-arg)
 run_cmake(TARGET_EXISTS-empty-arg)
 run_cmake(TARGET_EXISTS-empty-arg)

+ 6 - 0
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()

+ 16 - 0
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")

+ 1 - 0
Tests/RunCMake/alias_targets/RunCMakeTest.cmake

@@ -12,6 +12,7 @@ run_cmake(imported-global-target)
 run_cmake(imported-target)
 run_cmake(imported-target)
 run_cmake(alias-target)
 run_cmake(alias-target)
 run_cmake(set_property)
 run_cmake(set_property)
+run_cmake(get_property)
 run_cmake(set_target_properties)
 run_cmake(set_target_properties)
 run_cmake(target_link_libraries)
 run_cmake(target_link_libraries)
 run_cmake(target_include_directories)
 run_cmake(target_include_directories)

+ 8 - 0
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")

+ 59 - 0
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)

+ 0 - 1
Tests/RunCMake/alias_targets/imported-target-result.txt

@@ -1 +0,0 @@
-1

+ 2 - 15
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'.$

+ 6 - 0
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)

+ 20 - 0
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()

+ 11 - 0
Tests/RunCMake/alias_targets/imported-target.cmake

@@ -44,3 +44,14 @@ if(TARGET alias-test-lib)
 else()
 else()
     message("'alias-test-lib' does not exist!?")
     message("'alias-test-lib' does not exist!?")
 endif()
 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()

+ 36 - 0
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)

+ 23 - 9
Tests/RunCMake/target_link_libraries/RunCMakeTest.cmake

@@ -30,6 +30,29 @@ run_cmake(StaticPrivateDepNotExported)
 run_cmake(StaticPrivateDepNotTarget)
 run_cmake(StaticPrivateDepNotTarget)
 run_cmake(UNKNOWN-IMPORTED-GLOBAL)
 run_cmake(UNKNOWN-IMPORTED-GLOBAL)
 run_cmake(empty_keyword_args)
 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)
 run_cmake(genex_LINK_LANGUAGE-bad-usage)
 
 
 if (RunCMake_GENERATOR MATCHES "Makefiles|Ninja|Visual Studio|Xcode|Watcom WMake")
 if (RunCMake_GENERATOR MATCHES "Makefiles|Ninja|Visual Studio|Xcode|Watcom WMake")
@@ -37,15 +60,6 @@ if (RunCMake_GENERATOR MATCHES "Makefiles|Ninja|Visual Studio|Xcode|Watcom WMake
   run_cmake(genex_LINK_LANGUAGE-bad-mix-lang)
   run_cmake(genex_LINK_LANGUAGE-bad-mix-lang)
   run_cmake(genex_LINK_LANG_AND_ID-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)
   set(RunCMake_TEST_OUTPUT_MERGE TRUE)
   if (NOT RunCMake_GENERATOR_IS_MULTI_CONFIG)
   if (NOT RunCMake_GENERATOR_IS_MULTI_CONFIG)
     set(RunCMake_TEST_OPTIONS -DCMAKE_BUILD_TYPE=Release)
     set(RunCMake_TEST_OPTIONS -DCMAKE_BUILD_TYPE=Release)