From f14b390198222f5d7eca9e5109fabcb0188da762 Mon Sep 17 00:00:00 2001 From: Robert Maynard Date: Tue, 18 Aug 2020 08:25:31 -0400 Subject: 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. --- Help/command/add_custom_command.rst | 23 ++++--- Help/command/add_custom_target.rst | 13 ++-- Help/manual/cmake-generator-expressions.7.rst | 30 ++++++++++ Help/manual/cmake-policies.7.rst | 1 + Help/policy/CMP0112.rst | 39 ++++++++++++ ...et-generator-expression-dependency-addition.rst | 17 ++++++ Help/variable/CMAKE_POLICY_WARNING_CMPNNNN.rst | 2 + Source/cmGeneratorExpressionNode.cxx | 70 +++++++++++++++++++++- Source/cmPolicies.h | 7 ++- .../RunCMake/GenEx-TARGET_FILE/RunCMakeTest.cmake | 4 +- .../TARGET_FILE_DIR-dependency-result.txt | 1 + .../TARGET_FILE_DIR-dependency-stderr.txt | 6 ++ .../TARGET_FILE_DIR-dependency.cmake | 12 ++++ .../TARGET_FILE_DIR-no-dependency.cmake | 12 ++++ .../RunCMake/TargetPolicies/PolicyList-stderr.txt | 1 + 15 files changed, 223 insertions(+), 15 deletions(-) create mode 100644 Help/policy/CMP0112.rst create mode 100644 Help/release/dev/relax-target-generator-expression-dependency-addition.rst create mode 100644 Tests/RunCMake/GenEx-TARGET_FILE/TARGET_FILE_DIR-dependency-result.txt create mode 100644 Tests/RunCMake/GenEx-TARGET_FILE/TARGET_FILE_DIR-dependency-stderr.txt create mode 100644 Tests/RunCMake/GenEx-TARGET_FILE/TARGET_FILE_DIR-dependency.cmake create mode 100644 Tests/RunCMake/GenEx-TARGET_FILE/TARGET_FILE_DIR-no-dependency.cmake diff --git a/Help/command/add_custom_command.rst b/Help/command/add_custom_command.rst index 9279748..231f9da 100644 --- a/Help/command/add_custom_command.rst +++ b/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 diff --git a/Help/command/add_custom_target.rst b/Help/command/add_custom_target.rst index 56ab414..2eb0c88 100644 --- a/Help/command/add_custom_target.rst +++ b/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. diff --git a/Help/manual/cmake-generator-expressions.7.rst b/Help/manual/cmake-generator-expressions.7.rst index c7f6b27..5b55cac 100644 --- a/Help/manual/cmake-generator-expressions.7.rst +++ b/Help/manual/cmake-generator-expressions.7.rst @@ -596,6 +596,9 @@ which is just the string ``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. ``$`` Full path to the ``tgt`` binary file. ``$`` @@ -633,6 +636,9 @@ which is just the string ``tgt``. The ``tgt`` filename. ``$`` 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`). ``$`` 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. ``$`` 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`). ``$`` 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`). ``$`` File with soname (``.so.3``) where ``tgt`` is the name of a target. ``$`` 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`). ``$`` 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`). ``$`` 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. ``$`` 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`). ``$`` 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`). ``$`` 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`). ``$`` 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`). ``$`` Value of the property ``prop`` on the target ``tgt``. diff --git a/Help/manual/cmake-policies.7.rst b/Help/manual/cmake-policies.7.rst index ce8969b..cd1d4d3 100644 --- a/Help/manual/cmake-policies.7.rst +++ b/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. CMP0111: An imported target with a missing location fails during generation. CMP0110: add_test() supports arbitrary characters in test names. CMP0109: find_program() requires permission to execute but not to read. diff --git a/Help/policy/CMP0112.rst b/Help/policy/CMP0112.rst new file mode 100644 index 0000000..3eab6d2 --- /dev/null +++ b/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 >` +variable to control the warning. + +.. include:: DEPRECATED.txt diff --git a/Help/release/dev/relax-target-generator-expression-dependency-addition.rst b/Help/release/dev/relax-target-generator-expression-dependency-addition.rst new file mode 100644 index 0000000..6d30596 --- /dev/null +++ b/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`` diff --git a/Help/variable/CMAKE_POLICY_WARNING_CMPNNNN.rst b/Help/variable/CMAKE_POLICY_WARNING_CMPNNNN.rst index de71d0e..d35595a 100644 --- a/Help/variable/CMAKE_POLICY_WARNING_CMPNNNN.rst +++ b/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 diff --git a/Source/cmGeneratorExpressionNode.cxx b/Source/cmGeneratorExpressionNode.cxx index fdc8f29..d9cdf11 100644 --- a/Source/cmGeneratorExpressionNode.cxx +++ b/Source/cmGeneratorExpressionNode.cxx @@ -1901,6 +1901,70 @@ class ArtifactSonameTag; class ArtifactBundleDirTag; class ArtifactBundleContentDirTag; +template +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 +struct TargetFilesystemArtifactDependency + : TargetFilesystemArtifactDependencyCMP0112 +{ +}; +template +struct TargetFilesystemArtifactDependency + : TargetFilesystemArtifactDependencyCMP0112 +{ +}; +template <> +struct TargetFilesystemArtifactDependency + : TargetFilesystemArtifactDependencyCMP0112 +{ +}; +template <> +struct TargetFilesystemArtifactDependency + : TargetFilesystemArtifactDependencyCMP0112 +{ +}; + template 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::AddDependency( + target, context); std::string result = TargetFilesystemArtifactResultCreator::Create(target, context, diff --git a/Source/cmPolicies.h b/Source/cmPolicies.h index 1a12dab..bf6e531 100644 --- a/Source/cmPolicies.h +++ b/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 diff --git a/Tests/RunCMake/GenEx-TARGET_FILE/RunCMakeTest.cmake b/Tests/RunCMake/GenEx-TARGET_FILE/RunCMakeTest.cmake index ccec633..55b0f9b 100644 --- a/Tests/RunCMake/GenEx-TARGET_FILE/RunCMakeTest.cmake +++ b/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) diff --git a/Tests/RunCMake/GenEx-TARGET_FILE/TARGET_FILE_DIR-dependency-result.txt b/Tests/RunCMake/GenEx-TARGET_FILE/TARGET_FILE_DIR-dependency-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/GenEx-TARGET_FILE/TARGET_FILE_DIR-dependency-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/GenEx-TARGET_FILE/TARGET_FILE_DIR-dependency-stderr.txt b/Tests/RunCMake/GenEx-TARGET_FILE/TARGET_FILE_DIR-dependency-stderr.txt new file mode 100644 index 0000000..0a79032 --- /dev/null +++ b/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\) diff --git a/Tests/RunCMake/GenEx-TARGET_FILE/TARGET_FILE_DIR-dependency.cmake b/Tests/RunCMake/GenEx-TARGET_FILE/TARGET_FILE_DIR-dependency.cmake new file mode 100644 index 0000000..e18ccd9 --- /dev/null +++ b/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" + "$/$_e.c" +) +add_dependencies(exec1 copyFile) diff --git a/Tests/RunCMake/GenEx-TARGET_FILE/TARGET_FILE_DIR-no-dependency.cmake b/Tests/RunCMake/GenEx-TARGET_FILE/TARGET_FILE_DIR-no-dependency.cmake new file mode 100644 index 0000000..e048e10 --- /dev/null +++ b/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" + "$/$_e.c" +) +add_dependencies(exec1 copyFile) diff --git a/Tests/RunCMake/TargetPolicies/PolicyList-stderr.txt b/Tests/RunCMake/TargetPolicies/PolicyList-stderr.txt index 2454f25..fe13e81 100644 --- a/Tests/RunCMake/TargetPolicies/PolicyList-stderr.txt +++ b/Tests/RunCMake/TargetPolicies/PolicyList-stderr.txt @@ -32,6 +32,7 @@ \* CMP0104 \* CMP0105 \* CMP0108 + \* CMP0112 Call Stack \(most recent call first\): CMakeLists.txt:3 \(include\) -- cgit v0.12