mirror of
https://gitlab.kitware.com/cmake/cmake.git
synced 2026-09-25 04:09:36 +03:00
find_package: Share package information among copies of package stack
Since commitae373e93fb(install(PACKAGE_INFO): Add version and location to package dependencies, 2025-07-31, v4.2.0-rc1~340^2) we add package information to the current package's stack entry as it is discovered. However, a nested package can cause the current package's stack entry to be replaced by a copy with a new ordering index due to commitc6e6861e63(install(EXPORT): Export find_dependency() calls, 2023-11-07, v3.29.0-rc1~439^2~1). Depending on whether imported targets were created by the current package before finding the nested package, the `CurrentPackageInfo` pointer is either invalidated, or left pointing at only one of multiple copies. Fix this by sharing a single instance of package information with all copies of the current package's stack entry. Keep a mutable pointer to the current package's information only while it is still pending. This also avoids the need to expose mutation from the package stack. Add a test that exposes the previously-invalidated pointer to dynamic analysis tools. Fixes: #27730
This commit is contained in:
@@ -298,7 +298,8 @@ bool cmExportPackageInfoGenerator::NoteLinkedTarget(
|
|||||||
auto pkgInfo = [](cmTarget* t) -> Package {
|
auto pkgInfo = [](cmTarget* t) -> Package {
|
||||||
cmFindPackageStack pkgStack = t->GetFindPackageStack();
|
cmFindPackageStack pkgStack = t->GetFindPackageStack();
|
||||||
if (!pkgStack.Empty()) {
|
if (!pkgStack.Empty()) {
|
||||||
return std::make_pair(pkgStack.Top().Name, pkgStack.Top().PackageInfo);
|
return std::make_pair(pkgStack.Top().Name,
|
||||||
|
*pkgStack.Top().PackageInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
cmPackageInformation package;
|
cmPackageInformation package;
|
||||||
|
|||||||
@@ -1218,13 +1218,15 @@ bool cmFindPackageCommand::FindPackage(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Record package information discovered while it is loaded.
|
||||||
|
this->PackageInfo = std::make_shared<cmPackageInformation>();
|
||||||
|
|
||||||
// RAII objects to ensure we leave this function with consistent state.
|
// RAII objects to ensure we leave this function with consistent state.
|
||||||
FlushDebugBufferOnExit flushDebugBufferOnExit(*this);
|
FlushDebugBufferOnExit flushDebugBufferOnExit(*this);
|
||||||
PushPopRootPathStack pushPopRootPathStack(*this);
|
PushPopRootPathStack pushPopRootPathStack(*this);
|
||||||
SetRestoreFindDefinitions setRestoreFindDefinitions(*this);
|
SetRestoreFindDefinitions setRestoreFindDefinitions(*this);
|
||||||
cmFindPackageStackRAII findPackageStackRAII(this->Makefile, this->Name);
|
cmFindPackageStackRAII findPackageStackRAII(this->Makefile, this->Name,
|
||||||
|
this->PackageInfo);
|
||||||
findPackageStackRAII.BindTop(this->CurrentPackageInfo);
|
|
||||||
|
|
||||||
// See if we have been told to delegate to FetchContent or some other
|
// See if we have been told to delegate to FetchContent or some other
|
||||||
// redirected config package first. We have to check all names that
|
// redirected config package first. We have to check all names that
|
||||||
@@ -1272,8 +1274,8 @@ bool cmFindPackageCommand::FindPackage(
|
|||||||
this->Names.clear();
|
this->Names.clear();
|
||||||
this->Names.emplace_back(overrideName); // Force finding this one
|
this->Names.emplace_back(overrideName); // Force finding this one
|
||||||
this->Variable = cmStrCat(this->Name, "_DIR");
|
this->Variable = cmStrCat(this->Name, "_DIR");
|
||||||
this->CurrentPackageInfo->Directory = redirectsDir;
|
this->PackageInfo->Directory = redirectsDir;
|
||||||
this->CurrentPackageInfo->Version = this->VersionFound;
|
this->PackageInfo->Version = this->VersionFound;
|
||||||
this->SetConfigDirCacheVariable(redirectsDir);
|
this->SetConfigDirCacheVariable(redirectsDir);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -1734,9 +1736,9 @@ bool cmFindPackageCommand::HandlePackageMode(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (this->UseConfigFiles && found) {
|
if (this->UseConfigFiles && found) {
|
||||||
this->CurrentPackageInfo->Directory =
|
this->PackageInfo->Directory =
|
||||||
cmSystemTools::GetFilenamePath(this->FileFound);
|
cmSystemTools::GetFilenamePath(this->FileFound);
|
||||||
this->CurrentPackageInfo->Version = this->VersionFound;
|
this->PackageInfo->Version = this->VersionFound;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -285,7 +285,7 @@ private:
|
|||||||
std::set<std::string> OptionalComponents;
|
std::set<std::string> OptionalComponents;
|
||||||
std::set<std::string> RequiredTargets;
|
std::set<std::string> RequiredTargets;
|
||||||
std::string DebugBuffer;
|
std::string DebugBuffer;
|
||||||
cmPackageInformation* CurrentPackageInfo;
|
std::shared_ptr<cmPackageInformation> PackageInfo;
|
||||||
|
|
||||||
enum class SearchResult
|
enum class SearchResult
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ class cmFindPackageCall
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
std::string const Name;
|
std::string const Name;
|
||||||
cmPackageInformation PackageInfo;
|
std::shared_ptr<cmPackageInformation const> PackageInfo;
|
||||||
unsigned int Index;
|
unsigned int Index;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -50,19 +50,14 @@ public:
|
|||||||
class cmFindPackageStackRAII
|
class cmFindPackageStackRAII
|
||||||
{
|
{
|
||||||
cmMakefile* Makefile;
|
cmMakefile* Makefile;
|
||||||
cmPackageInformation** Value = nullptr;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
cmFindPackageStackRAII(cmMakefile* mf, std::string const& pkg);
|
cmFindPackageStackRAII(cmMakefile* mf, std::string const& pkg,
|
||||||
|
std::shared_ptr<cmPackageInformation const> pkgInfo);
|
||||||
~cmFindPackageStackRAII();
|
~cmFindPackageStackRAII();
|
||||||
|
|
||||||
cmFindPackageStackRAII(cmFindPackageStackRAII const&) = delete;
|
cmFindPackageStackRAII(cmFindPackageStackRAII const&) = delete;
|
||||||
cmFindPackageStackRAII& operator=(cmFindPackageStackRAII const&) = delete;
|
cmFindPackageStackRAII& operator=(cmFindPackageStackRAII const&) = delete;
|
||||||
|
|
||||||
/** Get a mutable pointer to the top of the stack.
|
|
||||||
The pointer is invalidated if BindTop is called again or when the
|
|
||||||
cmFindPackageStackRAII goes out of scope. */
|
|
||||||
void BindTop(cmPackageInformation*& value);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+4
-17
@@ -51,7 +51,6 @@
|
|||||||
#include "cmSourceFile.h"
|
#include "cmSourceFile.h"
|
||||||
#include "cmSourceFileLocation.h"
|
#include "cmSourceFileLocation.h"
|
||||||
#include "cmSourceGroup.h"
|
#include "cmSourceGroup.h"
|
||||||
#include "cmStack.h"
|
|
||||||
#include "cmState.h"
|
#include "cmState.h"
|
||||||
#include "cmStateDirectory.h"
|
#include "cmStateDirectory.h"
|
||||||
#include "cmStateTypes.h"
|
#include "cmStateTypes.h"
|
||||||
@@ -4242,34 +4241,22 @@ cmMakefile::MacroPushPop::~MacroPushPop()
|
|||||||
this->Makefile->PopMacroScope(this->ReportError);
|
this->Makefile->PopMacroScope(this->ReportError);
|
||||||
}
|
}
|
||||||
|
|
||||||
cmFindPackageStackRAII::cmFindPackageStackRAII(cmMakefile* mf,
|
cmFindPackageStackRAII::cmFindPackageStackRAII(
|
||||||
std::string const& name)
|
cmMakefile* mf, std::string const& name,
|
||||||
|
std::shared_ptr<cmPackageInformation const> pkgInfo)
|
||||||
: Makefile(mf)
|
: Makefile(mf)
|
||||||
{
|
{
|
||||||
this->Makefile->FindPackageStack =
|
this->Makefile->FindPackageStack =
|
||||||
this->Makefile->FindPackageStack.Push(cmFindPackageCall{
|
this->Makefile->FindPackageStack.Push(cmFindPackageCall{
|
||||||
name,
|
name,
|
||||||
cmPackageInformation(),
|
std::move(pkgInfo),
|
||||||
this->Makefile->FindPackageStackNextIndex,
|
this->Makefile->FindPackageStackNextIndex,
|
||||||
});
|
});
|
||||||
this->Makefile->FindPackageStackNextIndex++;
|
this->Makefile->FindPackageStackNextIndex++;
|
||||||
}
|
}
|
||||||
|
|
||||||
void cmFindPackageStackRAII::BindTop(cmPackageInformation*& value)
|
|
||||||
{
|
|
||||||
if (this->Value) {
|
|
||||||
*this->Value = nullptr;
|
|
||||||
}
|
|
||||||
this->Value = &value;
|
|
||||||
value = &this->Makefile->FindPackageStack.cmStack::Top().PackageInfo;
|
|
||||||
}
|
|
||||||
|
|
||||||
cmFindPackageStackRAII::~cmFindPackageStackRAII()
|
cmFindPackageStackRAII::~cmFindPackageStackRAII()
|
||||||
{
|
{
|
||||||
if (this->Value) {
|
|
||||||
*this->Value = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
this->Makefile->FindPackageStackNextIndex =
|
this->Makefile->FindPackageStackNextIndex =
|
||||||
this->Makefile->FindPackageStack.Top().Index + 1;
|
this->Makefile->FindPackageStack.Top().Index + 1;
|
||||||
this->Makefile->FindPackageStack = this->Makefile->FindPackageStack.Pop();
|
this->Makefile->FindPackageStack = this->Makefile->FindPackageStack.Pop();
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
cmake_policy(SET CMP0074 NEW)
|
||||||
|
set(Outer_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/NestedConfig)
|
||||||
|
find_package(Outer CONFIG)
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
find_package(Inner CONFIG NO_DEFAULT_PATH)
|
||||||
@@ -36,6 +36,7 @@ run_cmake(MissingConfigRequired)
|
|||||||
run_cmake(MissingConfigVersion)
|
run_cmake(MissingConfigVersion)
|
||||||
run_cmake(MixedModeOptions)
|
run_cmake(MixedModeOptions)
|
||||||
run_cmake_with_options(ModuleModeDebugPkg --debug-find-pkg=Foo,Zot)
|
run_cmake_with_options(ModuleModeDebugPkg --debug-find-pkg=Foo,Zot)
|
||||||
|
run_cmake(NestedConfig)
|
||||||
run_cmake(PackageRoot)
|
run_cmake(PackageRoot)
|
||||||
run_cmake(PackageRootNestedConfig)
|
run_cmake(PackageRootNestedConfig)
|
||||||
run_cmake(PackageRootNestedModule)
|
run_cmake(PackageRootNestedModule)
|
||||||
|
|||||||
Reference in New Issue
Block a user