Files
CMake/Source/cmFindPackageStack.h
Brad King aae02ee60a find_package: Share package information among copies of package stack
Since commit ae373e93fb (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 commit c6e6861e63
(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
2026-04-01 13:53:07 -04:00

56 lines
1.4 KiB
C++

/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file LICENSE.rst or https://cmake.org/licensing for details. */
#pragma once
#include "cmConfigure.h" // IWYU pragma: keep
#include <memory>
#include <set>
#include <string>
#include <cm/optional>
#include "cmConstStack.h"
/**
* This data represents the actual contents of find_package
* <PACKAGE>-Config.cmake or <PACKAGE>.cps file, and not what is passed
* to the find_package command. They can be the same, but it is not guaranteed.
*/
class cmPackageInformation
{
public:
cm::optional<std::string> Directory;
cm::optional<std::string> Version;
cm::optional<std::string> Description;
cm::optional<std::string> License;
cm::optional<std::string> Website;
cm::optional<std::string> PackageUrl;
std::set<std::string> Components;
};
/**
* Represents one call to find_package.
*/
class cmFindPackageCall
{
public:
std::string const Name;
std::shared_ptr<cmPackageInformation const> PackageInfo;
unsigned int Index;
};
/**
* Represents a stack of find_package calls with efficient value semantics.
*/
class cmFindPackageStack
: public cmConstStack<cmFindPackageCall, cmFindPackageStack>
{
using cmConstStack::cmConstStack;
friend class cmConstStack<cmFindPackageCall, cmFindPackageStack>;
};
#ifndef cmFindPackageStack_cxx
extern template class cmConstStack<cmFindPackageCall, cmFindPackageStack>;
#endif