From add64399c54859d26f9954fb06d616dbd00bffe7 Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 16 Mar 2022 09:15:37 -0400 Subject: target_link_libraries: Restore LINK_ONLY for multiple static lib dependencies Since commit c1e812ad4f (target_link_libraries: Improve tolerance of unquoted generator expressions, 2022-02-15, v3.23.0-rc2~11^2) we accumulate consecutive non-keyword arguments to recover an unquoted generator expression as a single entry. When given multiple consecutive non-genex library names, the grouping breaks our logic that expects each entry is either a raw target name or a genex. Revise the logic to only accumulate multiple arguments when they end inside a partial genex. This bug caused `target_link_libraries` to stop wrapping static library private dependencies in `$` for `INTERFACE_LINK_LIBRARIES` when multiple consecutive library names are given. Add a test case covering that behavior. Fixes: #23302 --- Source/cmTargetLinkLibrariesCommand.cxx | 29 ++++++++++++++++++++-- .../target_link_libraries/cmp0022/CMakeLists.txt | 16 ++++++++++++ .../target_link_libraries/cmp0022/staticlib1.cpp | 6 +++++ .../target_link_libraries/cmp0022/staticlib2.cpp | 6 +++++ 4 files changed, 55 insertions(+), 2 deletions(-) diff --git a/Source/cmTargetLinkLibrariesCommand.cxx b/Source/cmTargetLinkLibrariesCommand.cxx index 94fcdd9..e10d0b5 100644 --- a/Source/cmTargetLinkLibrariesCommand.cxx +++ b/Source/cmTargetLinkLibrariesCommand.cxx @@ -9,6 +9,7 @@ #include #include +#include #include "cmExecutionStatus.h" #include "cmGeneratorExpression.h" @@ -183,8 +184,11 @@ bool cmTargetLinkLibrariesCommand(std::vector const& args, // Accumulate consectuive non-keyword arguments into one entry in // order to handle unquoted generator expressions containing ';'. + std::size_t genexNesting = 0; cm::optional currentEntry; auto processCurrentEntry = [&]() -> bool { + // FIXME: Warn about partial genex if genexNesting > 0? + genexNesting = 0; if (currentEntry) { assert(!haveLLT); if (!tll.HandleLibrary(currentProcessingState, *currentEntry, @@ -220,7 +224,7 @@ bool cmTargetLinkLibrariesCommand(std::vector const& args, // of debug and optimized that can be used. for (unsigned int i = 1; i < args.size(); ++i) { if (keywords.count(args[i])) { - // A keyword argument terminates any preceding accumulated entry. + // A keyword argument terminates any accumulated partial genex. if (!processCurrentEntry()) { return false; } @@ -321,12 +325,33 @@ bool cmTargetLinkLibrariesCommand(std::vector const& args, } llt = GENERAL_LibraryType; } else { + // Track the genex nesting level. + { + cm::string_view arg = args[i]; + for (std::string::size_type pos = 0; pos < arg.size(); ++pos) { + cm::string_view cur = arg.substr(pos); + if (cmHasLiteralPrefix(cur, "$<")) { + ++genexNesting; + ++pos; + } else if (genexNesting > 0 && cmHasLiteralPrefix(cur, ">")) { + --genexNesting; + } + } + } + // Accumulate this argument in the current entry. extendCurrentEntry(args[i]); + + // Process this entry if it does not end inside a genex. + if (genexNesting == 0) { + if (!processCurrentEntry()) { + return false; + } + } } } - // Process the last accumulated entry, if any. + // Process the last accumulated partial genex, if any. if (!processCurrentEntry()) { return false; } diff --git a/Tests/CMakeCommands/target_link_libraries/cmp0022/CMakeLists.txt b/Tests/CMakeCommands/target_link_libraries/cmp0022/CMakeLists.txt index ca6309b..ebade02 100644 --- a/Tests/CMakeCommands/target_link_libraries/cmp0022/CMakeLists.txt +++ b/Tests/CMakeCommands/target_link_libraries/cmp0022/CMakeLists.txt @@ -33,6 +33,22 @@ add_library(staticlib2 STATIC staticlib2.cpp) generate_export_header(staticlib2) target_link_libraries(staticlib1 LINK_PUBLIC staticlib2) +# Test adding LINK_ONLY to each of multiple specified libraries. +add_library(staticlib2iface1 INTERFACE) +add_library(staticlib2iface2 INTERFACE) +target_compile_definitions(staticlib2iface1 INTERFACE STATICLIB2_IFACE_1) +target_compile_definitions(staticlib2iface2 INTERFACE STATICLIB2_IFACE_2) +target_link_libraries(staticlib2 PRIVATE staticlib2iface1 staticlib2iface2) + +# Test adding unquoted genex with ';' to LINK_LIBRARIES and INTERFACE_LINK_LIBRARIES. +target_link_libraries(staticlib2 + PUBLIC $<0:imp::missing1;imp::missing2> + PRIVATE $<0:imp::missing3;imp::missing4> + INTERFACE $<0:imp::missing5;imp::missing6> + ) +assert_property(staticlib2 INTERFACE_LINK_LIBRARIES "$;$;$<0:imp::missing1;imp::missing2>;$>;$<0:imp::missing5;imp::missing6>") +assert_property(staticlib2 LINK_LIBRARIES "staticlib2iface1;staticlib2iface2;$<0:imp::missing1;imp::missing2>;$<0:imp::missing3;imp::missing4>") + # Try adding a private link item to be propagated out of a static lib. set(private_link "") if (CMAKE_CXX_COMPILER_ID MATCHES GNU OR CMAKE_CXX_COMPILER_ID MATCHES Clang OR CMAKE_CXX_COMPILER_ID MATCHES LCC) diff --git a/Tests/CMakeCommands/target_link_libraries/cmp0022/staticlib1.cpp b/Tests/CMakeCommands/target_link_libraries/cmp0022/staticlib1.cpp index d6b3986..d7f3e7c 100644 --- a/Tests/CMakeCommands/target_link_libraries/cmp0022/staticlib1.cpp +++ b/Tests/CMakeCommands/target_link_libraries/cmp0022/staticlib1.cpp @@ -1,3 +1,9 @@ +#ifdef STATICLIB2_IFACE_1 +# error "STATICLIB2_IFACE_1 incorrectly defined" +#endif +#ifdef STATICLIB2_IFACE_2 +# error "STATICLIB2_IFACE_2 incorrectly defined" +#endif int staticlib1() { diff --git a/Tests/CMakeCommands/target_link_libraries/cmp0022/staticlib2.cpp b/Tests/CMakeCommands/target_link_libraries/cmp0022/staticlib2.cpp index bd1a901..caa4143 100644 --- a/Tests/CMakeCommands/target_link_libraries/cmp0022/staticlib2.cpp +++ b/Tests/CMakeCommands/target_link_libraries/cmp0022/staticlib2.cpp @@ -1,3 +1,9 @@ +#ifndef STATICLIB2_IFACE_1 +# error "STATICLIB2_IFACE_1 incorrectly not defined" +#endif +#ifndef STATICLIB2_IFACE_2 +# error "STATICLIB2_IFACE_2 incorrectly not defined" +#endif int staticlib2() { -- cgit v0.12