mirror of
https://github.com/Kitware/CMake.git
synced 2026-11-06 05:16:58 +00:00
Genex: Diagnose cyclic link information
A generator expression such as `$<TARGET_RUNTIME_DLLS:tgt>` reachable from the link closure of `tgt` causes a nested re-entry into `GetLinkInformation`. This computation runs over a partially computed link implementation and leads to bogus generation errors or a crash. Reserve the cache entry before computing, and error out when the computation is re-entered.
This commit is contained in:
1 parent
cda028d08c
commit
2ac0d35159
6 files changed
+43
-2
No files matched your search
@@ -1302,6 +1302,7 @@ private:
|
||||
using cmTargetLinkInformationMap =
|
||||
std::map<std::string, std::unique_ptr<cmComputeLinkInformation>>;
|
||||
mutable cmTargetLinkInformationMap LinkInformation;
|
||||
mutable std::set<std::string> LinkInformationInProgress;
|
||||
|
||||
void CheckPropertyCompatibility(cmComputeLinkInformation& info,
|
||||
std::string const& config) const;
|
||||
|
||||
@@ -347,7 +347,21 @@ cmComputeLinkInformation* cmGeneratorTarget::GetLinkInformation(
|
||||
// Lookup any existing information for this configuration.
|
||||
std::string key(cmSystemTools::UpperCase(config));
|
||||
auto i = this->LinkInformation.find(key);
|
||||
if (i == this->LinkInformation.end()) {
|
||||
if (i != this->LinkInformation.end()) {
|
||||
if (cm::contains(this->LinkInformationInProgress, key)) {
|
||||
this->GlobalGenerator->GetCMakeInstance()->IssueMessage(
|
||||
MessageType::FATAL_ERROR,
|
||||
cmStrCat("The link dependencies of \"", this->GetName(),
|
||||
"\" use a generator expression that depends on the link "
|
||||
"dependencies themselves."),
|
||||
this->GetBacktrace());
|
||||
}
|
||||
} else {
|
||||
// Reserve the entry so that a recursive lookup while computing the
|
||||
// information is diagnosed instead of re-entering the computation.
|
||||
i = this->LinkInformation.emplace(key, nullptr).first;
|
||||
this->LinkInformationInProgress.insert(key);
|
||||
|
||||
// Compute information for this configuration.
|
||||
auto info = cm::make_unique<cmComputeLinkInformation>(this, config);
|
||||
if (info && !info->Compute()) {
|
||||
@@ -355,7 +369,8 @@ cmComputeLinkInformation* cmGeneratorTarget::GetLinkInformation(
|
||||
}
|
||||
|
||||
// Store the information for this configuration.
|
||||
i = this->LinkInformation.emplace(key, std::move(info)).first;
|
||||
this->LinkInformationInProgress.erase(key);
|
||||
i->second = std::move(info);
|
||||
|
||||
if (i->second) {
|
||||
this->CheckPropertyCompatibility(*i->second, config);
|
||||
|
||||
@@ -5,3 +5,4 @@ run_cmake(static)
|
||||
run_cmake(target_link_libraries)
|
||||
run_cmake(target_link_libraries-cycle1)
|
||||
run_cmake(target_link_libraries-cycle2)
|
||||
run_cmake(target_link_libraries-cycle3)
|
||||
@@ -0,0 +1 @@
|
||||
1
|
||||
@@ -0,0 +1,5 @@
|
||||
CMake Error at target_link_libraries-cycle3\.cmake:[0-9]+ \(add_library\):
|
||||
The link dependencies of "lib1" use a generator expression that depends on
|
||||
the link dependencies themselves\.
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists\.txt:[0-9]+ \(include\)
|
||||
@@ -0,0 +1,18 @@
|
||||
enable_language(C)
|
||||
|
||||
# lib1 -> lib2 -> static -> iface -> $<TARGET_RUNTIME_DLLS:lib1>
|
||||
add_library(lib1 SHARED lib1.c)
|
||||
add_library(lib2 SHARED lib2.c)
|
||||
add_library(static STATIC static.c)
|
||||
add_library(iface INTERFACE)
|
||||
set_target_properties(iface PROPERTIES
|
||||
COMPATIBLE_INTERFACE_BOOL FOO
|
||||
INTERFACE_FOO ON
|
||||
)
|
||||
target_link_libraries(iface INTERFACE $<TARGET_RUNTIME_DLLS:lib1>)
|
||||
target_link_libraries(static PUBLIC iface)
|
||||
target_link_libraries(lib2 PUBLIC static)
|
||||
target_link_libraries(lib1 PRIVATE lib2)
|
||||
|
||||
# Evaluate the link interface before the sources of lib1 are computed.
|
||||
file(GENERATE OUTPUT "out-$<TARGET_PROPERTY:lib1,FOO>.txt" CONTENT "")
|
||||
Reference in new issue
Block a user