Forráskód Böngészése

GenEx: Remove unneeded dependencies from target info queries

Only generate a graph dependency between a custom command and
a target when the custom command queries for the file path
of an artifact of the target.

This makes generator expressions such as `TARGET_FILE_DIR`
behave the same way as `TARGET_PROPERTY` which never generated
a graph dependency.
Robert Maynard 5 éve
szülő
commit
f14b390198

+ 16 - 7
Help/command/add_custom_command.rst

@@ -102,13 +102,22 @@ The options are:
   a target later in the command line (i.e. as a command argument rather
   than as the command to execute).
 
-  Whenever a target is used as a command to execute or is mentioned in a
-  generator expression as a command argument, a target-level dependency
-  will be added automatically so that the mentioned target will be built
-  before any target using this custom command.  However this does NOT add
-  a file-level dependency that would cause the custom command to re-run
-  whenever the executable is recompiled.  List target names with
-  the ``DEPENDS`` option to add such file-level dependencies.
+  Whenever one of the following target based generator expressions are used as
+  a command to execute or is mentioned in a command argument, a target-level
+  dependency will be added automatically so that the mentioned target will be
+  built before any target using this custom command
+  (see policy :policy:`CMP0112`).
+
+    * ``TARGET_FILE``
+    * ``TARGET_LINKER_FILE``
+    * ``TARGET_SONAME_FILE``
+    * ``TARGET_PDB_FILE``
+
+  This target-level dependency does NOT add a file-level dependency that would
+  cause the custom command to re-run whenever the executable is recompiled.
+  List target names with the ``DEPENDS`` option to add such file-level
+  dependencies.
+
 
 ``COMMENT``
   Display the given message before the commands are executed at

+ 9 - 4
Help/command/add_custom_target.rst

@@ -81,10 +81,15 @@ The options are:
   a target later in the command line (i.e. as a command argument rather
   than as the command to execute).
 
-  Whenever a target is used as a command to execute or is mentioned in a
-  generator expression as a command argument, a target-level dependency
-  will be added automatically so that the mentioned target will be built
-  before this custom target.
+  Whenever one of the following target based generator expressions are used as
+  a command to execute or is mentioned in a command argument, a target-level
+  dependency will be added automatically so that the mentioned target will be
+  built before this custom target (see policy :policy:`CMP0112`).
+
+    * ``TARGET_FILE``
+    * ``TARGET_LINKER_FILE``
+    * ``TARGET_SONAME_FILE``
+    * ``TARGET_PDB_FILE``
 
   The command and arguments are optional and if not specified an empty
   target will be created.

+ 30 - 0
Help/manual/cmake-generator-expressions.7.rst

@@ -596,6 +596,9 @@ which is just the string ``tgt``.
 
 ``$<TARGET_NAME_IF_EXISTS:tgt>``
   The target name ``tgt`` if the target exists, an empty string otherwise.
+
+  Note that ``tgt`` is not added as a dependency of the target this
+  expression is evaluated on.
 ``$<TARGET_FILE:tgt>``
   Full path to the ``tgt`` binary file.
 ``$<TARGET_FILE_BASE_NAME:tgt>``
@@ -633,6 +636,9 @@ which is just the string ``tgt``.
   The ``tgt`` filename.
 ``$<TARGET_FILE_DIR:tgt>``
   Directory of the ``tgt`` binary file.
+
+  Note that ``tgt`` is not added as a dependency of the target this
+  expression is evaluated on (see policy :policy:`CMP0112`).
 ``$<TARGET_LINKER_FILE:tgt>``
   File used when linking to the ``tgt`` target.  This will usually
   be the library that ``tgt`` represents (``.a``, ``.lib``, ``.so``),
@@ -674,14 +680,26 @@ which is just the string ``tgt``.
   expression is evaluated on.
 ``$<TARGET_LINKER_FILE_NAME:tgt>``
   Name of file used to link target ``tgt``.
+
+  Note that ``tgt`` is not added as a dependency of the target this
+  expression is evaluated on (see policy :policy:`CMP0112`).
 ``$<TARGET_LINKER_FILE_DIR:tgt>``
   Directory of file used to link target ``tgt``.
+
+  Note that ``tgt`` is not added as a dependency of the target this
+  expression is evaluated on (see policy :policy:`CMP0112`).
 ``$<TARGET_SONAME_FILE:tgt>``
   File with soname (``.so.3``) where ``tgt`` is the name of a target.
 ``$<TARGET_SONAME_FILE_NAME:tgt>``
   Name of file with soname (``.so.3``).
+
+  Note that ``tgt`` is not added as a dependency of the target this
+  expression is evaluated on (see policy :policy:`CMP0112`).
 ``$<TARGET_SONAME_FILE_DIR:tgt>``
   Directory of with soname (``.so.3``).
+
+  Note that ``tgt`` is not added as a dependency of the target this
+  expression is evaluated on (see policy :policy:`CMP0112`).
 ``$<TARGET_PDB_FILE:tgt>``
   Full path to the linker generated program database file (.pdb)
   where ``tgt`` is the name of a target.
@@ -707,17 +725,29 @@ which is just the string ``tgt``.
   expression is evaluated on.
 ``$<TARGET_PDB_FILE_NAME:tgt>``
   Name of the linker generated program database file (.pdb).
+
+  Note that ``tgt`` is not added as a dependency of the target this
+  expression is evaluated on (see policy :policy:`CMP0112`).
 ``$<TARGET_PDB_FILE_DIR:tgt>``
   Directory of the linker generated program database file (.pdb).
+
+  Note that ``tgt`` is not added as a dependency of the target this
+  expression is evaluated on (see policy :policy:`CMP0112`).
 ``$<TARGET_BUNDLE_DIR:tgt>``
   Full path to the bundle directory (``my.app``, ``my.framework``, or
   ``my.bundle``) where ``tgt`` is the name of a target.
+
+  Note that ``tgt`` is not added as a dependency of the target this
+  expression is evaluated on (see policy :policy:`CMP0112`).
 ``$<TARGET_BUNDLE_CONTENT_DIR:tgt>``
   Full path to the bundle content directory where ``tgt`` is the name of a
   target. For the macOS SDK it leads to ``my.app/Contents``, ``my.framework``,
   or ``my.bundle/Contents``. For all other SDKs (e.g. iOS) it leads to
   ``my.app``, ``my.framework``, or ``my.bundle`` due to the flat bundle
   structure.
+
+  Note that ``tgt`` is not added as a dependency of the target this
+  expression is evaluated on (see policy :policy:`CMP0112`).
 ``$<TARGET_PROPERTY:tgt,prop>``
   Value of the property ``prop`` on the target ``tgt``.
 

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

@@ -57,6 +57,7 @@ Policies Introduced by CMake 3.19
 .. toctree::
    :maxdepth: 1
 
+   CMP0112: Target file component generator expressions do not add target dependencies. </policy/CMP0112>
    CMP0111: An imported target with a missing location fails during generation. </policy/CMP0111>
    CMP0110: add_test() supports arbitrary characters in test names. </policy/CMP0110>
    CMP0109: find_program() requires permission to execute but not to read. </policy/CMP0109>

+ 39 - 0
Help/policy/CMP0112.rst

@@ -0,0 +1,39 @@
+CMP0112
+-------
+
+.. versionadded:: 3.19
+
+Target file component generator expressions do not add target dependencies.
+
+The following target-based generator expressions that query for directory or
+file name components no longer add a dependency on the evaluated target.
+
+    - ``TARGET_FILE_DIR``
+    - ``TARGET_LINKER_FILE_BASE_NAME``
+    - ``TARGET_LINKER_FILE_NAME``
+    - ``TARGET_LINKER_FILE_DIR``
+    - ``TARGET_SONAME_FILE_NAME``
+    - ``TARGET_SONAME_FILE_DIR``
+    - ``TARGET_PDB_FILE_NAME``
+    - ``TARGET_PDB_FILE_DIR``
+    - ``TARGET_BUNDLE_DIR``
+    - ``TARGET_BUNDLE_CONTENT_DIR``
+
+
+In CMake 3.18 and lower a dependency on the evaluated target of the above
+generator expressions would be always added.  CMake 3.19 and above prefer
+to not add this dependency.  This policy provides compatibility for projects
+that have not been updated to expect the new behavior.
+
+The ``OLD`` behavior for this policy is to add a dependency on the evaluated
+target for the the above generator expressions.  The ``NEW`` behavior of
+this policy is to not add a dependency on the evaluated target for the the
+above generator expressions.
+
+This policy was introduced in CMake version 3.19.  Unlike many policies,
+CMake version |release| does *not* warn by default when this policy
+is not set and simply uses ``OLD`` behavior.  See documentation of the
+:variable:`CMAKE_POLICY_WARNING_CMP0112 <CMAKE_POLICY_WARNING_CMP<NNNN>>`
+variable to control the warning.
+
+.. include:: DEPRECATED.txt

+ 17 - 0
Help/release/dev/relax-target-generator-expression-dependency-addition.rst

@@ -0,0 +1,17 @@
+relax-target-generator-expression-dependency-addition
+-----------------------------------------------------
+
+* The following target-based generator expressions that query for directory or
+  file name components no longer add a dependency on the evaluated target.
+  See policy :policy:`CMP0112`.
+
+    - ``TARGET_FILE_DIR``
+    - ``TARGET_LINKER_FILE_BASE_NAME``
+    - ``TARGET_LINKER_FILE_NAME``
+    - ``TARGET_LINKER_FILE_DIR``
+    - ``TARGET_SONAME_FILE_NAME``
+    - ``TARGET_SONAME_FILE_DIR``
+    - ``TARGET_PDB_FILE_NAME``
+    - ``TARGET_PDB_FILE_DIR``
+    - ``TARGET_BUNDLE_DIR``
+    - ``TARGET_BUNDLE_CONTENT_DIR``

+ 2 - 0
Help/variable/CMAKE_POLICY_WARNING_CMPNNNN.rst

@@ -25,6 +25,8 @@ warn by default:
   policy :policy:`CMP0089`.
 * ``CMAKE_POLICY_WARNING_CMP0102`` controls the warning for
   policy :policy:`CMP0102`.
+* ``CMAKE_POLICY_WARNING_CMP0112`` controls the warning for
+  policy :policy:`CMP0112`.
 
 This variable should not be set by a project in CMake code.  Project
 developers running CMake may set this variable in their cache to

+ 68 - 2
Source/cmGeneratorExpressionNode.cxx

@@ -1901,6 +1901,70 @@ class ArtifactSonameTag;
 class ArtifactBundleDirTag;
 class ArtifactBundleContentDirTag;
 
+template <typename ArtifactT, typename ComponentT>
+struct TargetFilesystemArtifactDependency
+{
+  static void AddDependency(cmGeneratorTarget* target,
+                            cmGeneratorExpressionContext* context)
+  {
+    context->DependTargets.insert(target);
+    context->AllTargets.insert(target);
+  }
+};
+
+struct TargetFilesystemArtifactDependencyCMP0112
+{
+  static void AddDependency(cmGeneratorTarget* target,
+                            cmGeneratorExpressionContext* context)
+  {
+    context->AllTargets.insert(target);
+    cmLocalGenerator* lg = context->LG;
+    switch (target->GetPolicyStatusCMP0112()) {
+      case cmPolicies::WARN:
+        if (lg->GetMakefile()->PolicyOptionalWarningEnabled(
+              "CMAKE_POLICY_WARNING_CMP0112")) {
+          std::string err =
+            cmStrCat(cmPolicies::GetPolicyWarning(cmPolicies::CMP0112),
+                     "\nDependency being added to target:\n  \"",
+                     target->GetName(), "\"\n");
+          lg->GetCMakeInstance()->IssueMessage(MessageType ::AUTHOR_WARNING,
+                                               err, context->Backtrace);
+        }
+        CM_FALLTHROUGH;
+      case cmPolicies::OLD:
+        context->DependTargets.insert(target);
+        break;
+      case cmPolicies::REQUIRED_IF_USED:
+      case cmPolicies::REQUIRED_ALWAYS:
+      case cmPolicies::NEW:
+        break;
+    }
+  }
+};
+
+template <typename ArtifactT>
+struct TargetFilesystemArtifactDependency<ArtifactT, ArtifactNameTag>
+  : TargetFilesystemArtifactDependencyCMP0112
+{
+};
+template <typename ArtifactT>
+struct TargetFilesystemArtifactDependency<ArtifactT, ArtifactDirTag>
+  : TargetFilesystemArtifactDependencyCMP0112
+{
+};
+template <>
+struct TargetFilesystemArtifactDependency<ArtifactBundleDirTag,
+                                          ArtifactPathTag>
+  : TargetFilesystemArtifactDependencyCMP0112
+{
+};
+template <>
+struct TargetFilesystemArtifactDependency<ArtifactBundleContentDirTag,
+                                          ArtifactPathTag>
+  : TargetFilesystemArtifactDependencyCMP0112
+{
+};
+
 template <typename ArtifactT>
 struct TargetFilesystemArtifactResultCreator
 {
@@ -2153,8 +2217,10 @@ struct TargetFilesystemArtifact : public TargetArtifactBase
     if (!target) {
       return std::string();
     }
-    context->DependTargets.insert(target);
-    context->AllTargets.insert(target);
+    // Not a dependent target if we are querying for ArtifactDirTag,
+    // ArtifactNameTag, ArtifactBundleDirTag, and ArtifactBundleContentDirTag
+    TargetFilesystemArtifactDependency<ArtifactT, ComponentT>::AddDependency(
+      target, context);
 
     std::string result =
       TargetFilesystemArtifactResultCreator<ArtifactT>::Create(target, context,

+ 6 - 1
Source/cmPolicies.h

@@ -330,6 +330,10 @@ class cmMakefile;
   SELECT(POLICY, CMP0111,                                                     \
          "An imported target with a missing location fails during "           \
          "generation.",                                                       \
+         3, 19, 0, cmPolicies::WARN)                                          \
+  SELECT(POLICY, CMP0112,                                                     \
+         "Target file component generator expressions do not add target "     \
+         "dependencies.",                                                     \
          3, 19, 0, cmPolicies::WARN)
 
 #define CM_SELECT_ID(F, A1, A2, A3, A4, A5, A6) F(A1)
@@ -363,7 +367,8 @@ class cmMakefile;
   F(CMP0099)                                                                  \
   F(CMP0104)                                                                  \
   F(CMP0105)                                                                  \
-  F(CMP0108)
+  F(CMP0108)                                                                  \
+  F(CMP0112)
 
 /** \class cmPolicies
  * \brief Handles changes in CMake behavior and policies

+ 3 - 1
Tests/RunCMake/GenEx-TARGET_FILE/RunCMakeTest.cmake

@@ -2,8 +2,10 @@ include(RunCMake)
 
 run_cmake(TARGET_FILE-recursion)
 run_cmake(OUTPUT_NAME-recursion)
-run_cmake(TARGET_FILE_PREFIX)
+run_cmake(TARGET_FILE_DIR-dependency)
+run_cmake(TARGET_FILE_DIR-no-dependency)
 run_cmake(TARGET_FILE_PREFIX-imported-target)
+run_cmake(TARGET_FILE_PREFIX)
 run_cmake(TARGET_FILE_PREFIX-non-valid-target)
 run_cmake(TARGET_LINKER_FILE_PREFIX-non-valid-target)
 run_cmake(TARGET_FILE_SUFFIX)

+ 1 - 0
Tests/RunCMake/GenEx-TARGET_FILE/TARGET_FILE_DIR-dependency-result.txt

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

+ 6 - 0
Tests/RunCMake/GenEx-TARGET_FILE/TARGET_FILE_DIR-dependency-stderr.txt

@@ -0,0 +1,6 @@
+.*Policy CMP0112 is not set.*
+.*Dependency being added to target.*
+.*exec1.*
+CMake Error: The inter-target dependency graph.*
+.*"exec1" of type EXECUTABLE
+    depends on "copyFile" \(strong\)

+ 12 - 0
Tests/RunCMake/GenEx-TARGET_FILE/TARGET_FILE_DIR-dependency.cmake

@@ -0,0 +1,12 @@
+set(CMAKE_POLICY_WARNING_CMP0112 TRUE)
+
+enable_language (C)
+
+add_executable (exec1 empty.c)
+
+add_custom_target(copyFile
+  COMMAND ${CMAKE_COMMAND} -E copy_if_different
+        "${CMAKE_CURRENT_SOURCE_DIR}/empty.c"
+        "$<TARGET_FILE_DIR:exec1>/$<TARGET_FILE_BASE_NAME:exec1>_e.c"
+)
+add_dependencies(exec1 copyFile)

+ 12 - 0
Tests/RunCMake/GenEx-TARGET_FILE/TARGET_FILE_DIR-no-dependency.cmake

@@ -0,0 +1,12 @@
+cmake_policy(SET CMP0112 NEW)
+
+enable_language (C)
+
+add_executable (exec1 empty.c)
+
+add_custom_target(copyFile
+  COMMAND ${CMAKE_COMMAND} -E copy_if_different
+        "${CMAKE_CURRENT_SOURCE_DIR}/empty.c"
+        "$<TARGET_FILE_DIR:exec1>/$<TARGET_FILE_BASE_NAME:exec1>_e.c"
+)
+add_dependencies(exec1 copyFile)

+ 1 - 0
Tests/RunCMake/TargetPolicies/PolicyList-stderr.txt

@@ -32,6 +32,7 @@
    \* CMP0104
    \* CMP0105
    \* CMP0108
+   \* CMP0112
 
 Call Stack \(most recent call first\):
   CMakeLists.txt:3 \(include\)