Browse Source

Merge topic 'generalize-importedtargets-behavior'

fb88d2b5 Help: Add notes for topic 'generalize-importedtargets-behavior'
494906a8 Add support for IMPORTED GLOBAL targets to be aliased
fe4b25ec Teach target_* commands to set INTERFACE properties of IMPORTED targets
e40fd9fd cmTargetPropCommandBase: Fix typo in error message

Acked-by: Kitware Robot <[email protected]>
Acked-by: Henry Schreiner <[email protected]>
Merge-request: !1264
Brad King 8 years ago
parent
commit
8ffc1c3d89
40 changed files with 236 additions and 129 deletions
  1. 3 2
      Help/command/add_executable.rst
  2. 2 1
      Help/command/add_library.rst
  3. 4 3
      Help/command/target_compile_definitions.rst
  4. 5 4
      Help/command/target_compile_features.rst
  5. 7 4
      Help/command/target_compile_options.rst
  6. 4 4
      Help/command/target_include_directories.rst
  7. 2 1
      Help/command/target_link_libraries.rst
  8. 4 3
      Help/command/target_sources.rst
  9. 25 0
      Help/release/dev/generalize-importedtargets-behavior.rst
  10. 5 6
      Source/cmAddExecutableCommand.cxx
  11. 0 7
      Source/cmAddLibraryCommand.cxx
  12. 1 10
      Source/cmTargetCompileDefinitionsCommand.cxx
  13. 0 1
      Source/cmTargetCompileDefinitionsCommand.h
  14. 2 11
      Source/cmTargetCompileFeaturesCommand.cxx
  15. 0 1
      Source/cmTargetCompileFeaturesCommand.h
  16. 2 11
      Source/cmTargetCompileOptionsCommand.cxx
  17. 0 1
      Source/cmTargetCompileOptionsCommand.h
  18. 2 12
      Source/cmTargetIncludeDirectoriesCommand.cxx
  19. 0 1
      Source/cmTargetIncludeDirectoriesCommand.h
  20. 29 1
      Source/cmTargetLinkLibrariesCommand.cxx
  21. 6 9
      Source/cmTargetPropCommandBase.cxx
  22. 0 1
      Source/cmTargetPropCommandBase.h
  23. 1 8
      Source/cmTargetSourcesCommand.cxx
  24. 0 1
      Source/cmTargetSourcesCommand.h
  25. 0 5
      Tests/RunCMake/add_library/UNKNOWNwithNoSourcesButLinkObjects-stderr.txt
  26. 1 1
      Tests/RunCMake/add_library/UNKNOWNwithNoSourcesButLinkObjects.cmake
  27. 1 0
      Tests/RunCMake/alias_targets/RunCMakeTest.cmake
  28. 2 0
      Tests/RunCMake/alias_targets/imported-global-target-stderr.txt
  29. 46 0
      Tests/RunCMake/alias_targets/imported-global-target.cmake
  30. 8 4
      Tests/RunCMake/alias_targets/imported-target-stderr.txt
  31. 42 2
      Tests/RunCMake/alias_targets/imported-target.cmake
  32. 8 8
      Tests/RunCMake/interface_library/target_commands-stderr.txt
  33. 4 3
      Tests/RunCMake/target_compile_features/imported_target-stderr.txt
  34. 8 2
      Tests/RunCMake/target_compile_features/imported_target.cmake
  35. 1 1
      Tests/RunCMake/target_compile_features/invalid_args_on_interface-stderr.txt
  36. 2 0
      Tests/RunCMake/target_link_libraries/ImportedTarget.cmake
  37. 0 0
      Tests/RunCMake/target_link_libraries/ImportedTargetFailure-result.txt
  38. 5 0
      Tests/RunCMake/target_link_libraries/ImportedTargetFailure-stderr.txt
  39. 2 0
      Tests/RunCMake/target_link_libraries/ImportedTargetFailure.cmake
  40. 2 0
      Tests/RunCMake/target_link_libraries/RunCMakeTest.cmake

+ 3 - 2
Help/command/add_executable.rst

@@ -74,8 +74,9 @@ properties for more information.
 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 an :ref:`Imported Target <Imported Targets>` or an
-``ALIAS``.  ``ALIAS`` targets can be used as targets to read properties
+``<target>`` may not be a non-``GLOBAL``
+:ref:`Imported Target <Imported Targets>` or an ``ALIAS``.
+``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.
 The ``<name>`` may not be used to modify properties of ``<target>``, that
 The ``<name>`` may not be used to modify properties of ``<target>``, that

+ 2 - 1
Help/command/add_library.rst

@@ -125,7 +125,8 @@ 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 an :ref:`Imported Target <Imported Targets>` or an ``ALIAS``.
+may not be a non-``GLOBAL`` :ref:`Imported Target <Imported Targets>` or an
+``ALIAS``.
 ``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

+ 4 - 3
Help/command/target_compile_definitions.rst

@@ -12,14 +12,15 @@ Add compile definitions to a target.
 Specify compile definitions to use when compiling a given ``<target>``.  The
 Specify compile definitions to use when compiling a given ``<target>``.  The
 named ``<target>`` must have been created by a command such as
 named ``<target>`` must have been created by a command such as
 :command:`add_executable` or :command:`add_library` and must not be an
 :command:`add_executable` or :command:`add_library` and must not be an
-:ref:`Imported Target <Imported Targets>`.
+:ref:`ALIAS target <Alias Targets>`.
 
 
 The ``INTERFACE``, ``PUBLIC`` and ``PRIVATE`` keywords are required to
 The ``INTERFACE``, ``PUBLIC`` and ``PRIVATE`` keywords are required to
 specify the scope of the following arguments.  ``PRIVATE`` and ``PUBLIC``
 specify the scope of the following arguments.  ``PRIVATE`` and ``PUBLIC``
 items will populate the :prop_tgt:`COMPILE_DEFINITIONS` property of
 items will populate the :prop_tgt:`COMPILE_DEFINITIONS` property of
 ``<target>``. ``PUBLIC`` and ``INTERFACE`` items will populate the
 ``<target>``. ``PUBLIC`` and ``INTERFACE`` items will populate the
-:prop_tgt:`INTERFACE_COMPILE_DEFINITIONS` property of ``<target>``.  The
-following arguments specify compile definitions.  Repeated calls for the
+:prop_tgt:`INTERFACE_COMPILE_DEFINITIONS` property of ``<target>``.
+(:ref:`IMPORTED targets <Imported Targets>` only support ``INTERFACE`` items.)
+The following arguments specify compile definitions.  Repeated calls for the
 same ``<target>`` append items in the order called.
 same ``<target>`` append items in the order called.
 
 
 Arguments to ``target_compile_definitions`` may use "generator expressions"
 Arguments to ``target_compile_definitions`` may use "generator expressions"

+ 5 - 4
Help/command/target_compile_features.rst

@@ -18,12 +18,13 @@ The ``INTERFACE``, ``PUBLIC`` and ``PRIVATE`` keywords are required to
 specify the scope of the features.  ``PRIVATE`` and ``PUBLIC`` items will
 specify the scope of the features.  ``PRIVATE`` and ``PUBLIC`` items will
 populate the :prop_tgt:`COMPILE_FEATURES` property of ``<target>``.
 populate the :prop_tgt:`COMPILE_FEATURES` property of ``<target>``.
 ``PUBLIC`` and ``INTERFACE`` items will populate the
 ``PUBLIC`` and ``INTERFACE`` items will populate the
-:prop_tgt:`INTERFACE_COMPILE_FEATURES` property of ``<target>``.  Repeated
-calls for the same ``<target>`` append items.
+:prop_tgt:`INTERFACE_COMPILE_FEATURES` property of ``<target>``.
+(:ref:`IMPORTED targets <Imported Targets>` only support ``INTERFACE`` items.)
+Repeated calls for the same ``<target>`` append items.
 
 
 The named ``<target>`` must have been created by a command such as
 The named ``<target>`` must have been created by a command such as
-:command:`add_executable` or :command:`add_library` and must not be
-an ``IMPORTED`` target.
+:command:`add_executable` or :command:`add_library` and must not be an
+:ref:`ALIAS target <Alias Targets>`.
 
 
 Arguments to ``target_compile_features`` may use "generator expressions"
 Arguments to ``target_compile_features`` may use "generator expressions"
 with the syntax ``$<...>``.
 with the syntax ``$<...>``.

+ 7 - 4
Help/command/target_compile_options.rst

@@ -12,8 +12,10 @@ Add compile options to a target.
 Specify compile options to use when compiling a given target.  The
 Specify compile options to use when compiling a given target.  The
 named ``<target>`` must have been created by a command such as
 named ``<target>`` must have been created by a command such as
 :command:`add_executable` or :command:`add_library` and must not be an
 :command:`add_executable` or :command:`add_library` and must not be an
-:ref:`IMPORTED Target <Imported Targets>`.  If ``BEFORE`` is specified,
-the content will be prepended to the property instead of being appended.
+:ref:`ALIAS target <Alias Targets>`.
+
+If ``BEFORE`` is specified, the content will be prepended to the property
+instead of being appended.
 
 
 This command can be used to add any options, but
 This command can be used to add any options, but
 alternative commands exist to add preprocessor definitions
 alternative commands exist to add preprocessor definitions
@@ -27,8 +29,9 @@ The ``INTERFACE``, ``PUBLIC`` and ``PRIVATE`` keywords are required to
 specify the scope of the following arguments.  ``PRIVATE`` and ``PUBLIC``
 specify the scope of the following arguments.  ``PRIVATE`` and ``PUBLIC``
 items will populate the :prop_tgt:`COMPILE_OPTIONS` property of
 items will populate the :prop_tgt:`COMPILE_OPTIONS` property of
 ``<target>``.  ``PUBLIC`` and ``INTERFACE`` items will populate the
 ``<target>``.  ``PUBLIC`` and ``INTERFACE`` items will populate the
-:prop_tgt:`INTERFACE_COMPILE_OPTIONS` property of ``<target>``.  The
-following arguments specify compile options.  Repeated calls for the same
+:prop_tgt:`INTERFACE_COMPILE_OPTIONS` property of ``<target>``.
+(:ref:`IMPORTED targets <Imported Targets>` only support ``INTERFACE`` items.)
+The following arguments specify compile options.  Repeated calls for the same
 ``<target>`` append items in the order called.
 ``<target>`` append items in the order called.
 
 
 Arguments to ``target_compile_options`` may use "generator expressions"
 Arguments to ``target_compile_options`` may use "generator expressions"

+ 4 - 4
Help/command/target_include_directories.rst

@@ -12,7 +12,7 @@ Add include directories to a target.
 Specify include directories to use when compiling a given target.
 Specify include directories to use when compiling a given target.
 The named ``<target>`` must have been created by a command such
 The named ``<target>`` must have been created by a command such
 as :command:`add_executable` or :command:`add_library` and must not be an
 as :command:`add_executable` or :command:`add_library` and must not be an
-:prop_tgt:`IMPORTED` target.
+:ref:`ALIAS target <Alias Targets>`.
 
 
 If ``BEFORE`` is specified, the content will be prepended to the property
 If ``BEFORE`` is specified, the content will be prepended to the property
 instead of being appended.
 instead of being appended.
@@ -21,9 +21,9 @@ The ``INTERFACE``, ``PUBLIC`` and ``PRIVATE`` keywords are required to specify
 the scope of the following arguments.  ``PRIVATE`` and ``PUBLIC`` items will
 the scope of the following arguments.  ``PRIVATE`` and ``PUBLIC`` items will
 populate the :prop_tgt:`INCLUDE_DIRECTORIES` property of ``<target>``.
 populate the :prop_tgt:`INCLUDE_DIRECTORIES` property of ``<target>``.
 ``PUBLIC`` and ``INTERFACE`` items will populate the
 ``PUBLIC`` and ``INTERFACE`` items will populate the
-:prop_tgt:`INTERFACE_INCLUDE_DIRECTORIES`
-property of ``<target>``.  The following arguments specify include
-directories.
+:prop_tgt:`INTERFACE_INCLUDE_DIRECTORIES` property of ``<target>``.
+(:ref:`IMPORTED targets <Imported Targets>` only support ``INTERFACE`` items.)
+The following arguments specify include directories.
 
 
 Specified include directories may be absolute paths or relative paths.
 Specified include directories may be absolute paths or relative paths.
 Repeated calls for the same <target> append items in the order called.  If
 Repeated calls for the same <target> append items in the order called.  If

+ 2 - 1
Help/command/target_link_libraries.rst

@@ -19,7 +19,8 @@ All of them have the general form::
   target_link_libraries(<target> ... <item>... ...)
   target_link_libraries(<target> ... <item>... ...)
 
 
 The named ``<target>`` must have been created in the current directory by
 The named ``<target>`` must have been created in the current directory by
-a command such as :command:`add_executable` or :command:`add_library`.
+a command such as :command:`add_executable` or :command:`add_library` and
+must not be an :ref:`ALIAS target <Alias Targets>`.
 Repeated calls for the same ``<target>`` append items in the order called.
 Repeated calls for the same ``<target>`` append items in the order called.
 Each ``<item>`` may be:
 Each ``<item>`` may be:
 
 

+ 4 - 3
Help/command/target_sources.rst

@@ -12,14 +12,15 @@ Add sources to a target.
 Specify sources to use when compiling a given target.  The
 Specify sources to use when compiling a given target.  The
 named ``<target>`` must have been created by a command such as
 named ``<target>`` must have been created by a command such as
 :command:`add_executable` or :command:`add_library` and must not be an
 :command:`add_executable` or :command:`add_library` and must not be an
-:ref:`IMPORTED Target <Imported Targets>`.
+:ref:`ALIAS target <Alias Targets>`.
 
 
 The ``INTERFACE``, ``PUBLIC`` and ``PRIVATE`` keywords are required to
 The ``INTERFACE``, ``PUBLIC`` and ``PRIVATE`` keywords are required to
 specify the scope of the following arguments.  ``PRIVATE`` and ``PUBLIC``
 specify the scope of the following arguments.  ``PRIVATE`` and ``PUBLIC``
 items will populate the :prop_tgt:`SOURCES` property of
 items will populate the :prop_tgt:`SOURCES` property of
 ``<target>``.  ``PUBLIC`` and ``INTERFACE`` items will populate the
 ``<target>``.  ``PUBLIC`` and ``INTERFACE`` items will populate the
-:prop_tgt:`INTERFACE_SOURCES` property of ``<target>``.  The
-following arguments specify sources.  Repeated calls for the same
+:prop_tgt:`INTERFACE_SOURCES` property of ``<target>``.
+(:ref:`IMPORTED targets <Imported Targets>` only support ``INTERFACE`` items.)
+The following arguments specify sources.  Repeated calls for the same
 ``<target>`` append items in the order called.
 ``<target>`` append items in the order called.
 
 
 Arguments to ``target_sources`` may use "generator expressions"
 Arguments to ``target_sources`` may use "generator expressions"

+ 25 - 0
Help/release/dev/generalize-importedtargets-behavior.rst

@@ -0,0 +1,25 @@
+generalize-importedtargets-behavior
+-----------------------------------
+
+* The :command:`target_compile_definitions` command learned to set the
+  :prop_tgt:`INTERFACE_COMPILE_DEFINITIONS` property on
+  :ref:`Imported Targets`.
+
+* The :command:`target_compile_features` command learned to set the
+  :prop_tgt:`INTERFACE_COMPILE_FEATURES` property on :ref:`Imported Targets`.
+
+* The :command:`target_compile_options` command learned to set the
+  :prop_tgt:`INTERFACE_COMPILE_OPTIONS` property on :ref:`Imported Targets`.
+
+* The :command:`target_include_directories` command learned to set the
+  :prop_tgt:`INTERFACE_INCLUDE_DIRECTORIES` property on
+  :ref:`Imported Targets`.
+
+* The :command:`target_sources` command learned to set the
+  :prop_tgt:`INTERFACE_SOURCES` property on :ref:`Imported Targets`.
+
+* The :command:`target_link_libraries` command learned to set the
+  :prop_tgt:`INTERFACE_LINK_LIBRARIES` property on :ref:`Imported Targets`.
+
+* :ref:`Alias Targets` may now alias :ref:`Imported Targets` that are
+  created with the ``GLOBAL`` option to :command:`add_library`.

+ 5 - 6
Source/cmAddExecutableCommand.cxx

@@ -140,8 +140,7 @@ bool cmAddExecutableCommand::InitialPass(std::vector<std::string> const& args,
     if (!aliasedTarget) {
     if (!aliasedTarget) {
       std::ostringstream e;
       std::ostringstream e;
       e << "cannot create ALIAS target \"" << exename << "\" because target \""
       e << "cannot create ALIAS target \"" << exename << "\" because target \""
-        << aliasedName << "\" does not already "
-                          "exist.";
+        << aliasedName << "\" does not already exist.";
       this->SetError(e.str());
       this->SetError(e.str());
       return false;
       return false;
     }
     }
@@ -149,15 +148,15 @@ bool cmAddExecutableCommand::InitialPass(std::vector<std::string> const& args,
     if (type != cmStateEnums::EXECUTABLE) {
     if (type != cmStateEnums::EXECUTABLE) {
       std::ostringstream e;
       std::ostringstream e;
       e << "cannot create ALIAS target \"" << exename << "\" because target \""
       e << "cannot create ALIAS target \"" << exename << "\" because target \""
-        << aliasedName << "\" is not an "
-                          "executable.";
+        << aliasedName << "\" is not an executable.";
       this->SetError(e.str());
       this->SetError(e.str());
       return false;
       return false;
     }
     }
-    if (aliasedTarget->IsImported()) {
+    if (aliasedTarget->IsImported() &&
+        !aliasedTarget->IsImportedGloballyVisible()) {
       std::ostringstream e;
       std::ostringstream e;
       e << "cannot create ALIAS target \"" << exename << "\" because target \""
       e << "cannot create ALIAS target \"" << exename << "\" because target \""
-        << aliasedName << "\" is IMPORTED.";
+        << aliasedName << "\" is imported but not globally visible.";
       this->SetError(e.str());
       this->SetError(e.str());
       return false;
       return false;
     }
     }

+ 0 - 7
Source/cmAddLibraryCommand.cxx

@@ -256,13 +256,6 @@ bool cmAddLibraryCommand::InitialPass(std::vector<std::string> const& args,
       this->SetError(e.str());
       this->SetError(e.str());
       return false;
       return false;
     }
     }
-    if (aliasedTarget->IsImported()) {
-      std::ostringstream e;
-      e << "cannot create ALIAS target \"" << libName << "\" because target \""
-        << aliasedName << "\" is IMPORTED.";
-      this->SetError(e.str());
-      return false;
-    }
     this->Makefile->AddAlias(libName, aliasedName);
     this->Makefile->AddAlias(libName, aliasedName);
     return true;
     return true;
   }
   }

+ 1 - 10
Source/cmTargetCompileDefinitionsCommand.cxx

@@ -17,15 +17,6 @@ bool cmTargetCompileDefinitionsCommand::InitialPass(
   return this->HandleArguments(args, "COMPILE_DEFINITIONS");
   return this->HandleArguments(args, "COMPILE_DEFINITIONS");
 }
 }
 
 
-void cmTargetCompileDefinitionsCommand::HandleImportedTarget(
-  const std::string& tgt)
-{
-  std::ostringstream e;
-  e << "Cannot specify compile definitions for imported target \"" << tgt
-    << "\".";
-  this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
-}
-
 void cmTargetCompileDefinitionsCommand::HandleMissingTarget(
 void cmTargetCompileDefinitionsCommand::HandleMissingTarget(
   const std::string& name)
   const std::string& name)
 {
 {
@@ -56,5 +47,5 @@ bool cmTargetCompileDefinitionsCommand::HandleDirectContent(
   cmTarget* tgt, const std::vector<std::string>& content, bool, bool)
   cmTarget* tgt, const std::vector<std::string>& content, bool, bool)
 {
 {
   tgt->AppendProperty("COMPILE_DEFINITIONS", this->Join(content).c_str());
   tgt->AppendProperty("COMPILE_DEFINITIONS", this->Join(content).c_str());
-  return true;
+  return true; // Successfully handled.
 }
 }

+ 0 - 1
Source/cmTargetCompileDefinitionsCommand.h

@@ -30,7 +30,6 @@ public:
                    cmExecutionStatus& status) override;
                    cmExecutionStatus& status) override;
 
 
 private:
 private:
-  void HandleImportedTarget(const std::string& tgt) override;
   void HandleMissingTarget(const std::string& name) override;
   void HandleMissingTarget(const std::string& name) override;
 
 
   bool HandleDirectContent(cmTarget* tgt,
   bool HandleDirectContent(cmTarget* tgt,

+ 2 - 11
Source/cmTargetCompileFeaturesCommand.cxx

@@ -17,15 +17,6 @@ bool cmTargetCompileFeaturesCommand::InitialPass(
   return this->HandleArguments(args, "COMPILE_FEATURES", NO_FLAGS);
   return this->HandleArguments(args, "COMPILE_FEATURES", NO_FLAGS);
 }
 }
 
 
-void cmTargetCompileFeaturesCommand::HandleImportedTarget(
-  const std::string& tgt)
-{
-  std::ostringstream e;
-  e << "Cannot specify compile features for imported target \"" << tgt
-    << "\".";
-  this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
-}
-
 void cmTargetCompileFeaturesCommand::HandleMissingTarget(
 void cmTargetCompileFeaturesCommand::HandleMissingTarget(
   const std::string& name)
   const std::string& name)
 {
 {
@@ -49,8 +40,8 @@ bool cmTargetCompileFeaturesCommand::HandleDirectContent(
     std::string error;
     std::string error;
     if (!this->Makefile->AddRequiredTargetFeature(tgt, it, &error)) {
     if (!this->Makefile->AddRequiredTargetFeature(tgt, it, &error)) {
       this->SetError(error);
       this->SetError(error);
-      return false;
+      return false; // Not (successfully) handled.
     }
     }
   }
   }
-  return true;
+  return true; // Successfully handled.
 }
 }

+ 0 - 1
Source/cmTargetCompileFeaturesCommand.h

@@ -22,7 +22,6 @@ class cmTargetCompileFeaturesCommand : public cmTargetPropCommandBase
                    cmExecutionStatus& status) override;
                    cmExecutionStatus& status) override;
 
 
 private:
 private:
-  void HandleImportedTarget(const std::string& tgt) override;
   void HandleMissingTarget(const std::string& name) override;
   void HandleMissingTarget(const std::string& name) override;
 
 
   bool HandleDirectContent(cmTarget* tgt,
   bool HandleDirectContent(cmTarget* tgt,

+ 2 - 11
Source/cmTargetCompileOptionsCommand.cxx

@@ -18,21 +18,12 @@ bool cmTargetCompileOptionsCommand::InitialPass(
   return this->HandleArguments(args, "COMPILE_OPTIONS", PROCESS_BEFORE);
   return this->HandleArguments(args, "COMPILE_OPTIONS", PROCESS_BEFORE);
 }
 }
 
 
-void cmTargetCompileOptionsCommand::HandleImportedTarget(
-  const std::string& tgt)
-{
-  std::ostringstream e;
-  e << "Cannot specify compile options for imported target \"" << tgt << "\".";
-  this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
-}
-
 void cmTargetCompileOptionsCommand::HandleMissingTarget(
 void cmTargetCompileOptionsCommand::HandleMissingTarget(
   const std::string& name)
   const std::string& name)
 {
 {
   std::ostringstream e;
   std::ostringstream e;
   e << "Cannot specify compile options for target \"" << name
   e << "Cannot specify compile options for target \"" << name
-    << "\" "
-       "which is not built by this project.";
+    << "\" which is not built by this project.";
   this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
   this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
 }
 }
 
 
@@ -47,5 +38,5 @@ bool cmTargetCompileOptionsCommand::HandleDirectContent(
 {
 {
   cmListFileBacktrace lfbt = this->Makefile->GetBacktrace();
   cmListFileBacktrace lfbt = this->Makefile->GetBacktrace();
   tgt->InsertCompileOption(this->Join(content), lfbt);
   tgt->InsertCompileOption(this->Join(content), lfbt);
-  return true;
+  return true; // Successfully handled.
 }
 }

+ 0 - 1
Source/cmTargetCompileOptionsCommand.h

@@ -30,7 +30,6 @@ public:
                    cmExecutionStatus& status) override;
                    cmExecutionStatus& status) override;
 
 
 private:
 private:
-  void HandleImportedTarget(const std::string& tgt) override;
   void HandleMissingTarget(const std::string& name) override;
   void HandleMissingTarget(const std::string& name) override;
 
 
   bool HandleDirectContent(cmTarget* tgt,
   bool HandleDirectContent(cmTarget* tgt,

+ 2 - 12
Source/cmTargetIncludeDirectoriesCommand.cxx

@@ -21,22 +21,12 @@ bool cmTargetIncludeDirectoriesCommand::InitialPass(
                                ArgumentFlags(PROCESS_BEFORE | PROCESS_SYSTEM));
                                ArgumentFlags(PROCESS_BEFORE | PROCESS_SYSTEM));
 }
 }
 
 
-void cmTargetIncludeDirectoriesCommand::HandleImportedTarget(
-  const std::string& tgt)
-{
-  std::ostringstream e;
-  e << "Cannot specify include directories for imported target \"" << tgt
-    << "\".";
-  this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
-}
-
 void cmTargetIncludeDirectoriesCommand::HandleMissingTarget(
 void cmTargetIncludeDirectoriesCommand::HandleMissingTarget(
   const std::string& name)
   const std::string& name)
 {
 {
   std::ostringstream e;
   std::ostringstream e;
   e << "Cannot specify include directories for target \"" << name
   e << "Cannot specify include directories for target \"" << name
-    << "\" "
-       "which is not built by this project.";
+    << "\" which is not built by this project.";
   this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
   this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
 }
 }
 
 
@@ -79,7 +69,7 @@ bool cmTargetIncludeDirectoriesCommand::HandleDirectContent(
     }
     }
     tgt->AddSystemIncludeDirectories(sdirs);
     tgt->AddSystemIncludeDirectories(sdirs);
   }
   }
-  return true;
+  return true; // Successfully handled.
 }
 }
 
 
 void cmTargetIncludeDirectoriesCommand::HandleInterfaceContent(
 void cmTargetIncludeDirectoriesCommand::HandleInterfaceContent(

+ 0 - 1
Source/cmTargetIncludeDirectoriesCommand.h

@@ -30,7 +30,6 @@ public:
                    cmExecutionStatus& status) override;
                    cmExecutionStatus& status) override;
 
 
 private:
 private:
-  void HandleImportedTarget(const std::string& tgt) override;
   void HandleMissingTarget(const std::string& name) override;
   void HandleMissingTarget(const std::string& name) override;
 
 
   bool HandleDirectContent(cmTarget* tgt,
   bool HandleDirectContent(cmTarget* tgt,

+ 29 - 1
Source/cmTargetLinkLibrariesCommand.cxx

@@ -39,6 +39,16 @@ bool cmTargetLinkLibrariesCommand::InitialPass(
   this->Target =
   this->Target =
     this->Makefile->GetCMakeInstance()->GetGlobalGenerator()->FindTarget(
     this->Makefile->GetCMakeInstance()->GetGlobalGenerator()->FindTarget(
       args[0]);
       args[0]);
+  if (!this->Target) {
+    const std::vector<cmTarget*>& importedTargets =
+      this->Makefile->GetOwnedImportedTargets();
+    for (cmTarget* importedTarget : importedTargets) {
+      if (importedTarget->GetName() == args[0]) {
+        this->Target = importedTarget;
+        break;
+      }
+    }
+  }
   if (!this->Target) {
   if (!this->Target) {
     cmake::MessageType t = cmake::FATAL_ERROR; // fail by default
     cmake::MessageType t = cmake::FATAL_ERROR; // fail by default
     std::ostringstream e;
     std::ostringstream e;
@@ -228,7 +238,7 @@ bool cmTargetLinkLibrariesCommand::InitialPass(
     } else {
     } else {
       // Lookup old-style cache entry if type is unspecified.  So if you
       // Lookup old-style cache entry if type is unspecified.  So if you
       // do a target_link_libraries(foo optimized bar) it will stay optimized
       // do a target_link_libraries(foo optimized bar) it will stay optimized
-      // and not use the lookup.  As there maybe the case where someone has
+      // and not use the lookup.  As there may be the case where someone has
       // specifed that a library is both debug and optimized.  (this check is
       // specifed that a library is both debug and optimized.  (this check is
       // only there for backwards compatibility when mixing projects built
       // only there for backwards compatibility when mixing projects built
       // with old versions of CMake and new)
       // with old versions of CMake and new)
@@ -299,6 +309,14 @@ bool cmTargetLinkLibrariesCommand::HandleLibrary(const std::string& lib,
       "target_link_libraries");
       "target_link_libraries");
     return false;
     return false;
   }
   }
+  if (this->Target->IsImported() &&
+      this->CurrentProcessingState != ProcessingKeywordLinkInterface) {
+    this->Makefile->IssueMessage(
+      cmake::FATAL_ERROR,
+      "IMPORTED library can only be used with the INTERFACE keyword of "
+      "target_link_libraries");
+    return false;
+  }
 
 
   cmTarget::TLLSignature sig =
   cmTarget::TLLSignature sig =
     (this->CurrentProcessingState == ProcessingPlainPrivateInterface ||
     (this->CurrentProcessingState == ProcessingPlainPrivateInterface ||
@@ -354,6 +372,16 @@ bool cmTargetLinkLibrariesCommand::HandleLibrary(const std::string& lib,
 
 
     cmTarget* t =
     cmTarget* t =
       this->Makefile->FindLocalNonAliasTarget(this->Target->GetName());
       this->Makefile->FindLocalNonAliasTarget(this->Target->GetName());
+    if (!t) {
+      const std::vector<cmTarget*>& importedTargets =
+        this->Makefile->GetOwnedImportedTargets();
+      for (cmTarget* importedTarget : importedTargets) {
+        if (importedTarget->GetName() == this->Target->GetName()) {
+          t = importedTarget;
+          break;
+        }
+      }
+    }
     if (!t) {
     if (!t) {
       std::ostringstream e;
       std::ostringstream e;
       e << "Attempt to add link library \"" << lib << "\" to target \""
       e << "Attempt to add link library \"" << lib << "\" to target \""

+ 6 - 9
Source/cmTargetPropCommandBase.cxx

@@ -17,11 +17,11 @@ bool cmTargetPropCommandBase::HandleArguments(
     return false;
     return false;
   }
   }
 
 
-  // Lookup the target for which libraries are specified.
   if (this->Makefile->IsAlias(args[0])) {
   if (this->Makefile->IsAlias(args[0])) {
     this->SetError("can not be used on an ALIAS target.");
     this->SetError("can not be used on an ALIAS target.");
     return false;
     return false;
   }
   }
+  // Lookup the target for which property-values are specified.
   this->Target =
   this->Target =
     this->Makefile->GetCMakeInstance()->GetGlobalGenerator()->FindTarget(
     this->Makefile->GetCMakeInstance()->GetGlobalGenerator()->FindTarget(
       args[0]);
       args[0]);
@@ -84,16 +84,13 @@ bool cmTargetPropCommandBase::ProcessContentArgs(
     this->SetError("called with invalid arguments");
     this->SetError("called with invalid arguments");
     return false;
     return false;
   }
   }
-
-  if (this->Target->IsImported()) {
-    this->HandleImportedTarget(args[0]);
-    return false;
-  }
-
   if (this->Target->GetType() == cmStateEnums::INTERFACE_LIBRARY &&
   if (this->Target->GetType() == cmStateEnums::INTERFACE_LIBRARY &&
       scope != "INTERFACE") {
       scope != "INTERFACE") {
-    this->SetError("may only be set INTERFACE properties on INTERFACE "
-                   "targets");
+    this->SetError("may only set INTERFACE properties on INTERFACE targets");
+    return false;
+  }
+  if (this->Target->IsImported() && scope != "INTERFACE") {
+    this->SetError("may only set INTERFACE properties on IMPORTED targets");
     return false;
     return false;
   }
   }
 
 

+ 0 - 1
Source/cmTargetPropCommandBase.h

@@ -35,7 +35,6 @@ protected:
                                       bool prepend, bool system);
                                       bool prepend, bool system);
 
 
 private:
 private:
-  virtual void HandleImportedTarget(const std::string& tgt) = 0;
   virtual void HandleMissingTarget(const std::string& name) = 0;
   virtual void HandleMissingTarget(const std::string& name) = 0;
 
 
   virtual bool HandleDirectContent(cmTarget* tgt,
   virtual bool HandleDirectContent(cmTarget* tgt,

+ 1 - 8
Source/cmTargetSourcesCommand.cxx

@@ -17,13 +17,6 @@ bool cmTargetSourcesCommand::InitialPass(std::vector<std::string> const& args,
   return this->HandleArguments(args, "SOURCES");
   return this->HandleArguments(args, "SOURCES");
 }
 }
 
 
-void cmTargetSourcesCommand::HandleImportedTarget(const std::string& tgt)
-{
-  std::ostringstream e;
-  e << "Cannot specify sources for imported target \"" << tgt << "\".";
-  this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
-}
-
 void cmTargetSourcesCommand::HandleMissingTarget(const std::string& name)
 void cmTargetSourcesCommand::HandleMissingTarget(const std::string& name)
 {
 {
   std::ostringstream e;
   std::ostringstream e;
@@ -43,5 +36,5 @@ bool cmTargetSourcesCommand::HandleDirectContent(
   cmTarget* tgt, const std::vector<std::string>& content, bool, bool)
   cmTarget* tgt, const std::vector<std::string>& content, bool, bool)
 {
 {
   tgt->AppendProperty("SOURCES", this->Join(content).c_str());
   tgt->AppendProperty("SOURCES", this->Join(content).c_str());
-  return true;
+  return true; // Successfully handled.
 }
 }

+ 0 - 1
Source/cmTargetSourcesCommand.h

@@ -30,7 +30,6 @@ public:
                    cmExecutionStatus& status) override;
                    cmExecutionStatus& status) override;
 
 
 private:
 private:
-  void HandleImportedTarget(const std::string& tgt) override;
   void HandleMissingTarget(const std::string& name) override;
   void HandleMissingTarget(const std::string& name) override;
 
 
   bool HandleDirectContent(cmTarget* tgt,
   bool HandleDirectContent(cmTarget* tgt,

+ 0 - 5
Tests/RunCMake/add_library/UNKNOWNwithNoSourcesButLinkObjects-stderr.txt

@@ -1,5 +0,0 @@
-^CMake Error at UNKNOWNwithNoSourcesButLinkObjects.cmake:[0-9]+ \(target_link_libraries\):
-  Cannot specify link libraries for target \"TestUnknownLibWithoutSources\"
-  which is not built by this project.
-Call Stack \(most recent call first\):
-  CMakeLists.txt:[0-9]+ \(include\)$

+ 1 - 1
Tests/RunCMake/add_library/UNKNOWNwithNoSourcesButLinkObjects.cmake

@@ -2,4 +2,4 @@ enable_language(CXX)
 add_library(ObjectLibDependency OBJECT test.cpp)
 add_library(ObjectLibDependency OBJECT test.cpp)
 
 
 add_library(TestUnknownLibWithoutSources UNKNOWN IMPORTED)
 add_library(TestUnknownLibWithoutSources UNKNOWN IMPORTED)
-target_link_libraries(TestUnknownLibWithoutSources PUBLIC $<TARGET_OBJECTS:ObjectLibDependency>)
+target_link_libraries(TestUnknownLibWithoutSources INTERFACE $<TARGET_OBJECTS:ObjectLibDependency>)

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

@@ -6,6 +6,7 @@ run_cmake(exclude-from-all)
 run_cmake(imported)
 run_cmake(imported)
 run_cmake(invalid-name)
 run_cmake(invalid-name)
 run_cmake(invalid-target)
 run_cmake(invalid-target)
+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)

+ 2 - 0
Tests/RunCMake/alias_targets/imported-global-target-stderr.txt

@@ -0,0 +1,2 @@
+^'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'.$

+ 46 - 0
Tests/RunCMake/alias_targets/imported-global-target.cmake

@@ -0,0 +1,46 @@
+
+enable_language(CXX)
+
+
+add_executable(test-exe IMPORTED GLOBAL)
+add_executable(alias-test-exe ALIAS test-exe)
+
+if(TARGET alias-test-exe)
+  get_target_property(aliased-target alias-test-exe ALIASED_TARGET)
+  if("${aliased-target}" STREQUAL "test-exe")
+    get_target_property(aliased-name alias-test-exe NAME)
+    if("${aliased-name}" STREQUAL "test-exe")
+      message("'alias-test-exe' is an alias for '${aliased-target}'"
+              " and its name-property contains '${aliased-name}'.")
+    else()
+      message("'alias-test-exe' is an alias for '${aliased-target}'"
+              " but its name-property contains '${aliased-name}'!?")
+    endif()
+  else()
+    message("'alias-test-exe' is something but not a real target!?")
+  endif()
+else()
+    message("'alias-test-exe' does not exist!?")
+endif()
+
+
+add_library(test-lib SHARED IMPORTED GLOBAL)
+add_library(alias-test-lib ALIAS test-lib)
+
+if(TARGET alias-test-lib)
+  get_target_property(aliased-target alias-test-lib ALIASED_TARGET)
+  if("${aliased-target}" STREQUAL "test-lib")
+    get_target_property(aliased-name alias-test-lib NAME)
+    if("${aliased-name}" STREQUAL "test-lib")
+      message("'alias-test-lib' is an alias for '${aliased-target}'"
+              " and its name-property contains '${aliased-name}'.")
+    else()
+      message("'alias-test-lib' is an alias for '${aliased-target}'"
+              " but its name-property contains '${aliased-name}'!?")
+    endif()
+  else()
+    message("'alias-test-lib' is something but not a real target!?")
+  endif()
+else()
+    message("'alias-test-lib' does not exist!?")
+endif()

+ 8 - 4
Tests/RunCMake/alias_targets/imported-target-stderr.txt

@@ -1,5 +1,9 @@
-CMake Error at imported-target.cmake:6 \(add_library\):
-  add_library cannot create ALIAS target "alias" because target "foo" is
-  IMPORTED.
+^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\):
 Call Stack \(most recent call first\):
-  CMakeLists.txt:3 \(include\)
+  CMakeLists.txt:[0-9]+ \(include\)
+
+
+'alias-test-exe' does not exist![?]
+'alias-test-lib' does not exist![?]$

+ 42 - 2
Tests/RunCMake/alias_targets/imported-target.cmake

@@ -1,6 +1,46 @@
 
 
 enable_language(CXX)
 enable_language(CXX)
 
 
-add_library(foo SHARED IMPORTED)
 
 
-add_library(alias ALIAS foo)
+add_executable(test-exe IMPORTED)
+add_executable(alias-test-exe ALIAS test-exe)
+
+if(TARGET alias-test-exe)
+  get_target_property(aliased-target alias-test-exe ALIASED_TARGET)
+  if("${aliased-target}" STREQUAL "test-exe")
+    get_target_property(aliased-name alias-test-exe NAME)
+    if("${aliased-name}" STREQUAL "test-exe")
+      message("'alias-test-exe' is an alias for '${aliased-target}'"
+              " and its name-property contains '${aliased-name}'.")
+    else()
+      message("'alias-test-exe' is an alias for '${aliased-target}'"
+              " but its name-property contains '${aliased-name}'!?")
+    endif()
+  else()
+    message("'alias-test-exe' is something but not a real target!?")
+  endif()
+else()
+    message("'alias-test-exe' does not exist!?")
+endif()
+
+
+add_library(test-lib SHARED IMPORTED)
+add_library(alias-test-lib ALIAS test-lib)
+
+if(TARGET alias-test-lib)
+  get_target_property(aliased-target alias-test-lib ALIASED_TARGET)
+  if("${aliased-target}" STREQUAL "test-lib")
+    get_target_property(aliased-name alias-test-lib NAME)
+    if("${aliased-name}" STREQUAL "test-lib")
+      message("'alias-test-lib' is an alias for '${aliased-target}'"
+              " and its name-property contains '${aliased-name}'.")
+    else()
+      message("'alias-test-lib' is an alias for '${aliased-target}'"
+              " but its name-property contains '${aliased-name}'!?")
+    endif()
+  else()
+    message("'alias-test-lib' is something but not a real target!?")
+  endif()
+else()
+    message("'alias-test-lib' does not exist!?")
+endif()

+ 8 - 8
Tests/RunCMake/interface_library/target_commands-stderr.txt

@@ -23,25 +23,25 @@ Call Stack \(most recent call first\):
   CMakeLists.txt:3 \(include\)
   CMakeLists.txt:3 \(include\)
 +
 +
 CMake Error at target_commands.cmake:9 \(target_include_directories\):
 CMake Error at target_commands.cmake:9 \(target_include_directories\):
-  target_include_directories may only be set INTERFACE properties on
-  INTERFACE targets
+  target_include_directories may only set INTERFACE properties on INTERFACE
+  targets
 Call Stack \(most recent call first\):
 Call Stack \(most recent call first\):
   CMakeLists.txt:3 \(include\)
   CMakeLists.txt:3 \(include\)
 +
 +
 CMake Error at target_commands.cmake:10 \(target_include_directories\):
 CMake Error at target_commands.cmake:10 \(target_include_directories\):
-  target_include_directories may only be set INTERFACE properties on
-  INTERFACE targets
+  target_include_directories may only set INTERFACE properties on INTERFACE
+  targets
 Call Stack \(most recent call first\):
 Call Stack \(most recent call first\):
   CMakeLists.txt:3 \(include\)
   CMakeLists.txt:3 \(include\)
 +
 +
 CMake Error at target_commands.cmake:12 \(target_compile_definitions\):
 CMake Error at target_commands.cmake:12 \(target_compile_definitions\):
-  target_compile_definitions may only be set INTERFACE properties on
-  INTERFACE targets
+  target_compile_definitions may only set INTERFACE properties on INTERFACE
+  targets
 Call Stack \(most recent call first\):
 Call Stack \(most recent call first\):
   CMakeLists.txt:3 \(include\)
   CMakeLists.txt:3 \(include\)
 +
 +
 CMake Error at target_commands.cmake:13 \(target_compile_definitions\):
 CMake Error at target_commands.cmake:13 \(target_compile_definitions\):
-  target_compile_definitions may only be set INTERFACE properties on
-  INTERFACE targets
+  target_compile_definitions may only set INTERFACE properties on INTERFACE
+  targets
 Call Stack \(most recent call first\):
 Call Stack \(most recent call first\):
   CMakeLists.txt:3 \(include\)
   CMakeLists.txt:3 \(include\)

+ 4 - 3
Tests/RunCMake/target_compile_features/imported_target-stderr.txt

@@ -1,4 +1,5 @@
-CMake Error at imported_target.cmake:[0-9]+ \(target_compile_features\):
-  Cannot specify compile features for imported target "main".
+^CMake Error at imported_target.cmake:[0-9]+ \(target_compile_features\):
+  target_compile_features may only set INTERFACE properties on INTERFACE
+  targets
 Call Stack \(most recent call first\):
 Call Stack \(most recent call first\):
-  CMakeLists.txt:3 \(include\)
+  CMakeLists.txt:3 \(include\)$

+ 8 - 2
Tests/RunCMake/target_compile_features/imported_target.cmake

@@ -1,4 +1,10 @@
 enable_language(CXX)
 enable_language(CXX)
 
 
-add_library(main INTERFACE IMPORTED)
-target_compile_features(main INTERFACE cxx_delegating_constructors)
+add_library(lib1-interface INTERFACE IMPORTED)
+target_compile_features(lib1-interface INTERFACE cxx_delegating_constructors)
+
+add_library(lib2-interface INTERFACE IMPORTED)
+target_compile_features(lib2-interface PUBLIC cxx_delegating_constructors)
+
+add_library(lib-shared SHARED IMPORTED)
+target_compile_features(lib-shared INTERFACE cxx_delegating_constructors)

+ 1 - 1
Tests/RunCMake/target_compile_features/invalid_args_on_interface-stderr.txt

@@ -1,5 +1,5 @@
 CMake Error at invalid_args_on_interface.cmake:[0-9]+ \(target_compile_features\):
 CMake Error at invalid_args_on_interface.cmake:[0-9]+ \(target_compile_features\):
-  target_compile_features may only be set INTERFACE properties on INTERFACE
+  target_compile_features may only set INTERFACE properties on INTERFACE
   targets
   targets
 Call Stack \(most recent call first\):
 Call Stack \(most recent call first\):
   CMakeLists.txt:3 \(include\)
   CMakeLists.txt:3 \(include\)

+ 2 - 0
Tests/RunCMake/target_link_libraries/ImportedTarget.cmake

@@ -0,0 +1,2 @@
+add_library(UnknownImportedGlobal UNKNOWN IMPORTED GLOBAL)
+target_link_libraries(UnknownImportedGlobal INTERFACE z)

+ 0 - 0
Tests/RunCMake/add_library/UNKNOWNwithNoSourcesButLinkObjects-result.txt → Tests/RunCMake/target_link_libraries/ImportedTargetFailure-result.txt


+ 5 - 0
Tests/RunCMake/target_link_libraries/ImportedTargetFailure-stderr.txt

@@ -0,0 +1,5 @@
+^CMake Error at ImportedTargetFailure.cmake:[0-9]+ \(target_link_libraries\):
+  IMPORTED library can only be used with the INTERFACE keyword of
+  target_link_libraries
+Call Stack \(most recent call first\):
+  CMakeLists\.txt:[0-9]+ \(include\)$

+ 2 - 0
Tests/RunCMake/target_link_libraries/ImportedTargetFailure.cmake

@@ -0,0 +1,2 @@
+add_library(UnknownImportedGlobal UNKNOWN IMPORTED GLOBAL)
+target_link_libraries(UnknownImportedGlobal PRIVATE z)

+ 2 - 0
Tests/RunCMake/target_link_libraries/RunCMakeTest.cmake

@@ -4,6 +4,8 @@ run_cmake(CMP0023-WARN)
 run_cmake(CMP0023-NEW)
 run_cmake(CMP0023-NEW)
 run_cmake(CMP0023-WARN-2)
 run_cmake(CMP0023-WARN-2)
 run_cmake(CMP0023-NEW-2)
 run_cmake(CMP0023-NEW-2)
+run_cmake(ImportedTarget)
+run_cmake(ImportedTargetFailure)
 run_cmake(MixedSignature)
 run_cmake(MixedSignature)
 run_cmake(Separate-PRIVATE-LINK_PRIVATE-uses)
 run_cmake(Separate-PRIVATE-LINK_PRIVATE-uses)
 run_cmake(SubDirTarget)
 run_cmake(SubDirTarget)