mirror of
https://github.com/Kitware/CMake.git
synced 2025-10-16 22:37:30 +08:00
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 `$<LINK_ONLY:...>` for `INTERFACE_LINK_LIBRARIES`
when multiple consecutive library names are given. Add a test case
covering that behavior.
Fixes: #23302
This commit is contained in:
@@ -9,6 +9,7 @@
|
||||
#include <utility>
|
||||
|
||||
#include <cm/optional>
|
||||
#include <cm/string_view>
|
||||
|
||||
#include "cmExecutionStatus.h"
|
||||
#include "cmGeneratorExpression.h"
|
||||
@@ -183,8 +184,11 @@ bool cmTargetLinkLibrariesCommand(std::vector<std::string> 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<std::string> 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<std::string> 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<std::string> 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;
|
||||
}
|
||||
|
@@ -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 "$<LINK_ONLY:staticlib2iface1>;$<LINK_ONLY:staticlib2iface2>;$<0:imp::missing1;imp::missing2>;$<LINK_ONLY:$<0:imp::missing3;imp::missing4>>;$<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)
|
||||
|
@@ -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()
|
||||
{
|
||||
|
@@ -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()
|
||||
{
|
||||
|
Reference in New Issue
Block a user