diff options
author | Brad King <brad.king@kitware.com> | 2024-04-15 13:56:40 (GMT) |
---|---|---|
committer | Kitware Robot <kwrobot@kitware.com> | 2024-04-15 13:56:53 (GMT) |
commit | ca449572ef8b1c6066e88879795900aea9727834 (patch) | |
tree | b7f4f67018d8fead9292e9d0133fa02e22879918 /Source/cmGeneratorTarget.cxx | |
parent | abd572de909de2f30ca93e3b1cca1311e33c4f75 (diff) | |
parent | 429902ebad620c877b869068583d2a32bb6197b4 (diff) | |
download | CMake-ca449572ef8b1c6066e88879795900aea9727834.zip CMake-ca449572ef8b1c6066e88879795900aea9727834.tar.gz CMake-ca449572ef8b1c6066e88879795900aea9727834.tar.bz2 |
Merge topic 'cxxmodules-import-std'
429902ebad Clang: support creating a target for imported modules
4617f272b4 MSVC: support `import std`
62a71047bb cmGraphVizWriter: ignore `__cmake_`-prefixed targets
442086c1dc fileapi: ignore `__cmake_`-prefixed targets
ffe74289b3 CMakeDetermineCompilerId: extract C++ standard library impl
15bbd1d9b8 Experimental: add an experimental feature gate for `import std`
f80c60df02 CMakeDetermineCompilerSupport: construct C++ modules targets
19341e2582 ci: enable `import_std23` C++ module tests on MSVC
...
Acked-by: Kitware Robot <kwrobot@kitware.com>
Tested-by: buildbot <buildbot@kitware.com>
Merge-request: !9337
Diffstat (limited to 'Source/cmGeneratorTarget.cxx')
-rw-r--r-- | Source/cmGeneratorTarget.cxx | 124 |
1 files changed, 124 insertions, 0 deletions
diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index 2ec1a29..be82099 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -32,6 +32,7 @@ #include "cmCustomCommandGenerator.h" #include "cmCxxModuleUsageEffects.h" #include "cmEvaluatedTargetProperty.h" +#include "cmExperimental.h" #include "cmFileSet.h" #include "cmFileTimes.h" #include "cmGeneratedFileStream.h" @@ -8411,9 +8412,119 @@ 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; + } + + // Check the experimental feature here as well. A toolchain may have + // provided the target and skipped the check in the toolchain preparation + // logic. + if (!cmExperimental::HasSupportEnabled( + *this->Makefile, cmExperimental::Feature::CxxImportStd)) { + break; + } + + this->Target->AppendProperty( + "LINK_LIBRARIES", + cmStrCat("$<BUILD_LOCAL_INTERFACE:$<$<CONFIG:", config, ">:", targetName, + ">>")); + } + + return true; +} + bool cmGeneratorTarget::DiscoverSyntheticTargets(cmSyntheticTargetCache& cache, std::string const& config) { + std::vector<std::string> allConfigs = + this->Makefile->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig); cmOptionalLinkImplementation impl; this->ComputeLinkImplementationLibraries(config, impl, this, LinkInterfaceFor::Link); @@ -8488,9 +8599,22 @@ bool cmGeneratorTarget::DiscoverSyntheticTargets(cmSyntheticTargetCache& cache, // Create the generator target and attach it to the local generator. auto gtp = cm::make_unique<cmGeneratorTarget>(tgt, lg); + synthDep = gtp.get(); cache.CxxModuleTargets[targetName] = synthDep; + + // See `localGen->ComputeTargetCompileFeatures()` call in + // `cmGlobalGenerator::Compute` for where non-synthetic targets resolve + // this. + 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); + lg->AddGeneratorTarget(std::move(gtp)); } else { synthDep = cached->second; |