mirror of
https://github.com/Kitware/CMake.git
synced 2026-05-12 17:19:05 -05:00
cxxmodules: link to std-providing targets when available
This commit is contained in:
@@ -86,6 +86,12 @@ Compilers which CMake natively supports module dependency scanning include:
|
||||
* LLVM/Clang 16.0 and newer
|
||||
* GCC 14 (for the in-development branch, after 2023-09-20) and newer
|
||||
|
||||
``import std`` Support
|
||||
======================
|
||||
|
||||
Support for ``import std`` is limited to the following toolchain and standard
|
||||
library combinations:
|
||||
|
||||
Generator Support
|
||||
=================
|
||||
|
||||
@@ -116,6 +122,7 @@ For the :ref:`Visual Studio Generators`:
|
||||
- Only Visual Studio 2022 and MSVC toolsets 14.34 (Visual Studio
|
||||
17.4) and newer.
|
||||
- No support for exporting or installing BMI or module information.
|
||||
- No support for compiling BMIs from ``IMPORTED`` targets with C++ modules.
|
||||
- No support for compiling BMIs from ``IMPORTED`` targets with C++ modules
|
||||
(including ``import std``).
|
||||
- No diagnosis of using modules provided by ``PRIVATE`` sources from
|
||||
``PUBLIC`` module sources.
|
||||
|
||||
@@ -8411,6 +8411,106 @@ void ComputeLinkImplTransitive(cmGeneratorTarget const* self,
|
||||
}
|
||||
}
|
||||
|
||||
bool cmGeneratorTarget::ApplyCXXStdTargets()
|
||||
{
|
||||
cmStandardLevelResolver standardResolver(this->Makefile);
|
||||
cmStandardLevel const cxxStd23 =
|
||||
*standardResolver.LanguageStandardLevel("CXX", "23");
|
||||
std::vector<std::string> const& configs =
|
||||
this->Makefile->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig);
|
||||
auto std_prop = this->GetProperty("CXX_MODULE_STD");
|
||||
if (!std_prop) {
|
||||
// TODO(cxxmodules): Add a target policy to flip the default here. Set
|
||||
// `std_prop` based on it.
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string std_prop_value;
|
||||
if (std_prop) {
|
||||
// Evaluate generator expressions.
|
||||
cmGeneratorExpression ge(*this->LocalGenerator->GetCMakeInstance());
|
||||
auto cge = ge.Parse(*std_prop);
|
||||
if (!cge) {
|
||||
this->Makefile->IssueMessage(
|
||||
MessageType::FATAL_ERROR,
|
||||
cmStrCat(R"(The "CXX_MODULE_STD" property on the target ")",
|
||||
this->GetName(), "\" is not a valid generator expression."));
|
||||
return false;
|
||||
}
|
||||
// But do not allow context-sensitive queries. Whether a target uses
|
||||
// `import std` should not depend on configuration or properties of the
|
||||
// consumer (head target). The link language also shouldn't matter, so ban
|
||||
// it as well.
|
||||
if (cge->GetHadHeadSensitiveCondition()) {
|
||||
// Not reachable; all target-sensitive genexes actually fail to parse.
|
||||
this->Makefile->IssueMessage(
|
||||
MessageType::FATAL_ERROR,
|
||||
cmStrCat(R"(The "CXX_MODULE_STD" property on the target ")",
|
||||
this->GetName(),
|
||||
"\" contains a condition that queries the "
|
||||
"consuming target which is not supported."));
|
||||
return false;
|
||||
}
|
||||
if (cge->GetHadLinkLanguageSensitiveCondition()) {
|
||||
// Not reachable; all link language genexes actually fail to parse.
|
||||
this->Makefile->IssueMessage(
|
||||
MessageType::FATAL_ERROR,
|
||||
cmStrCat(R"(The "CXX_MODULE_STD" property on the target ")",
|
||||
this->GetName(),
|
||||
"\" contains a condition that queries the "
|
||||
"link language which is not supported."));
|
||||
return false;
|
||||
}
|
||||
std_prop_value = cge->Evaluate(this->LocalGenerator, "");
|
||||
if (cge->GetHadContextSensitiveCondition()) {
|
||||
this->Makefile->IssueMessage(
|
||||
MessageType::FATAL_ERROR,
|
||||
cmStrCat(R"(The "CXX_MODULE_STD" property on the target ")",
|
||||
this->GetName(),
|
||||
"\" contains a context-sensitive condition "
|
||||
"that is not supported."));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
auto use_std = cmIsOn(std_prop_value);
|
||||
|
||||
// If we have a value and it is not true, there's nothing to do.
|
||||
if (std_prop && !use_std) {
|
||||
return true;
|
||||
}
|
||||
|
||||
for (auto const& config : configs) {
|
||||
if (this->HaveCxxModuleSupport(config) != Cxx20SupportLevel::Supported) {
|
||||
continue;
|
||||
}
|
||||
|
||||
cm::optional<cmStandardLevel> explicitLevel =
|
||||
this->GetExplicitStandardLevel("CXX", config);
|
||||
if (!explicitLevel || *explicitLevel < cxxStd23) {
|
||||
continue;
|
||||
}
|
||||
|
||||
auto const targetName = cmStrCat(
|
||||
"__CMAKE::CXX", standardResolver.GetLevelString("CXX", *explicitLevel));
|
||||
if (!this->Makefile->FindTargetToUse(targetName)) {
|
||||
this->Makefile->IssueMessage(
|
||||
MessageType::FATAL_ERROR,
|
||||
cmStrCat(
|
||||
R"(The "CXX_MODULE_STD" property on the target ")", this->GetName(),
|
||||
"\" requires that the \"", targetName,
|
||||
"\" target exist, but it was not provided by the toolchain."));
|
||||
break;
|
||||
}
|
||||
|
||||
this->Target->AppendProperty(
|
||||
"LINK_LIBRARIES",
|
||||
cmStrCat("$<BUILD_LOCAL_INTERFACE:$<$<CONFIG:", config, ">:", targetName,
|
||||
">>"));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cmGeneratorTarget::DiscoverSyntheticTargets(cmSyntheticTargetCache& cache,
|
||||
std::string const& config)
|
||||
{
|
||||
@@ -8500,6 +8600,9 @@ bool cmGeneratorTarget::DiscoverSyntheticTargets(cmSyntheticTargetCache& cache,
|
||||
for (auto const& innerConfig : allConfigs) {
|
||||
gtp->ComputeCompileFeatures(innerConfig);
|
||||
}
|
||||
// See `cmGlobalGenerator::ApplyCXXStdTargets` in
|
||||
// `cmGlobalGenerator::Compute` for non-synthetic target resolutions.
|
||||
gtp->ApplyCXXStdTargets();
|
||||
|
||||
gtp->DiscoverSyntheticTargets(cache, config);
|
||||
|
||||
|
||||
@@ -961,6 +961,7 @@ public:
|
||||
|
||||
std::string GetImportedXcFrameworkPath(const std::string& config) const;
|
||||
|
||||
bool ApplyCXXStdTargets();
|
||||
bool DiscoverSyntheticTargets(cmSyntheticTargetCache& cache,
|
||||
std::string const& config);
|
||||
|
||||
|
||||
@@ -1594,6 +1594,16 @@ bool cmGlobalGenerator::Compute()
|
||||
}
|
||||
}
|
||||
|
||||
// We now have all targets set up and std levels constructed. Add
|
||||
// `__CMAKE::CXX*` targets as link dependencies to all targets which need
|
||||
// them.
|
||||
//
|
||||
// Synthetic targets performed this inside of
|
||||
// `cmLocalGenerator::DiscoverSyntheticTargets`
|
||||
if (!this->ApplyCXXStdTargets()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Iterate through all targets and set up C++20 module targets.
|
||||
// Create target templates for each imported target with C++20 modules.
|
||||
// INTERFACE library with BMI-generating rules and a collation step?
|
||||
@@ -1830,6 +1840,19 @@ void cmGlobalGenerator::ComputeTargetOrder(cmGeneratorTarget const* gt,
|
||||
entry->second = index++;
|
||||
}
|
||||
|
||||
bool cmGlobalGenerator::ApplyCXXStdTargets()
|
||||
{
|
||||
for (auto const& gen : this->LocalGenerators) {
|
||||
for (auto const& tgt : gen->GetGeneratorTargets()) {
|
||||
if (!tgt->ApplyCXXStdTargets()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cmGlobalGenerator::DiscoverSyntheticTargets()
|
||||
{
|
||||
cmSyntheticTargetCache cache;
|
||||
|
||||
@@ -674,6 +674,7 @@ protected:
|
||||
|
||||
virtual bool CheckALLOW_DUPLICATE_CUSTOM_TARGETS() const;
|
||||
|
||||
bool ApplyCXXStdTargets();
|
||||
bool DiscoverSyntheticTargets();
|
||||
|
||||
bool AddHeaderSetVerification();
|
||||
|
||||
Reference in New Issue
Block a user