LINK_LIBRARIES: Add support for LINK_ONLY genex

Previously we always used content guarded by `$<LINK_ONLY:...>`
in `LINK_LIBRARIES`, even when evaluating for non-linking usage
requirements.  Add a policy to honor `LINK_ONLY` in `LINK_LIBRARIES`
the same way we already do in `INTERFACE_LINK_LIBRARIES`.
This commit is contained in:
Brad King
2022-03-22 11:09:23 -04:00
parent 41a6b4a53b
commit cf312a2e54
10 changed files with 99 additions and 8 deletions

View File

@@ -1106,12 +1106,15 @@ Output-Related Expressions
.. versionadded:: 3.1
Content of ``...`` except when evaluated in a link interface while
propagating :ref:`Target Usage Requirements`, in which case it is the
empty string.
Intended for use only in an :prop_tgt:`INTERFACE_LINK_LIBRARIES` target
property, perhaps via the :command:`target_link_libraries` command,
to specify private link dependencies without other usage requirements.
Content of ``...``, except while collecting :ref:`Target Usage Requirements`,
in which case it is the empty string. This is intended for use in an
:prop_tgt:`INTERFACE_LINK_LIBRARIES` target property, typically populated
via the :command:`target_link_libraries` command, to specify private link
dependencies without other usage requirements.
.. versionadded:: 3.24
``LINK_ONLY`` may also be used in a :prop_tgt:`LINK_LIBRARIES` target
property. See policy :policy:`CMP0131`.
.. genex:: $<LINK_LIBRARY:feature,library-list>

View File

@@ -58,6 +58,7 @@ Policies Introduced by CMake 3.24
.. toctree::
:maxdepth: 1
CMP0131: LINK_LIBRARIES supports the LINK_ONLY generator expression. </policy/CMP0131>
CMP0130: while() diagnoses condition evaluation errors. </policy/CMP0130>
Policies Introduced by CMake 3.23

31
Help/policy/CMP0131.rst Normal file
View File

@@ -0,0 +1,31 @@
CMP0131
-------
.. versionadded:: 3.24
:prop_tgt:`LINK_LIBRARIES` supports the :genex:`$<LINK_ONLY:...>`
generator expression.
CMake 3.23 and below documented the :genex:`$<LINK_ONLY:...>` generator
expression only for use in :prop_tgt:`INTERFACE_LINK_LIBRARIES`.
When used in :prop_tgt:`LINK_LIBRARIES`, the content guarded inside
:genex:`$<LINK_ONLY:...>` was always used, even when collecting non-linking
usage requirements such as :prop_tgt:`INTERFACE_COMPILE_DEFINITIONS`.
CMake 3.24 and above prefer to support :genex:`$<LINK_ONLY:...>`, when
used in :prop_tgt:`LINK_LIBRARIES`, by using the guarded content only
for link dependencies and not other usage requirements. This policy
provides compatibility for projects that have not been updated to
account for this change.
The ``OLD`` behavior for this policy is to use :prop_tgt:`LINK_LIBRARIES`
content guarded by :genex:`$<LINK_ONLY:...>` even for non-linking
usage requirements. The ``NEW`` behavior for this policy is to to use
the guarded content only for link dependencies.
This policy was introduced in CMake version 3.24. Use the
:command:`cmake_policy` command to set this policy to ``OLD`` or ``NEW``
explicitly. Unlike many policies, CMake version |release| does *not*
warn when this policy is not set, and simply uses ``OLD`` behavior.
.. include:: DEPRECATED.txt

View File

@@ -5,3 +5,7 @@ link-interface-direct
:prop_tgt:`INTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE` target properties
were added to express usage requirements affecting a consumer's
direct link dependencies.
* The :prop_tgt:`LINK_LIBRARIES` target property now supports
the :genex:`$<LINK_ONLY:...>` generator expression.
See policy :policy:`CMP0131`.

View File

@@ -8152,6 +8152,20 @@ void cmGeneratorTarget::ComputeLinkImplementationLibraries(
// Keep this logic in sync with ExpandLinkItems.
cmGeneratorExpressionDAGChecker dagChecker(this, "LINK_LIBRARIES", nullptr,
nullptr);
// The $<LINK_ONLY> expression may be used to specify link dependencies
// that are otherwise excluded from usage requirements.
if (implFor == LinkInterfaceFor::Usage) {
switch (this->GetPolicyStatusCMP0131()) {
case cmPolicies::WARN:
case cmPolicies::OLD:
break;
case cmPolicies::REQUIRED_IF_USED:
case cmPolicies::REQUIRED_ALWAYS:
case cmPolicies::NEW:
dagChecker.SetTransitivePropertiesOnly();
break;
}
}
cmGeneratorExpression ge(entry.Backtrace);
std::unique_ptr<cmCompiledGeneratorExpression> const cge =
ge.Parse(entry.Value);

View File

@@ -390,7 +390,10 @@ class cmMakefile;
"Compiler id for MCST LCC compilers is now LCC, not GNU.", 3, 23, 0, \
cmPolicies::WARN) \
SELECT(POLICY, CMP0130, "while() diagnoses condition evaluation errors.", \
3, 24, 0, cmPolicies::WARN)
3, 24, 0, cmPolicies::WARN) \
SELECT(POLICY, CMP0131, \
"LINK_LIBRARIES supports the LINK_ONLY generator expression.", 3, \
24, 0, cmPolicies::WARN)
#define CM_SELECT_ID(F, A1, A2, A3, A4, A5, A6) F(A1)
#define CM_FOR_EACH_POLICY_ID(POLICY) \
@@ -426,7 +429,8 @@ class cmMakefile;
F(CMP0108) \
F(CMP0112) \
F(CMP0113) \
F(CMP0119)
F(CMP0119) \
F(CMP0131)
/** \class cmPolicies
* \brief Handles changes in CMake behavior and policies

View File

@@ -59,3 +59,12 @@ set_property(TARGET bar_static_private APPEND PROPERTY INTERFACE_LINK_LIBRARIES
add_executable(InterfaceLinkLibraries main_vs6_4.cpp)
set_property(TARGET InterfaceLinkLibraries APPEND PROPERTY LINK_LIBRARIES bar_static_private)
add_library(foo_link_only STATIC foo_link_only.c)
target_compile_definitions(foo_link_only PUBLIC FOO_LINK_ONLY)
add_executable(use_foo_link_only_CMP0131_OLD use_foo_link_only.c)
target_link_libraries(use_foo_link_only_CMP0131_OLD PRIVATE "$<LINK_ONLY:foo_link_only>")
target_compile_definitions(use_foo_link_only_CMP0131_OLD PRIVATE EXPECT_FOO_LINK_ONLY)
cmake_policy(SET CMP0131 NEW)
add_executable(use_foo_link_only_CMP0131_NEW use_foo_link_only.c)
target_link_libraries(use_foo_link_only_CMP0131_NEW PRIVATE "$<LINK_ONLY:foo_link_only>")

View File

@@ -0,0 +1,8 @@
#ifndef FOO_LINK_ONLY
# error "FOO_LINK_ONLY incorrectly not defined"
#endif
int foo_link_only(void)
{
return 0;
}

View File

@@ -0,0 +1,16 @@
#ifdef EXPECT_FOO_LINK_ONLY
# ifndef FOO_LINK_ONLY
# error "FOO_LINK_ONLY incorrectly not defined"
# endif
#else
# ifdef FOO_LINK_ONLY
# error "FOO_LINK_ONLY incorrectly defined"
# endif
#endif
extern int foo_link_only(void);
int main(void)
{
return foo_link_only();
}

View File

@@ -35,6 +35,7 @@
\* CMP0112
\* CMP0113
\* CMP0119
\* CMP0131
Call Stack \(most recent call first\):
CMakeLists.txt:3 \(include\)