From e0bbe79ceabb82b3ff0f28ab227c58db2489101b Mon Sep 17 00:00:00 2001 From: Brad King Date: Mon, 29 Sep 2025 09:48:50 -0400 Subject: [PATCH] CMP0189: Restore support for linking `$` In general we disallow references to transitive target properties, such as `COMPILE_DEFINITIONS`, in `[INTERFACE_]LINK_LIBRARIES` properties, because the latter establish the transitivity itself. Prior to CMP0189, the `[INTERFACE_]LINK_LIBRARIES` properties were not themselves transitive in `$` expressions, so existing projects have code like target_link_libraries(foo PRIVATE "$") Policy CMP0189's NEW behavior, introduced by commit b3da9c6d60 (GenEx: Evaluate LINK_LIBRARIES target properties transitively, 2025-02-24, v4.1.0-rc1~731^2), makes `$` transitive, causing the above to be rejected. Since evaluation of a target's link libraries can already encounter and handle other targets' link libraries, allow it in this case. Fixes: #27265 --- Source/cmGeneratorExpressionNode.cxx | 3 ++- .../LinkLikewise-CMP0189-NEW.cmake | 5 +++++ .../LinkLikewise-CMP0189-OLD.cmake | 2 ++ .../GenEx-TARGET_PROPERTY/LinkLikewise-common.cmake | 12 ++++++++++++ .../RunCMake/GenEx-TARGET_PROPERTY/LinkLikewiseLib.c | 4 ++++ .../GenEx-TARGET_PROPERTY/LinkLikewiseMain.c | 5 +++++ .../GenEx-TARGET_PROPERTY/RunCMakeTest.cmake | 9 +++++++++ 7 files changed, 39 insertions(+), 1 deletion(-) create mode 100644 Tests/RunCMake/GenEx-TARGET_PROPERTY/LinkLikewise-CMP0189-NEW.cmake create mode 100644 Tests/RunCMake/GenEx-TARGET_PROPERTY/LinkLikewise-CMP0189-OLD.cmake create mode 100644 Tests/RunCMake/GenEx-TARGET_PROPERTY/LinkLikewise-common.cmake create mode 100644 Tests/RunCMake/GenEx-TARGET_PROPERTY/LinkLikewiseLib.c create mode 100644 Tests/RunCMake/GenEx-TARGET_PROPERTY/LinkLikewiseMain.c diff --git a/Source/cmGeneratorExpressionNode.cxx b/Source/cmGeneratorExpressionNode.cxx index 98f8c72639..082fd3d462 100644 --- a/Source/cmGeneratorExpressionNode.cxx +++ b/Source/cmGeneratorExpressionNode.cxx @@ -2903,7 +2903,8 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode dagCheckerParent->EvaluatingLinkerLauncher()) { // No check required. } else if (evaluatingLinkLibraries) { - if (!interfacePropertyName.empty()) { + if (!interfacePropertyName.empty() && + interfacePropertyName != "INTERFACE_LINK_LIBRARIES"_s) { reportError( eval, content->GetOriginalExpression(), "$ expression in link libraries " diff --git a/Tests/RunCMake/GenEx-TARGET_PROPERTY/LinkLikewise-CMP0189-NEW.cmake b/Tests/RunCMake/GenEx-TARGET_PROPERTY/LinkLikewise-CMP0189-NEW.cmake new file mode 100644 index 0000000000..d8fa95db2f --- /dev/null +++ b/Tests/RunCMake/GenEx-TARGET_PROPERTY/LinkLikewise-CMP0189-NEW.cmake @@ -0,0 +1,5 @@ +cmake_policy(SET CMP0189 NEW) +include(LinkLikewise-common.cmake) + +# Test that CMP0189 NEW tolerates circular LINK_LIBRARIES references. +target_link_libraries(main1 PRIVATE "$") diff --git a/Tests/RunCMake/GenEx-TARGET_PROPERTY/LinkLikewise-CMP0189-OLD.cmake b/Tests/RunCMake/GenEx-TARGET_PROPERTY/LinkLikewise-CMP0189-OLD.cmake new file mode 100644 index 0000000000..ed587e5d60 --- /dev/null +++ b/Tests/RunCMake/GenEx-TARGET_PROPERTY/LinkLikewise-CMP0189-OLD.cmake @@ -0,0 +1,2 @@ +cmake_policy(SET CMP0189 OLD) +include(LinkLikewise-common.cmake) diff --git a/Tests/RunCMake/GenEx-TARGET_PROPERTY/LinkLikewise-common.cmake b/Tests/RunCMake/GenEx-TARGET_PROPERTY/LinkLikewise-common.cmake new file mode 100644 index 0000000000..b7d3405adc --- /dev/null +++ b/Tests/RunCMake/GenEx-TARGET_PROPERTY/LinkLikewise-common.cmake @@ -0,0 +1,12 @@ +enable_language(C) + +add_library(foo STATIC LinkLikewiseLib.c) + +add_executable(main1 LinkLikewiseMain.c) +add_executable(main2 LinkLikewiseMain.c) + +# main1 depends on foo. +target_link_libraries(main1 PRIVATE foo) + +# main2 depends on foo, but express it by referencing main1's dependency. +target_link_libraries(main2 PRIVATE "$") diff --git a/Tests/RunCMake/GenEx-TARGET_PROPERTY/LinkLikewiseLib.c b/Tests/RunCMake/GenEx-TARGET_PROPERTY/LinkLikewiseLib.c new file mode 100644 index 0000000000..ff1c2eb1f3 --- /dev/null +++ b/Tests/RunCMake/GenEx-TARGET_PROPERTY/LinkLikewiseLib.c @@ -0,0 +1,4 @@ +int LinkLikewiseLib(void) +{ + return 0; +} diff --git a/Tests/RunCMake/GenEx-TARGET_PROPERTY/LinkLikewiseMain.c b/Tests/RunCMake/GenEx-TARGET_PROPERTY/LinkLikewiseMain.c new file mode 100644 index 0000000000..f4f862806c --- /dev/null +++ b/Tests/RunCMake/GenEx-TARGET_PROPERTY/LinkLikewiseMain.c @@ -0,0 +1,5 @@ +extern int LinkLikewiseLib(void); +int main(void) +{ + return LinkLikewiseLib(); +} diff --git a/Tests/RunCMake/GenEx-TARGET_PROPERTY/RunCMakeTest.cmake b/Tests/RunCMake/GenEx-TARGET_PROPERTY/RunCMakeTest.cmake index d877c52105..7471b65f9f 100644 --- a/Tests/RunCMake/GenEx-TARGET_PROPERTY/RunCMakeTest.cmake +++ b/Tests/RunCMake/GenEx-TARGET_PROPERTY/RunCMakeTest.cmake @@ -17,6 +17,15 @@ run_cmake(TransitiveLink-CMP0166-OLD) run_cmake(TransitiveLink-CMP0166-NEW) run_cmake(Unset) +function(run_LinkLikewise case) + run_cmake(LinkLikewise-${case}) + set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/LinkLikewise-${case}-build) + set(RunCMake_TEST_NO_CLEAN 1) + run_cmake_command(LinkLikewise-${case}-build ${CMAKE_COMMAND} --build . --config Debug) +endfunction() +run_LinkLikewise(CMP0189-OLD) +run_LinkLikewise(CMP0189-NEW) + block() run_cmake(Scope) set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/Scope-build)