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.
This commit is contained in:
Robert Maynard 2020-08-18 08:25:31 -04:00 committed by Brad King
parent 5294febcaf
commit f14b390198
15 changed files with 223 additions and 15 deletions

View File

@ -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

View File

@ -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.

View File

@ -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``.

View File

@ -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
Help/policy/CMP0112.rst Normal file
View File

@ -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

View File

@ -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``

View File

@ -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

View File

@ -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,

View File

@ -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

View File

@ -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)

View File

@ -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\)

View File

@ -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)

View File

@ -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)

View File

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