Merge topic 'import-std-refactor'

ab1bd6f6c6 c++modules: Remove CXX_MODULE_STD and CMAKE_CXX_COMPILER_IMPORT_STD
00d8e23414 c++modules: use synthetic interface objects for import std

Acked-by: Kitware Robot <kwrobot@kitware.com>
Merge-request: !12347
This commit is contained in:
Brad King
2026-08-03 10:18:23 -04:00
committed by Kitware Robot
75 changed files with 675 additions and 430 deletions
+2 -6
View File
@@ -66,7 +66,7 @@ In order to activate support for ``import std`` in C++23 and newer targets,
set
* variable ``CMAKE_EXPERIMENTAL_CXX_IMPORT_STD`` to
* value ``f35a9ac6-8463-4d38-8eec-5d6008153e7d``.
* value ``25d6f6aa-be65-4692-b44e-87b23e96d4e1``.
This UUID may change in future versions of CMake. Be sure to use the value
documented here by the source tree of the version of CMake with which you are
@@ -75,11 +75,7 @@ CMake, usually as part of a ``project()`` call.
When activated, this experimental feature provides the following:
* The ``CXX_MODULE_STD`` target property and its initializing variable
``CMAKE_CXX_MODULE_STD``.
* Targets with the property set to a true value and at least ``cxx_std_23``
may use ``import std;`` in any scanned C++ source file.
* Targets may use ``import std;`` in any scanned C++ source file.
Build database support
======================
+7 -6
View File
@@ -91,7 +91,8 @@ library combinations:
* Clang 18.1.2 and newer with standard library ``libc++`` or ``libstdc++``
* MSVC toolset 14.36 and newer (provided with Visual Studio 17.6 and newer)
* GCC 15 and newer
* GCC 15 and newer, with the exception of MacOS
* GCC 16 and newer on MacOS
.. note::
@@ -100,12 +101,12 @@ library combinations:
.. _`Ubuntu issue 2141579`: https://bugs.launchpad.net/ubuntu/+source/gcc-15/+bug/2141579
The :variable:`CMAKE_CXX_COMPILER_IMPORT_STD` variable lists standard levels
which have support for ``import std`` in the active C++ toolchain.
Only the :ref:`Ninja Generators` currently support ``import std`` because
:ref:`Visual Studio Generators` do not support building :term:`BMIs <BMI>`
for ``IMPORTED`` targets.
Additionally, only the :ref:`Ninja Generators` currently support
``import std`` at this time because :ref:`Visual Studio Generators` do not
support building :term:`BMIs <BMI>` for ``IMPORTED`` targets.
``import std`` is available for all language standards which support C++ module
scanning (ie, C++20 and newer).
.. note::
+5
View File
@@ -1,6 +1,11 @@
CXX_MODULE_STD
--------------
.. versionchanged:: 4.5
``CXX_MODULE_STD`` no longer has any effect. ``import std;`` is handled
automatically on all sources with :prop_tgt:`CXX_SCAN_FOR_MODULES` enabled.
.. versionadded:: 3.30
``CXX_MODULE_STD`` is a boolean specifying whether the target may use
@@ -1,6 +1,12 @@
CMAKE_CXX_COMPILER_IMPORT_STD
-----------------------------
.. versionchanged:: 4.5
Reporting of supported C++ standard levels has been removed as toolchains
no longer control generation of standard library targets.
``CMAKE_CXX_COMPILER_IMPORT_STD`` is left undefined.
.. versionadded:: 3.30
A list of C++ standard levels for which ``import std`` support exists for the
+5
View File
@@ -1,6 +1,11 @@
CMAKE_CXX_MODULE_STD
--------------------
.. versionchanged:: 4.5
``CMAKE_CXX_MODULE_STD`` no longer has any effect. ``import std;`` is handled
automatically on all sources with :prop_tgt:`CXX_SCAN_FOR_MODULES` enabled.
.. versionadded:: 3.30
Whether to add utility targets as dependencies to targets with at least
-1
View File
@@ -98,6 +98,5 @@ set(CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES "@CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES@")
set(CMAKE_CXX_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "@CMAKE_CXX_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES@")
set(CMAKE_CXX_COMPILER_CLANG_RESOURCE_DIR "@CMAKE_CXX_COMPILER_CLANG_RESOURCE_DIR@")
set(CMAKE_CXX_COMPILER_IMPORT_STD "@CMAKE_CXX_COMPILER_IMPORT_STD@")
set(CMAKE_CXX_COMPILER_IMPORT_STD_ERROR_MESSAGE "@CMAKE_CXX_COMPILER_IMPORT_STD_ERROR_MESSAGE@")
set(CMAKE_CXX_STDLIB_MODULES_JSON "@CMAKE_CXX_STDLIB_MODULES_JSON@")
@@ -152,19 +152,8 @@ function(cmake_determine_compiler_support lang)
endif()
endif ()
# Find the module metadata for import std
set(CMAKE_CXX_COMPILER_IMPORT_STD "")
cmake_cxx_find_modules_json()
foreach(_cmake_import_std_version IN ITEMS 23 26)
if(CMAKE_CXX${_cmake_import_std_version}_COMPILE_FEATURES)
# Modules JSON covers all versions, otherwise rely on toolchain targets
if(CMAKE_CXX_STDLIB_MODULES_JSON)
list(APPEND CMAKE_CXX_COMPILER_IMPORT_STD ${_cmake_import_std_version})
endif()
endif()
endforeach()
set(CMAKE_CXX_COMPILER_IMPORT_STD ${CMAKE_CXX_COMPILER_IMPORT_STD} PARENT_SCOPE)
set(CMAKE_CXX_STDLIB_MODULES_JSON ${CMAKE_CXX_STDLIB_MODULES_JSON} PARENT_SCOPE)
set(CMAKE_CXX_COMPILER_IMPORT_STD_ERROR_MESSAGE "${CMAKE_CXX_COMPILER_IMPORT_STD_ERROR_MESSAGE}" PARENT_SCOPE)
-2
View File
@@ -215,8 +215,6 @@ Entry const kEntries[] = {
"Default value for CUDA_STANDARD_REQUIRED target property if set when a target is created. See the cmake-compile-features(7) manual for information on compile features and a list of supported compilers."_s },
{ "CMAKE_CXX_EXTENSIONS"_s,
"Default value for CXX_EXTENSIONS target property if set when a target is created. See the cmake-compile-features(7) manual for information on compile features and a list of supported compilers."_s },
{ "CMAKE_CXX_MODULE_STD"_s,
"Whether to add utility targets as dependencies for C++23 targets"_s },
{ "CMAKE_CXX_SCAN_FOR_MODULES"_s,
"Whether to scan C++ source files for module dependencies"_s },
{ "CMAKE_CXX_STANDARD"_s,
+34 -12
View File
@@ -31,6 +31,38 @@
#include "cmTargetTypes.h"
#include "cmValue.h"
namespace {
bool LinkedTargetHasModules(cmGeneratorTarget const* target,
std::string const& lang, std::string const& config,
cmGlobalCommonGenerator const* gg,
cmGeneratorTarget const* currentTarget)
{
if (!target) {
return false;
}
if (lang == "CXX"_s && target->HasCxxImportModuleErrors()) {
return true;
}
if (target->IsImported()) {
return false;
}
if (!gg->TargetOrderIndexLess(target, currentTarget)) {
return false;
}
if (target->GetType() == cm::TargetType::INTERFACE_LIBRARY &&
!target->IsSynthetic()) {
return false;
}
if (lang == "CXX"_s && target->HaveCxx20ModuleSources()) {
return true;
}
if (lang == "Fortran"_s && target->HaveFortranSources(config)) {
return true;
}
return false;
}
}
cmCommonTargetGenerator::cmCommonTargetGenerator(cmGeneratorTarget* gt)
: GeneratorTarget(gt)
, Makefile(gt->Makefile)
@@ -252,18 +284,8 @@ cmCommonTargetGenerator::GetLinkedTargetDirectories(
}
if (mappedLinkee &&
!mappedLinkee->IsImported()
// Skip targets that build after this one in a static lib cycle.
&& gg->TargetOrderIndexLess(mappedLinkee, this->GeneratorTarget)
// We can ignore the INTERFACE_LIBRARY items because
// Target->GetLinkInformation already processed their
// link interface and they don't have any output themselves.
&& (mappedLinkee->GetType() != cm::TargetType::INTERFACE_LIBRARY
// Synthesized targets may have relevant rules.
|| mappedLinkee->IsSynthetic()) &&
((lang == "CXX"_s && mappedLinkee->HaveCxx20ModuleSources()) ||
(lang == "Fortran"_s &&
mappedLinkee->HaveFortranSources(config)))) {
LinkedTargetHasModules(mappedLinkee, lang, config, gg,
this->GeneratorTarget)) {
cmLocalGenerator* lg = mappedLinkee->GetLocalGenerator();
std::string di = mappedLinkee->GetSupportDirectory();
if (lg->GetGlobalGenerator()->IsMultiConfig()) {
+1 -1
View File
@@ -31,7 +31,7 @@ cmExperimental::FeatureData const LookupTable[] = {
cmExperimental::TryCompileCondition::Always },
// CxxImportStd
{ "CxxImportStd",
"f35a9ac6-8463-4d38-8eec-5d6008153e7d",
"25d6f6aa-be65-4692-b44e-87b23e96d4e1",
"CMAKE_EXPERIMENTAL_CXX_IMPORT_STD",
"CMake's support for `import std;` in C++23 and newer is experimental. It "
"is meant only for experimentation and feedback to CMake developers.",
-8
View File
@@ -753,14 +753,6 @@ bool cmExportFileGenerator::PopulateCxxModuleExportProperties(
ModuleTargetPropertyTable const exportedDirectModuleProperties[] = {
{ "CXX_EXTENSIONS"_s, ExportWhen::Defined },
// Always define this property as it is an intrinsic property of the target
// and should not be inherited from the in-scope `CMAKE_CXX_MODULE_STD`
// variable.
//
// TODO(cxxmodules): A future policy may make this "ON" based on the target
// policies if unset. Add a new `ExportWhen` condition to handle it when
// this happens.
{ "CXX_MODULE_STD"_s, ExportWhen::Always },
};
for (auto const& prop : exportedDirectModuleProperties) {
auto const propNameStr = std::string(prop.Name);
+66 -96
View File
@@ -708,7 +708,7 @@ void cmGeneratorTarget::GetObjectSources(
this->VisitedConfigsForObjects.insert(config);
}
void cmGeneratorTarget::ComputeObjectMapping()
void cmGeneratorTarget::ComputeObjectMapping() const
{
auto const& configs =
this->Makefile->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig);
@@ -863,7 +863,8 @@ bool cmGeneratorTarget::IsIPOEnabled(std::string const& lang,
return false;
}
std::string const& cmGeneratorTarget::GetObjectName(cmSourceFile const* file)
std::string const& cmGeneratorTarget::GetObjectName(
cmSourceFile const* file) const
{
this->ComputeObjectMapping();
auto const useShortPaths = this->GetUseShortObjectNames()
@@ -906,7 +907,7 @@ void cmGeneratorTarget::AddExplicitObjectName(cmSourceFile const* sf)
bool cmGeneratorTarget::HasExplicitObjectName(cmSourceFile const* file) const
{
const_cast<cmGeneratorTarget*>(this)->ComputeObjectMapping();
this->ComputeObjectMapping();
auto it = this->ExplicitObjectName.find(file);
return it != this->ExplicitObjectName.end();
}
@@ -5331,7 +5332,6 @@ bool cmGeneratorTarget::IsNullImpliedByLinkLibraries(
namespace {
bool CreateCxxStdlibTarget(cmMakefile* makefile, cmLocalGenerator* lg,
std::string const& targetName,
std::vector<std::string> const& configs)
{
#ifndef CMAKE_BOOTSTRAP
@@ -5343,25 +5343,33 @@ bool CreateCxxStdlibTarget(cmMakefile* makefile, cmLocalGenerator* lg,
auto errorMessage =
makefile->GetDefinition("CMAKE_CXX_COMPILER_IMPORT_STD_ERROR_MESSAGE");
if (!errorMessage.IsEmpty()) {
makefile->IssueMessage(
MessageType::FATAL_ERROR,
cmStrCat(R"(The "CXX_MODULE_STD" property on target ")", targetName,
"\" requires toolchain support, but it was not provided. "
"Reason:\n ",
*errorMessage));
return false;
auto* stdlibTgt = makefile->AddImportedTarget(
"@cmake_cxx_std", cm::TargetType::INTERFACE_LIBRARY,
cm::ImportedTargetScope::Global);
stdlibTgt->SetProperty("CXX_IMPORT_ERROR_MESSAGE", *errorMessage);
stdlibTgt->SetProperty("CXX_IMPORT_ERROR_MODULES", "std;std.compat");
auto gt = cm::make_unique<cmGeneratorTarget>(stdlibTgt, lg);
lg->AddImportedGeneratorTarget(gt.get());
lg->AddOwnedImportedGeneratorTarget(std::move(gt));
return true;
}
auto metadataPath =
makefile->GetDefinition("CMAKE_CXX_STDLIB_MODULES_JSON");
if (metadataPath.IsEmpty()) {
makefile->IssueMessage(
MessageType::FATAL_ERROR,
cmStrCat(
R"("The "CXX_MODULE_STD" property on target ")", targetName,
"\" requires CMAKE_CXX_STDLIB_MODULES_JSON be set, but it was not "
"provided by the toolchain."));
return false;
auto* stdlibTgt = makefile->AddImportedTarget(
"@cmake_cxx_std", cm::TargetType::INTERFACE_LIBRARY,
cm::ImportedTargetScope::Global);
stdlibTgt->SetProperty(
"CXX_IMPORT_ERROR_MESSAGE",
R"(CMAKE_CXX_STDLIB_MODULES_JSON set to empty string)");
stdlibTgt->SetProperty("CXX_IMPORT_ERROR_MODULES", "std;std.compat");
auto gt = cm::make_unique<cmGeneratorTarget>(stdlibTgt, lg);
lg->AddImportedGeneratorTarget(gt.get());
lg->AddOwnedImportedGeneratorTarget(std::move(gt));
return true;
}
auto parseResult = cmCxxModuleMetadata::LoadFromFile(*metadataPath);
@@ -5377,8 +5385,9 @@ bool CreateCxxStdlibTarget(cmMakefile* makefile, cmLocalGenerator* lg,
metadata = std::move(*parseResult.Meta);
}
auto* stdlibTgt = makefile->AddLibrary(
"@cmake_cxx_std", cm::TargetType::STATIC_LIBRARY, {}, true);
auto* stdlibTgt = makefile->AddImportedTarget(
"@cmake_cxx_std", cm::TargetType::INTERFACE_LIBRARY,
cm::ImportedTargetScope::Global);
cmCxxModuleMetadata::PopulateTarget(*stdlibTgt, *metadata, configs);
cmStandardLevelResolver standardResolver(makefile);
standardResolver.AddRequiredTargetFeature(stdlibTgt, "cxx_std_20");
@@ -5387,7 +5396,13 @@ bool CreateCxxStdlibTarget(cmMakefile* makefile, cmLocalGenerator* lg,
gt->ComputeCompileFeatures(config);
}
lg->AddGeneratorTarget(std::move(gt));
auto compilerId = makefile->GetSafeDefinition("CMAKE_CXX_COMPILER_ID");
if (compilerId == "MSVC") {
stdlibTgt->SetCxxModuleNeedsInterfaceObjects(true);
}
lg->AddImportedGeneratorTarget(gt.get());
lg->AddOwnedImportedGeneratorTarget(std::move(gt));
#endif // CMAKE_BOOTSTRAP
@@ -5397,66 +5412,26 @@ bool CreateCxxStdlibTarget(cmMakefile* makefile, cmLocalGenerator* lg,
bool cmGeneratorTarget::ApplyCXXStdTarget()
{
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.
if (!cmExperimental::HasSupportEnabled(
*this->Makefile, cmExperimental::Feature::CxxImportStd)) {
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;
std::vector<std::string> const& configs =
this->Makefile->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig);
bool needsStd = false;
if (this->Target->IsImported()) {
needsStd = this->HaveInterfaceCxx20ModuleSources();
} else {
for (auto const& config : configs) {
if (this->NeedCxxDyndep(config) == CxxModuleSupport::Enabled) {
needsStd = true;
break;
}
}
}
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) {
if (!needsStd) {
return true;
}
@@ -5464,29 +5439,26 @@ bool cmGeneratorTarget::ApplyCXXStdTarget()
// already exist. BMI compatibility handles per-consumer standard level
// differences by creating synthetic targets as needed.
if (!this->Makefile->FindTargetToUse("@cmake_cxx_std") &&
!CreateCxxStdlibTarget(this->Makefile, this->LocalGenerator,
this->GetName(), configs)) {
!CreateCxxStdlibTarget(this->Makefile, this->LocalGenerator, configs)) {
return false;
}
this->Target->AppendProperty("LINK_LIBRARIES",
"$<BUILD_LOCAL_INTERFACE:@cmake_cxx_std>");
// Check the experimental feature here. A toolchain may have
// skipped the check in the toolchain preparation logic.
if (!cmExperimental::HasSupportEnabled(
*this->Makefile, cmExperimental::Feature::CxxImportStd)) {
this->Makefile->IssueMessage(
MessageType::FATAL_ERROR,
"Experimental `import std` support not enabled when detecting "
"toolchain; it must be set before `CXX` is enabled (usually a "
"`project()` call).");
return false;
if (this->Target->IsImported()) {
this->Target->AppendProperty("IMPORTED_CXX_MODULES_LINK_LIBRARIES",
"@cmake_cxx_std");
} else {
this->Target->AppendProperty("LINK_LIBRARIES",
"$<BUILD_LOCAL_INTERFACE:@cmake_cxx_std>");
}
return true;
}
bool cmGeneratorTarget::HasCxxImportModuleErrors() const
{
return this->Target->GetProperty("CXX_IMPORT_ERROR_MODULES") != nullptr;
}
cmCxxModuleUsageEffects const& cmGeneratorTarget::GetCxxModuleUsageEffects(
std::string const& config) const
{
@@ -5541,6 +5513,9 @@ cmGeneratorTarget const* cmGeneratorTarget::GetCxxSyntheticTarget(
auto* lg = this->GetLocalGenerator();
auto* tgt =
mf->AddSynthesizedTarget(cm::TargetType::INTERFACE_LIBRARY, targetName);
if (model->CxxModuleNeedsInterfaceObjects()) {
tgt->SetCxxModuleNeedsInterfaceObjects(true);
}
// Copy relevant information from the existing target.
@@ -5591,11 +5566,6 @@ cmGeneratorTarget const* cmGeneratorTarget::GetCxxSyntheticTarget(
for (auto const& innerConfig : allConfigs) {
gtp->ComputeCompileFeatures(innerConfig);
}
// See `cmGlobalGenerator::ApplyCXXStdTarget` in
// `cmGlobalGenerator::Compute` for non-synthetic target resolutions.
if (!gtp->ApplyCXXStdTarget()) {
return nullptr;
}
lg->AddGeneratorTarget(std::move(gtp));
this->SynthCxxTargets[usageHash] = syntheticTarget;
+3 -2
View File
@@ -195,7 +195,7 @@ public:
void GetObjectSources(std::vector<cmSourceFile const*>&,
std::string const& config) const;
std::string const& GetObjectName(cmSourceFile const* file);
std::string const& GetObjectName(cmSourceFile const* file) const;
char const* GetCustomObjectExtension() const;
bool HasExplicitObjectName(cmSourceFile const* file) const;
@@ -233,7 +233,7 @@ public:
std::set<cmLinkItem> const& GetUtilityItems() const;
void ComputeObjectMapping();
void ComputeObjectMapping() const;
cmValue GetFeature(std::string const& feature,
std::string const& config) const;
@@ -1148,6 +1148,7 @@ public:
std::string GetImportedXcFrameworkPath(std::string const& config) const;
bool ApplyCXXStdTarget();
bool HasCxxImportModuleErrors() const;
cmCxxModuleUsageEffects const& GetCxxModuleUsageEffects(
std::string const& config) const;
cmGeneratorTarget const* GetTargetForCxxModules(
+3 -1
View File
@@ -422,7 +422,9 @@ void cmGeneratorTarget::ComputeKindedSources(KindedSources& files,
kind = SourceKindCustomCommand;
} else if (!this->Target->IsNormal() && !this->Target->IsImported() &&
fs && (fs->GetType() == cm::FileSetMetadata::CXX_MODULES)) {
kind = SourceKindCxxModuleSource;
kind = this->Target->CxxModuleNeedsInterfaceObjects()
? SourceKindObjectSource
: SourceKindCxxModuleSource;
} else if (this->Target->GetType() == cm::TargetType::UTILITY ||
this->Target->GetType() == cm::TargetType::INTERFACE_LIBRARY
// XXX(clang-tidy): https://bugs.llvm.org/show_bug.cgi?id=44165
+62 -9
View File
@@ -1701,6 +1701,9 @@ bool cmGlobalGenerator::Compute()
return false;
}
// Write pre-generated module info for targets that report import errors.
this->WriteCxxImportErrorModules();
// 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?
@@ -2018,17 +2021,29 @@ void cmGlobalGenerator::ComputeTargetOrder(cmGeneratorTarget const* gt,
bool cmGlobalGenerator::ApplyCXXStdTarget()
{
for (auto const& gen : this->LocalGenerators) {
// tgt->ApplyCXXStdTarget can create a target itself, so we need iterators
// which won't be invalidated by that target creation
auto const& genTgts = gen->GetGeneratorTargets();
std::vector<cmGeneratorTarget*> existingTgts;
existingTgts.reserve(genTgts.size());
for (auto const& tgt : genTgts) {
existingTgts.push_back(tgt.get());
// @cmake_cxx_std is added to OwnedImportedGeneratorTargets during
// iteration. If it doesn't exist yet, copy the list to protect against
// invalidation when CreateCxxStdlibTarget adds it.
if (gen->GetMakefile()->FindTargetToUse("@cmake_cxx_std")) {
for (auto const& tgt : gen->GetOwnedImportedGeneratorTargets()) {
if (!tgt->ApplyCXXStdTarget()) {
return false;
}
}
} else {
std::vector<cmGeneratorTarget*> impTgts;
impTgts.reserve(gen->GetOwnedImportedGeneratorTargets().size());
for (auto const& tgt : gen->GetOwnedImportedGeneratorTargets()) {
impTgts.push_back(tgt.get());
}
for (auto* tgt : impTgts) {
if (!tgt->ApplyCXXStdTarget()) {
return false;
}
}
}
for (auto const& tgt : existingTgts) {
for (auto const& tgt : gen->GetGeneratorTargets()) {
if (!tgt->ApplyCXXStdTarget()) {
return false;
}
@@ -2038,6 +2053,44 @@ bool cmGlobalGenerator::ApplyCXXStdTarget()
return true;
}
void cmGlobalGenerator::WriteCxxImportErrorModules()
{
#ifndef CMAKE_BOOTSTRAP
for (auto const& gen : this->LocalGenerators) {
for (auto const& tgt : gen->GetOwnedImportedGeneratorTargets()) {
auto errorMsg = tgt->Target->GetProperty("CXX_IMPORT_ERROR_MESSAGE");
auto modules = tgt->Target->GetProperty("CXX_IMPORT_ERROR_MODULES");
if (!errorMsg || !modules) {
continue;
}
auto configs =
tgt->Makefile->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig);
for (auto const& config : configs) {
auto dir = tgt->GetSupportDirectory();
if (this->IsMultiConfig()) {
dir = cmStrCat(dir, '/', config);
}
cmSystemTools::MakeDirectory(dir);
Json::Value moduleInfo(Json::objectValue);
moduleInfo["modules"] = Json::objectValue;
Json::Value importError(Json::objectValue);
importError["message"] = *errorMsg;
Json::Value modulesArray(Json::arrayValue);
for (auto const& m : cmList{ *modules }) {
modulesArray.append(m);
}
importError["modules"] = modulesArray;
moduleInfo["import-error"] = importError;
cmGeneratedFileStream mf(cmStrCat(dir, "/CXXModules.json"));
mf << moduleInfo;
}
}
}
#endif
}
bool cmGlobalGenerator::DiscoverSyntheticTargets()
{
for (auto const& gen : this->LocalGenerators) {
+1
View File
@@ -811,6 +811,7 @@ protected:
virtual bool CheckALLOW_DUPLICATE_CUSTOM_TARGETS() const;
bool ApplyCXXStdTarget();
void WriteCxxImportErrorModules();
bool DiscoverSyntheticTargets();
bool AddHeaderSetVerification();
+104 -4
View File
@@ -2680,7 +2680,8 @@ bool cmGlobalNinjaGenerator::WriteDyndepFile(
std::vector<std::string> const& linked_target_dirs,
std::vector<std::string> const& forward_modules_from_target_dirs,
std::string const& native_target_dir, std::string const& arg_lang,
std::string const& arg_modmapfmt, cmCxxModuleExportInfo const& export_info)
std::string const& arg_modmapfmt, cmCxxModuleExportInfo const& export_info,
Json::Value const* cxx_interface_objects)
{
// Setup path conversions.
{
@@ -2715,6 +2716,14 @@ bool cmGlobalNinjaGenerator::WriteDyndepFile(
};
std::map<std::string, AvailableModuleInfo> mod_files;
struct ImportErrorInfo
{
std::string Message;
std::set<std::string> Modules;
};
std::vector<ImportErrorInfo> importErrors;
Json::Value transitiveInterfaceObjects(Json::objectValue);
// Populate the module map with those provided by linked targets first.
for (std::string const& linked_target_dir : linked_target_dirs) {
std::string const ltmn =
@@ -2784,6 +2793,42 @@ bool cmGlobalNinjaGenerator::WriteDyndepFile(
}
}
}
Json::Value const& import_error = ltm["import-error"];
if (import_error.isObject()) {
ImportErrorInfo info;
info.Message = import_error["message"].asString();
Json::Value const& errModules = import_error["modules"];
if (errModules.isArray()) {
for (auto const& m : errModules) {
info.Modules.insert(m.asString());
}
}
if (!info.Modules.empty()) {
importErrors.push_back(std::move(info));
}
}
Json::Value const& linked_interface_objects = ltm["interface-objects"];
if (linked_interface_objects.isObject()) {
for (auto i = linked_interface_objects.begin();
i != linked_interface_objects.end(); ++i) {
if (!transitiveInterfaceObjects.isMember(i.key().asString())) {
transitiveInterfaceObjects[i.key().asString()] = *i;
}
}
}
}
}
if (!importErrors.empty()) {
for (cmScanDepInfo const& object : objects) {
for (auto const& r : object.Requires) {
for (auto const& ie : importErrors) {
if (ie.Modules.count(r.LogicalName)) {
cmSystemTools::Error(ie.Message);
return false;
}
}
}
}
}
@@ -3050,8 +3095,37 @@ bool cmGlobalNinjaGenerator::WriteDyndepFile(
forward_info(tmi_target_modules, fmft["modules"]);
forward_info(target_references, fmft["references"]);
forward_info(target_usages, fmft["usages"]);
forward_info(transitiveInterfaceObjects, fmft["interface-objects"]);
}
// Compute the set of modules actually imported by sources in this target.
std::set<std::string> usedModules;
for (cmScanDepInfo const& object : objects) {
for (auto const& r : object.Requires) {
usedModules.insert(r.LogicalName);
}
}
// Merge direct interface objects into the accumulated set.
// Direct objects are filtered: only keep those for modules that are
// actually imported by sources in this target. Transitive objects from
// linked targets were already filtered in their originating target.
if (cxx_interface_objects && cxx_interface_objects->isObject()) {
Json::Value const& directObjects =
(*cxx_interface_objects)["module-objects"];
if (directObjects.isObject()) {
for (auto i = directObjects.begin(); i != directObjects.end(); ++i) {
std::string moduleName = i.key().asString();
if (usedModules.count(moduleName) &&
!transitiveInterfaceObjects.isMember(moduleName)) {
transitiveInterfaceObjects[i.key().asString()] = *i;
}
}
}
}
target_module_info["interface-objects"] = transitiveInterfaceObjects;
cmGeneratedFileStream tmf(target_mods_file);
tmf.SetCopyIfDifferent(true);
tmf << target_module_info;
@@ -3066,8 +3140,29 @@ bool cmGlobalNinjaGenerator::WriteDyndepFile(
return {};
};
return cmDyndepCollation::WriteDyndepMetadata(arg_lang, objects, export_info,
cb);
if (!cmDyndepCollation::WriteDyndepMetadata(arg_lang, objects, export_info,
cb)) {
return false;
}
// Write the interface objects response file if configured.
if (cxx_interface_objects && cxx_interface_objects->isObject()) {
Json::Value const& rspFile = (*cxx_interface_objects)["rsp-file"];
if (rspFile.isString()) {
cmGeneratedFileStream rsp(rspFile.asString());
rsp.SetCopyIfDifferent(true);
auto* lg = this->LocalGenerators.back().get();
for (auto const& objPath : transitiveInterfaceObjects) {
rsp << lg->ConvertToOutputFormat(
lg->MaybeRelativeToTopBinDir(objPath.asString()),
cmOutputConverter::RESPONSE)
<< "\n";
}
}
}
return true;
}
int cmcmd_cmake_ninja_dyndep(std::vector<std::string>::const_iterator argBeg,
@@ -3182,6 +3277,11 @@ int cmcmd_cmake_ninja_dyndep(std::vector<std::string>::const_iterator argBeg,
auto export_info = cmDyndepCollation::ParseExportInfo(tdi);
Json::Value const* cxx_interface_objects = nullptr;
if (tdi.isMember("cxx-interface-objects")) {
cxx_interface_objects = &tdi["cxx-interface-objects"];
}
cmake cm(cmState::Role::Internal);
cm.SetHomeDirectory(dir_top_src);
cm.SetHomeOutputDirectory(dir_top_bld);
@@ -3200,7 +3300,7 @@ int cmcmd_cmake_ninja_dyndep(std::vector<std::string>::const_iterator argBeg,
arg_dd, arg_ddis, module_dir, linked_target_dirs,
forward_modules_from_target_dirs,
native_target_dir, arg_lang, arg_modmapfmt,
*export_info)
*export_info, cxx_interface_objects)
? 0
: 1;
}
+6 -2
View File
@@ -32,6 +32,10 @@ class cmMakefile;
class cmake;
struct cmCxxModuleExportInfo;
namespace Json {
class Value;
}
/**
* \class cmGlobalNinjaGenerator
* \brief Write a build.ninja file.
@@ -434,8 +438,8 @@ public:
std::vector<std::string> const& linked_target_dirs,
std::vector<std::string> const& forward_modules_from_target_dirs,
std::string const& native_target_dir, std::string const& arg_lang,
std::string const& arg_modmapfmt,
cmCxxModuleExportInfo const& export_info);
std::string const& arg_modmapfmt, cmCxxModuleExportInfo const& export_info,
Json::Value const* cxx_interface_objects = nullptr);
virtual std::string BuildAlias(std::string const& alias,
std::string const& /*config*/) const
+25
View File
@@ -42,6 +42,7 @@
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmTarget.h"
#include "cmTargetTypes.h"
#include "cmValue.h"
@@ -1386,6 +1387,30 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement(
vars["LINK_PATH"] = frameworkPath + linkPath;
vars["CONFIG"] = config;
// Add interface objects response file to link flags if configured.
{
bool multiConfig = this->GetGlobalGenerator()->IsMultiConfig();
std::string configDir = multiConfig ? cmStrCat('/', config) : "";
bool hasInterfaceObjects = false;
for (auto const& pair :
this->GetGeneratorTarget()->GetSyntheticDeps(config)) {
if (pair.first->Target->CxxModuleNeedsInterfaceObjects()) {
hasInterfaceObjects = true;
break;
}
}
if (hasInterfaceObjects) {
std::string rspPath =
cmStrCat(this->GeneratorTarget->GetSupportDirectory(), configDir,
"/CXXInterfaceObjects.rsp");
vars["LINK_FLAGS"] += cmStrCat(
" @",
this->GetLocalGenerator()->ConvertToOutputFormat(
this->ConvertToNinjaPath(rspPath), cmOutputConverter::SHELL));
linkBuild.ImplicitDeps.emplace_back(this->ConvertToNinjaPath(rspPath));
}
}
// Compute architecture specific link flags. Yes, these go into a different
// variable for executables, probably due to a mistake made when duplicating
// code between the Makefile executable and library generators.
+86 -1
View File
@@ -50,6 +50,7 @@
#include "cmRange.h"
#include "cmRulePlaceholderExpander.h"
#include "cmSourceFile.h"
#include "cmSourceFileLocationKind.h"
#include "cmState.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
@@ -291,7 +292,8 @@ std::string cmNinjaTargetGenerator::ComputeFlagsForObject(
R"(" but the source is not classified as a "CXX" source.)"));
}
if (!this->GeneratorTarget->Target->IsNormal()) {
if (!this->GeneratorTarget->Target->IsNormal() &&
!this->GeneratorTarget->Target->CxxModuleNeedsInterfaceObjects()) {
if (this->GetMakefile()
->GetDefinition("CMAKE_CXX_COMPILE_BMI")
.IsEmpty()) {
@@ -1356,6 +1358,25 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatements(
build.Outputs.push_back(this->GetDyndepFilePath(language, config));
build.ImplicitOuts.emplace_back(
cmStrCat(this->GetObjectFileDir(config), '/', language, "Modules.json"));
// Add interface objects response file as implicit output if needed.
{
bool multiConfig = this->GetGlobalGenerator()->IsMultiConfig();
std::string configDir = multiConfig ? cmStrCat('/', config) : "";
std::string rspPath =
cmStrCat(this->GeneratorTarget->GetSupportDirectory(), configDir,
"/CXXInterfaceObjects.rsp");
bool hasInterfaceObjects = false;
for (auto const& pair :
this->GeneratorTarget->GetSyntheticDeps(config)) {
if (pair.first->Target->CxxModuleNeedsInterfaceObjects()) {
hasInterfaceObjects = true;
break;
}
}
if (hasInterfaceObjects) {
build.ImplicitOuts.emplace_back(this->ConvertToNinjaPath(rspPath));
}
}
build.ImplicitDeps.emplace_back(
this->GetTargetDependInfoPath(language, config));
{
@@ -2440,6 +2461,70 @@ void cmNinjaTargetGenerator::WriteTargetDependInfo(std::string const& lang,
config, cb);
#endif
// Collect interface objects from tagged synthetics for the response file.
{
auto const& synthDeps = this->GeneratorTarget->GetSyntheticDeps(config);
if (!synthDeps.empty()) {
bool multiConfig = this->GetGlobalGenerator()->IsMultiConfig();
std::string configDir = multiConfig ? cmStrCat('/', config) : "";
std::string configUpper = cmSystemTools::UpperCase(config);
std::string modulesProp = cmStrCat("IMPORTED_CXX_MODULES_", configUpper);
Json::Value interfaceObjects(Json::objectValue);
Json::Value moduleObjects(Json::objectValue);
bool hasInterfaceObjects = false;
for (auto const& pair : synthDeps) {
auto const* nativeGT = pair.first;
if (!nativeGT->Target->CxxModuleNeedsInterfaceObjects()) {
continue;
}
hasInterfaceObjects = true;
for (auto const* synthGT : pair.second) {
std::string objDir =
cmStrCat(synthGT->GetSupportDirectory(), configDir);
cmValue importedModules = synthGT->Target->GetProperty(modulesProp);
if (!importedModules) {
continue;
}
for (auto const& entry : cmList{ *importedModules }) {
auto nameSep = entry.find('=');
if (nameSep == std::string::npos) {
continue;
}
auto moduleName = entry.substr(0, nameSep);
auto nameAndPath = entry.substr(nameSep + 1);
auto commaSep = nameAndPath.find(',');
std::string sourcePath = commaSep == std::string::npos
? nameAndPath
: nameAndPath.substr(0, commaSep);
cmSourceFile const* sf = synthGT->Makefile->GetSource(
sourcePath, cmSourceFileLocationKind::Known);
if (!sf) {
continue;
}
std::string const& objName = synthGT->GetObjectName(sf);
std::string objPath = cmStrCat(objDir, '/', objName);
moduleObjects[moduleName] = objPath;
}
}
}
if (hasInterfaceObjects) {
std::string rspPath =
cmStrCat(this->GeneratorTarget->GetSupportDirectory(), configDir,
"/CXXInterfaceObjects.rsp");
interfaceObjects["rsp-file"] = rspPath;
interfaceObjects["module-objects"] = moduleObjects;
tdi["cxx-interface-objects"] = interfaceObjects;
}
}
}
std::string const tdin = this->GetTargetDependInfoPath(lang, config);
cmGeneratedFileStream tdif(tdin);
tdif << tdi;
+11 -2
View File
@@ -351,7 +351,6 @@ TargetProperty const StaticTargetProperties[] = {
COMMON_LANGUAGE_PROPERTIES(C),
// ---- C++
COMMON_LANGUAGE_PROPERTIES(CXX),
{ "CXX_MODULE_STD"_s, IC::CanCompileSources },
// ---- CSharp
{ "DOTNET_SDK"_s, IC::NonImportedTarget },
{ "DOTNET_TARGET_FRAMEWORK"_s, IC::TargetWithCommands },
@@ -632,6 +631,7 @@ public:
bool IsSymbolic = false;
bool IsForTryCompile = false;
bool IsExportPassthrough = false;
bool CxxModuleNeedsInterfaceObjects = false;
cmTarget::Visibility TargetVisibility;
std::set<BT<std::pair<std::string, bool>>> Utilities;
std::set<std::string> CodegenDependencies;
@@ -1190,6 +1190,16 @@ cmGlobalGenerator* cmTarget::GetGlobalGenerator() const
return this->impl->Makefile->GetGlobalGenerator();
}
bool cmTarget::CxxModuleNeedsInterfaceObjects() const
{
return this->impl->CxxModuleNeedsInterfaceObjects;
}
void cmTarget::SetCxxModuleNeedsInterfaceObjects(bool v)
{
this->impl->CxxModuleNeedsInterfaceObjects = v;
}
BTs<std::string> const* cmTarget::GetLanguageStandardProperty(
std::string const& propertyName) const
{
@@ -1875,7 +1885,6 @@ void cmTarget::CopyCxxModulesProperties(cmTarget const* tgt)
// ---- C++
"CXX_COMPILER_LAUNCHER",
"CXX_VISIBILITY_PRESET",
"CXX_MODULE_STD",
// Static analysis
"CXX_CLANG_TIDY",
+4
View File
@@ -314,6 +314,10 @@ public:
cmStringRange GetInstallIncludeDirectoriesEntries(
cmTargetExport const& te) const;
//! Control if the target generates object files for module interfaces
bool CxxModuleNeedsInterfaceObjects() const;
void SetCxxModuleNeedsInterfaceObjects(bool);
BTs<std::string> const* GetLanguageStandardProperty(
std::string const& propertyName) const;
@@ -1 +0,0 @@
1
@@ -1,3 +0,0 @@
CMake Error in CMakeLists\.txt:
The "CXX_MODULE_STD" property on the target "nocxx23target" contains a
context-sensitive condition that is not supported\.
@@ -1,10 +0,0 @@
enable_language(CXX)
set(CMAKE_CXX_MODULE_STD "$<CONFIG:Release>")
add_library(nocxx23target)
target_sources(nocxx23target
PRIVATE
FILE_SET fs TYPE CXX_MODULES FILES
sources/module.cxx)
target_compile_features(nocxx23target PRIVATE cxx_std_23)
@@ -1 +0,0 @@
1
@@ -1,9 +0,0 @@
CMake Error:
Error evaluating generator expression:
\$<TARGET_PROPERTY:use_std_in_consumed>
\$<TARGET_PROPERTY:prop> may only be used with binary targets\. It may not
be used with add_custom_command or add_custom_target\. Specify the target
to read a property from using the \$<TARGET_PROPERTY:tgt,prop> signature
instead\.
@@ -1,10 +0,0 @@
enable_language(CXX)
set(CMAKE_CXX_MODULE_STD "$<TARGET_PROPERTY:use_std_in_consumed>")
add_library(nocxx23target)
target_sources(nocxx23target
PRIVATE
FILE_SET fs TYPE CXX_MODULES FILES
sources/module.cxx)
target_compile_features(nocxx23target PRIVATE cxx_std_23)
@@ -1,11 +0,0 @@
enable_language(CXX)
set(CMAKE_CXX_SCANDEP_SOURCE "echo")
set(CMAKE_CXX_MODULE_STD "$<STREQUAL:")
add_library(nocxx23target)
target_sources(nocxx23target
PRIVATE
FILE_SET fs TYPE CXX_MODULES FILES
sources/module.cxx)
target_compile_features(nocxx23target PRIVATE cxx_std_23)
@@ -1 +0,0 @@
1
@@ -1,7 +0,0 @@
CMake Error:
Error evaluating generator expression:
\$<LINK_LANGUAGE:CXX>
\$<LINK_LANGUAGE:\.\.\.> may only be used with binary targets to specify link
libraries, link directories, link options and link depends\.
@@ -1,10 +0,0 @@
enable_language(CXX)
set(CMAKE_CXX_MODULE_STD "$<LINK_LANGUAGE:CXX>")
add_library(nocxx23target)
target_sources(nocxx23target
PRIVATE
FILE_SET fs TYPE CXX_MODULES FILES
sources/module.cxx)
target_compile_features(nocxx23target PRIVATE cxx_std_23)
-2
View File
@@ -20,8 +20,6 @@ string(APPEND info "\
set(CMAKE_CXX_COMPILE_FEATURES \"${CMAKE_CXX_COMPILE_FEATURES}\")
set(CMAKE_MAKE_PROGRAM \"${CMAKE_MAKE_PROGRAM}\")
set(forced_cxx_standard \"${forced_cxx_standard}\")
set(have_cxx23_import_std \"${have_cxx23_import_std}\")
set(have_cxx26_import_std \"${have_cxx26_import_std}\")
set(CMAKE_CXX_COMPILER_VERSION \"${CMAKE_CXX_COMPILER_VERSION}\")
set(CMAKE_CXX_OUTPUT_EXTENSION \"${CMAKE_CXX_OUTPUT_EXTENSION}\")
set(CXXModules_default_build_type \"${CMAKE_BUILD_TYPE}\")
@@ -1,11 +0,0 @@
enable_language(CXX)
set(CMAKE_CXX_SCANDEP_SOURCE "echo")
set(CMAKE_CXX_MODULE_STD 0)
add_library(nocxx23target)
target_sources(nocxx23target
PRIVATE
FILE_SET fs TYPE CXX_MODULES FILES
sources/module.cxx)
target_compile_features(nocxx23target PRIVATE cxx_std_23)
@@ -1 +0,0 @@
1
@@ -1,8 +0,0 @@
CMake Error in CMakeLists\.txt:
The "CXX_MODULE_STD" property on target "nocxx23target" requires toolchain
support, but it was not provided. Reason:
(Toolchain does not support discovering module metadata|Experimental `import std` support not enabled when detecting toolchain; it must be set before `CXX` is enabled \(usually a `project\(\)` call\)|Unsupported generator: [^\n]*)
CMake Generate step failed\. Build files cannot be regenerated correctly\.
@@ -1,11 +0,0 @@
enable_language(CXX)
set(CMAKE_CXX_SCANDEP_SOURCE "echo")
set(CMAKE_CXX_MODULE_STD 1)
add_library(nocxx23target)
target_sources(nocxx23target
PRIVATE
FILE_SET fs TYPE CXX_MODULES FILES
sources/module.cxx)
target_compile_features(nocxx23target PRIVATE cxx_std_23)
@@ -1,13 +0,0 @@
enable_language(CXX)
set(CMAKE_CXX_SCANDEP_SOURCE "echo")
# TODO(cxxmodules): Add instances of this test which test the policy
# of the property's unset behavior.
# set(CMAKE_CXX_MODULE_STD ...)
add_library(nocxx23target)
target_sources(nocxx23target
PRIVATE
FILE_SET fs TYPE CXX_MODULES FILES
sources/module.cxx)
target_compile_features(nocxx23target PRIVATE cxx_std_23)
@@ -1,11 +0,0 @@
enable_language(CXX)
set(CMAKE_CXX_SCANDEP_SOURCE "echo")
set(CMAKE_CXX_MODULE_STD 0)
add_library(nocxx26target)
target_sources(nocxx26target
PRIVATE
FILE_SET fs TYPE CXX_MODULES FILES
sources/module.cxx)
target_compile_features(nocxx26target PRIVATE cxx_std_26)
@@ -1 +0,0 @@
1
@@ -1,8 +0,0 @@
CMake Error in CMakeLists\.txt:
The "CXX_MODULE_STD" property on target "nocxx26target" requires toolchain
support, but it was not provided. Reason:
(Toolchain does not support discovering module metadata|Experimental `import std` support not enabled when detecting toolchain; it must be set before `CXX` is enabled \(usually a `project\(\)` call\)|Unsupported generator: [^\n]*)
CMake Generate step failed\. Build files cannot be regenerated correctly\.
@@ -1,11 +0,0 @@
enable_language(CXX)
set(CMAKE_CXX_SCANDEP_SOURCE "echo")
set(CMAKE_CXX_MODULE_STD 1)
add_library(nocxx26target)
target_sources(nocxx26target
PRIVATE
FILE_SET fs TYPE CXX_MODULES FILES
sources/module.cxx)
target_compile_features(nocxx26target PRIVATE cxx_std_26)
@@ -1,13 +0,0 @@
enable_language(CXX)
set(CMAKE_CXX_SCANDEP_SOURCE "echo")
# TODO(cxxmodules): Add instances of this test which test the policy
# of the property's unset behavior.
# set(CMAKE_CXX_MODULE_STD ...)
add_library(nocxx26target)
target_sources(nocxx26target
PRIVATE
FILE_SET fs TYPE CXX_MODULES FILES
sources/module.cxx)
target_compile_features(nocxx26target PRIVATE cxx_std_26)
@@ -93,27 +93,6 @@ foreach (fileset_type IN LISTS fileset_types)
run_cmake("NotCXXSource${fileset_type}")
endforeach ()
if ("cxx_std_23" IN_LIST CMAKE_CXX_COMPILE_FEATURES)
run_cmake(CXXImportStdConfig)
run_cmake(CXXImportStdHeadTarget)
run_cmake(CXXImportStdLinkLanguage)
run_cmake(CXXImportStdInvalidGenex)
endif ()
if ("cxx_std_23" IN_LIST CMAKE_CXX_COMPILE_FEATURES AND
NOT have_cxx23_import_std)
run_cmake(NoCXX23TargetUnset)
run_cmake(NoCXX23TargetNotRequired)
run_cmake(NoCXX23TargetRequired)
endif ()
if ("cxx_std_26" IN_LIST CMAKE_CXX_COMPILE_FEATURES AND
NOT have_cxx26_import_std)
run_cmake(NoCXX26TargetUnset)
run_cmake(NoCXX26TargetNotRequired)
run_cmake(NoCXX26TargetRequired)
endif ()
run_cmake(InstallBMI)
run_cmake(InstallBMIGenericArgs)
run_cmake(InstallBMIIgnore)
@@ -233,11 +233,12 @@ if ("named" IN_LIST CMake_TEST_MODULE_COMPILATION)
if ("cxx_std_23" IN_LIST CMAKE_CXX_COMPILE_FEATURES AND
"import_std23" IN_LIST CMake_TEST_MODULE_COMPILATION)
run_cxx_module_test(imp-std)
run_cxx_module_test(imp-dummy-std)
set(RunCMake_CXXModules_NO_TEST 1)
run_cxx_module_test(imp-std-no-std-prop)
run_cxx_module_test(imp-std-no-std-json)
unset(RunCMake_CXXModules_NO_TEST)
run_cxx_module_test(imp-dummy-std)
run_cxx_module_test(imp-std-exp-no-std-build)
run_cxx_module_test(imp-std-shared)
set(RunCMake_CXXModules_INSTALL 1)
run_cxx_module_test(imp-std-exp-no-std-install)
unset(RunCMake_CXXModules_INSTALL)
@@ -249,10 +250,10 @@ if ("named" IN_LIST CMake_TEST_MODULE_COMPILATION)
set(RunCMake_CXXModules_INSTALL 1)
run_cxx_module_test(imp-std-not-in-exp-install)
unset(RunCMake_CXXModules_INSTALL)
run_cxx_module_test(imp-std-trans imp-std-trans-not-in-exp-install "-DCMAKE_PREFIX_PATH=${RunCMake_BINARY_DIR}/imp-std-not-in-exp-install-install")
run_cxx_module_test(imp-std-trans imp-std-trans-not-in-exp-install "-DCMAKE_PREFIX_PATH=${RunCMake_BINARY_DIR}/imp-std-not-in-exp-install-install" "-Dimport_std_not_in_export_cps_DIR=${RunCMake_BINARY_DIR}/imp-std-not-in-exp-install-install/lib/cmake/import_std_not_in_export_cps")
run_cxx_module_test(imp-std-trans imp-std-trans-exp-no-std-build "-DCMAKE_PREFIX_PATH=${RunCMake_BINARY_DIR}/imp-std-exp-no-std-build-build" -DEXPORT_NO_STD=1)
run_cxx_module_test(imp-std-trans imp-std-trans-exp-no-std-install "-DCMAKE_PREFIX_PATH=${RunCMake_BINARY_DIR}/imp-std-exp-no-std-install-install" -DEXPORT_NO_STD=1)
run_cxx_module_test(imp-std-trans imp-std-trans-exp-no-std-install "-DCMAKE_PREFIX_PATH=${RunCMake_BINARY_DIR}/imp-std-exp-no-std-install-install" "-Dimport_std_export_no_std_cps_DIR=${RunCMake_BINARY_DIR}/imp-std-exp-no-std-install-install/lib/cmake/import_std_export_no_std_cps" -DEXPORT_NO_STD=1)
endif ()
endif ()
endif ()
@@ -1,5 +1,5 @@
set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD
"f35a9ac6-8463-4d38-8eec-5d6008153e7d")
"25d6f6aa-be65-4692-b44e-87b23e96d4e1")
set(CMAKE_CXX_STDLIB_MODULES_JSON
"${CMAKE_CURRENT_LIST_DIR}/../dummy-std/manifest/dummy-std.modules.json"
)
@@ -9,8 +9,6 @@ project(cxx_modules_import_std CXX)
include("${CMAKE_SOURCE_DIR}/../cxx-modules-rules.cmake")
set(CMAKE_CXX_MODULE_STD 1)
add_executable(main
main.cxx)
target_compile_features(main PRIVATE cxx_std_23)
@@ -1,5 +1,5 @@
set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD
"f35a9ac6-8463-4d38-8eec-5d6008153e7d")
"25d6f6aa-be65-4692-b44e-87b23e96d4e1")
cmake_minimum_required(VERSION 3.29)
project(cxx_modules_import_std_export_no_std CXX)
@@ -16,9 +16,6 @@ target_sources(import_std_export_no_std
FILE_SET use_std TYPE CXX_MODULES FILES
impl-uses-std.cxx)
target_compile_features(import_std_export_no_std PUBLIC cxx_std_23)
set_property(TARGET import_std_export_no_std
PROPERTY
CXX_MODULE_STD "$<BOOL:$<BUILD_LOCAL_INTERFACE:1>>")
add_executable(main
main.cxx)
@@ -36,6 +33,10 @@ file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/import_std_export_no_std-config.cmake"
set(\${CMAKE_FIND_PACKAGE_NAME}_FOUND 1)
")
export(PACKAGE_INFO import_std_export_no_std_cps
EXPORT export
CXX_MODULES_DIRECTORY "import_std_export_no_std-cxx-modules-cps")
add_test(NAME main COMMAND main)
set(generator
@@ -8,8 +8,8 @@ if (NOT TARGET CXXModules::import_std_export_no_std)
"Missing imported target")
endif ()
function (check_property expected property)
get_property(actual TARGET CXXModules::import_std_export_no_std
function (check_property expected property target)
get_property(actual TARGET ${target}
PROPERTY "${property}")
if (NOT DEFINED actual)
if (NOT expected STREQUAL "<UNDEF>")
@@ -22,12 +22,11 @@ function (check_property expected property)
endif ()
endfunction ()
check_property("<UNDEF>" "IMPORTED_CXX_MODULES_INCLUDE_DIRECTORIES")
check_property("<UNDEF>" "IMPORTED_CXX_MODULES_COMPILE_DEFINITIONS")
check_property("cxx_std_23" "IMPORTED_CXX_MODULES_COMPILE_FEATURES")
check_property("" "IMPORTED_CXX_MODULES_LINK_LIBRARIES")
check_property("<UNDEF>" "INTERFACE_LINK_LIBRARIES")
check_property("$<BOOL:>" "CXX_MODULE_STD")
check_property("<UNDEF>" "IMPORTED_CXX_MODULES_INCLUDE_DIRECTORIES" CXXModules::import_std_export_no_std)
check_property("<UNDEF>" "IMPORTED_CXX_MODULES_COMPILE_DEFINITIONS" CXXModules::import_std_export_no_std)
check_property("cxx_std_23" "IMPORTED_CXX_MODULES_COMPILE_FEATURES" CXXModules::import_std_export_no_std)
check_property("" "IMPORTED_CXX_MODULES_LINK_LIBRARIES" CXXModules::import_std_export_no_std)
check_property("<UNDEF>" "INTERFACE_LINK_LIBRARIES" CXXModules::import_std_export_no_std)
# Extract the export-dependent targets from the export file.
file(STRINGS "${import_std_export_no_std_DIR}/import_std_export_no_std-targets.cmake" usage_dependent_targets
@@ -41,5 +40,17 @@ string(REPLACE "\"" "" usage_dependent_targets "${usage_dependent_targets}")
if ("@cmake_cxx_std" IN_LIST usage_dependent_targets)
message(SEND_ERROR
"The main export requires the '@cmake_cxx_std' target")
"The CMake config export requires the '@cmake_cxx_std' target")
endif ()
# CPS import test
find_package(import_std_export_no_std_cps CONFIG REQUIRED)
if (NOT TARGET import_std_export_no_std_cps::import_std_export_no_std)
message(FATAL_ERROR "Missing CPS imported target")
endif ()
check_property("<UNDEF>" "IMPORTED_CXX_MODULES_INCLUDE_DIRECTORIES" import_std_export_no_std_cps::import_std_export_no_std)
check_property("<UNDEF>" "IMPORTED_CXX_MODULES_COMPILE_DEFINITIONS" import_std_export_no_std_cps::import_std_export_no_std)
check_property("<UNDEF>" "IMPORTED_CXX_MODULES_COMPILE_FEATURES" import_std_export_no_std_cps::import_std_export_no_std)
check_property("<UNDEF>" "IMPORTED_CXX_MODULES_LINK_LIBRARIES" import_std_export_no_std_cps::import_std_export_no_std)
check_property("<UNDEF>" "INTERFACE_LINK_LIBRARIES" import_std_export_no_std_cps::import_std_export_no_std)
@@ -1,5 +1,5 @@
set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD
"f35a9ac6-8463-4d38-8eec-5d6008153e7d")
"25d6f6aa-be65-4692-b44e-87b23e96d4e1")
cmake_minimum_required(VERSION 3.29)
project(cxx_modules_import_std_export_no_std CXX)
@@ -14,9 +14,6 @@ target_sources(import_std_export_no_std
FILE_SET use_std TYPE CXX_MODULES FILES
impl-uses-std.cxx)
target_compile_features(import_std_export_no_std PUBLIC cxx_std_23)
set_property(TARGET import_std_export_no_std
PROPERTY
CXX_MODULE_STD "$<BOOL:$<BUILD_LOCAL_INTERFACE:1>>")
add_executable(main
main.cxx)
@@ -38,6 +35,11 @@ set(\${CMAKE_FIND_PACKAGE_NAME}_FOUND 1)
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/import_std_export_no_std-config.cmake"
DESTINATION "lib/cmake/import_std_export_no_std")
install(PACKAGE_INFO import_std_export_no_std_cps
EXPORT export
DESTINATION "lib/cmake/import_std_export_no_std_cps"
CXX_MODULES_DIRECTORY "import_std_export_no_std-cxx-modules-cps")
add_test(NAME main COMMAND main)
set(generator
@@ -56,6 +58,7 @@ add_test(NAME import_std_export_no_std_build
"${CMAKE_COMMAND}"
"-Dexpected_dir=${CMAKE_INSTALL_PREFIX}/lib/cxx/miu"
"-Dimport_std_export_no_std_DIR=${CMAKE_INSTALL_PREFIX}/lib/cmake/import_std_export_no_std"
"-Dimport_std_export_no_std_cps_DIR=${CMAKE_INSTALL_PREFIX}/lib/cmake/import_std_export_no_std_cps"
${generator}
-S "${CMAKE_CURRENT_SOURCE_DIR}/test"
-B "${CMAKE_CURRENT_BINARY_DIR}/test")
@@ -8,8 +8,8 @@ if (NOT TARGET CXXModules::import_std_export_no_std)
"Missing imported target")
endif ()
function (check_property expected property)
get_property(actual TARGET CXXModules::import_std_export_no_std
function (check_property expected property target)
get_property(actual TARGET ${target}
PROPERTY "${property}")
if (NOT DEFINED actual)
if (NOT expected STREQUAL "<UNDEF>")
@@ -22,12 +22,11 @@ function (check_property expected property)
endif ()
endfunction ()
check_property("<UNDEF>" "IMPORTED_CXX_MODULES_INCLUDE_DIRECTORIES")
check_property("<UNDEF>" "IMPORTED_CXX_MODULES_COMPILE_DEFINITIONS")
check_property("cxx_std_23" "IMPORTED_CXX_MODULES_COMPILE_FEATURES")
check_property("" "IMPORTED_CXX_MODULES_LINK_LIBRARIES")
check_property("<UNDEF>" "INTERFACE_LINK_LIBRARIES")
check_property("$<BOOL:>" "CXX_MODULE_STD")
check_property("<UNDEF>" "IMPORTED_CXX_MODULES_INCLUDE_DIRECTORIES" CXXModules::import_std_export_no_std)
check_property("<UNDEF>" "IMPORTED_CXX_MODULES_COMPILE_DEFINITIONS" CXXModules::import_std_export_no_std)
check_property("cxx_std_23" "IMPORTED_CXX_MODULES_COMPILE_FEATURES" CXXModules::import_std_export_no_std)
check_property("" "IMPORTED_CXX_MODULES_LINK_LIBRARIES" CXXModules::import_std_export_no_std)
check_property("<UNDEF>" "INTERFACE_LINK_LIBRARIES" CXXModules::import_std_export_no_std)
# Extract the export-dependent targets from the export file.
file(STRINGS "${import_std_export_no_std_DIR}/import_std_export_no_std-targets.cmake" usage_dependent_targets
@@ -41,5 +40,17 @@ string(REPLACE "\"" "" usage_dependent_targets "${usage_dependent_targets}")
if ("@cmake_cxx_std" IN_LIST usage_dependent_targets)
message(SEND_ERROR
"The main export requires the '@cmake_cxx_std' target")
"The CMake config export requires the '@cmake_cxx_std' target")
endif ()
# CPS import test
find_package(import_std_export_no_std_cps CONFIG REQUIRED)
if (NOT TARGET import_std_export_no_std_cps::import_std_export_no_std)
message(FATAL_ERROR "Missing CPS imported target")
endif ()
check_property("<UNDEF>" "IMPORTED_CXX_MODULES_INCLUDE_DIRECTORIES" import_std_export_no_std_cps::import_std_export_no_std)
check_property("<UNDEF>" "IMPORTED_CXX_MODULES_COMPILE_DEFINITIONS" import_std_export_no_std_cps::import_std_export_no_std)
check_property("<UNDEF>" "IMPORTED_CXX_MODULES_COMPILE_FEATURES" import_std_export_no_std_cps::import_std_export_no_std)
check_property("<UNDEF>" "IMPORTED_CXX_MODULES_LINK_LIBRARIES" import_std_export_no_std_cps::import_std_export_no_std)
check_property("<UNDEF>" "INTERFACE_LINK_LIBRARIES" import_std_export_no_std_cps::import_std_export_no_std)
@@ -0,0 +1 @@
CMAKE_CXX_STDLIB_MODULES_JSON set to empty string
@@ -1,13 +1,13 @@
set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD
"f35a9ac6-8463-4d38-8eec-5d6008153e7d")
"25d6f6aa-be65-4692-b44e-87b23e96d4e1")
cmake_minimum_required(VERSION 3.29)
project(cxx_modules_import_std_no_std_property CXX)
project(cxx_modules_import_std_no_json CXX)
set(CMAKE_CXX_STDLIB_MODULES_JSON "")
include("${CMAKE_SOURCE_DIR}/../cxx-modules-rules.cmake")
set(CMAKE_CXX_MODULE_STD 0)
add_executable(main
main.cxx)
target_compile_features(main PRIVATE cxx_std_23)
@@ -0,0 +1,5 @@
import std;
int main()
{
}
@@ -1 +0,0 @@
((GNU)?fatal error: unknown compiled module interface: no such module|(Clang)?module 'std' not found|(MSVC)?could not find module 'std')
@@ -1,6 +0,0 @@
import std;
int main(int argc, char* argv[])
{
return 0;
}
@@ -1,13 +1,11 @@
set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD
"f35a9ac6-8463-4d38-8eec-5d6008153e7d")
"25d6f6aa-be65-4692-b44e-87b23e96d4e1")
cmake_minimum_required(VERSION 3.29)
project(cxx_modules_import_std_not_in_export CXX)
include("${CMAKE_SOURCE_DIR}/../cxx-modules-rules.cmake")
set(CMAKE_CXX_MODULE_STD 1)
add_library(import_std_not_in_export)
target_sources(import_std_not_in_export
PUBLIC
@@ -31,6 +29,10 @@ file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/import_std_not_in_export-config.cmake"
set(\${CMAKE_FIND_PACKAGE_NAME}_FOUND 1)
")
export(PACKAGE_INFO import_std_not_in_export_cps
EXPORT export
CXX_MODULES_DIRECTORY "import_std_not_in_export-cxx-modules-cps")
add_test(NAME main COMMAND main)
set(generator
@@ -5,11 +5,11 @@ find_package(import_std_not_in_export REQUIRED)
if (NOT TARGET CXXModules::import_std_not_in_export)
message(FATAL_ERROR
"Missing imported target")
"Missing CMake config imported target")
endif ()
function (check_property expected property)
get_property(actual TARGET CXXModules::import_std_not_in_export
function (check_property expected property target)
get_property(actual TARGET ${target}
PROPERTY "${property}")
if (NOT DEFINED actual)
if (NOT expected STREQUAL "<UNDEF>")
@@ -22,12 +22,11 @@ function (check_property expected property)
endif ()
endfunction ()
check_property("<UNDEF>" "IMPORTED_CXX_MODULES_INCLUDE_DIRECTORIES")
check_property("<UNDEF>" "IMPORTED_CXX_MODULES_COMPILE_DEFINITIONS")
check_property("cxx_std_23" "IMPORTED_CXX_MODULES_COMPILE_FEATURES")
check_property("" "IMPORTED_CXX_MODULES_LINK_LIBRARIES")
check_property("<UNDEF>" "INTERFACE_LINK_LIBRARIES")
check_property("1" "CXX_MODULE_STD")
check_property("<UNDEF>" "IMPORTED_CXX_MODULES_INCLUDE_DIRECTORIES" CXXModules::import_std_not_in_export)
check_property("<UNDEF>" "IMPORTED_CXX_MODULES_COMPILE_DEFINITIONS" CXXModules::import_std_not_in_export)
check_property("cxx_std_23" "IMPORTED_CXX_MODULES_COMPILE_FEATURES" CXXModules::import_std_not_in_export)
check_property("" "IMPORTED_CXX_MODULES_LINK_LIBRARIES" CXXModules::import_std_not_in_export)
check_property("<UNDEF>" "INTERFACE_LINK_LIBRARIES" CXXModules::import_std_not_in_export)
# Extract the export-dependent targets from the export file.
file(STRINGS "${import_std_not_in_export_DIR}/import_std_not_in_export-targets.cmake" usage_dependent_targets
@@ -41,5 +40,17 @@ string(REPLACE "\"" "" usage_dependent_targets "${usage_dependent_targets}")
if ("@cmake_cxx_std" IN_LIST usage_dependent_targets)
message(SEND_ERROR
"The main export requires the '@cmake_cxx_std' target")
"The CMake config export requires the '@cmake_cxx_std' target")
endif ()
# CPS import test
find_package(import_std_not_in_export_cps CONFIG REQUIRED)
if (NOT TARGET import_std_not_in_export_cps::import_std_not_in_export)
message(FATAL_ERROR "Missing CPS imported target")
endif ()
check_property("<UNDEF>" "IMPORTED_CXX_MODULES_INCLUDE_DIRECTORIES" import_std_not_in_export_cps::import_std_not_in_export)
check_property("<UNDEF>" "IMPORTED_CXX_MODULES_COMPILE_DEFINITIONS" import_std_not_in_export_cps::import_std_not_in_export)
check_property("<UNDEF>" "IMPORTED_CXX_MODULES_COMPILE_FEATURES" import_std_not_in_export_cps::import_std_not_in_export)
check_property("<UNDEF>" "IMPORTED_CXX_MODULES_LINK_LIBRARIES" import_std_not_in_export_cps::import_std_not_in_export)
check_property("<UNDEF>" "INTERFACE_LINK_LIBRARIES" import_std_not_in_export_cps::import_std_not_in_export)
@@ -1,13 +1,11 @@
set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD
"f35a9ac6-8463-4d38-8eec-5d6008153e7d")
"25d6f6aa-be65-4692-b44e-87b23e96d4e1")
cmake_minimum_required(VERSION 3.29)
project(cxx_modules_import_std_not_in_export CXX)
include("${CMAKE_SOURCE_DIR}/../cxx-modules-rules.cmake")
set(CMAKE_CXX_MODULE_STD 1)
add_library(import_std_not_in_export)
target_sources(import_std_not_in_export
PUBLIC
@@ -35,6 +33,11 @@ set(\${CMAKE_FIND_PACKAGE_NAME}_FOUND 1)
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/import_std_not_in_export-config.cmake"
DESTINATION "lib/cmake/import_std_not_in_export")
install(PACKAGE_INFO import_std_not_in_export_cps
EXPORT export
DESTINATION "lib/cmake/import_std_not_in_export_cps"
CXX_MODULES_DIRECTORY "import_std_not_in_export-cxx-modules-cps")
add_test(NAME main COMMAND main)
set(generator
@@ -53,6 +56,7 @@ add_test(NAME import_std_not_in_export_build
"${CMAKE_COMMAND}"
"-Dexpected_dir=${CMAKE_INSTALL_PREFIX}/lib/cxx/miu"
"-Dimport_std_not_in_export_DIR=${CMAKE_INSTALL_PREFIX}/lib/cmake/import_std_not_in_export"
"-Dimport_std_not_in_export_cps_DIR=${CMAKE_INSTALL_PREFIX}/lib/cmake/import_std_not_in_export_cps"
${generator}
-S "${CMAKE_CURRENT_SOURCE_DIR}/test"
-B "${CMAKE_CURRENT_BINARY_DIR}/test")
@@ -8,8 +8,8 @@ if (NOT TARGET CXXModules::import_std_not_in_export)
"Missing imported target")
endif ()
function (check_property expected property)
get_property(actual TARGET CXXModules::import_std_not_in_export
function (check_property expected property target)
get_property(actual TARGET ${target}
PROPERTY "${property}")
if (NOT DEFINED actual)
if (NOT expected STREQUAL "<UNDEF>")
@@ -22,12 +22,11 @@ function (check_property expected property)
endif ()
endfunction ()
check_property("<UNDEF>" "IMPORTED_CXX_MODULES_INCLUDE_DIRECTORIES")
check_property("<UNDEF>" "IMPORTED_CXX_MODULES_COMPILE_DEFINITIONS")
check_property("cxx_std_23" "IMPORTED_CXX_MODULES_COMPILE_FEATURES")
check_property("" "IMPORTED_CXX_MODULES_LINK_LIBRARIES")
check_property("<UNDEF>" "INTERFACE_LINK_LIBRARIES")
check_property("1" "CXX_MODULE_STD")
check_property("<UNDEF>" "IMPORTED_CXX_MODULES_INCLUDE_DIRECTORIES" CXXModules::import_std_not_in_export)
check_property("<UNDEF>" "IMPORTED_CXX_MODULES_COMPILE_DEFINITIONS" CXXModules::import_std_not_in_export)
check_property("cxx_std_23" "IMPORTED_CXX_MODULES_COMPILE_FEATURES" CXXModules::import_std_not_in_export)
check_property("" "IMPORTED_CXX_MODULES_LINK_LIBRARIES" CXXModules::import_std_not_in_export)
check_property("<UNDEF>" "INTERFACE_LINK_LIBRARIES" CXXModules::import_std_not_in_export)
# Extract the export-dependent targets from the export file.
file(STRINGS "${import_std_not_in_export_DIR}/import_std_not_in_export-targets.cmake" usage_dependent_targets
@@ -41,5 +40,17 @@ string(REPLACE "\"" "" usage_dependent_targets "${usage_dependent_targets}")
if ("@cmake_cxx_std" IN_LIST usage_dependent_targets)
message(SEND_ERROR
"The main export requires the '@cmake_cxx_std' target")
"The CMake config export requires the '@cmake_cxx_std' target")
endif ()
# CPS import test
find_package(import_std_not_in_export_cps CONFIG REQUIRED)
if (NOT TARGET import_std_not_in_export_cps::import_std_not_in_export)
message(FATAL_ERROR "Missing CPS imported target")
endif ()
check_property("<UNDEF>" "IMPORTED_CXX_MODULES_INCLUDE_DIRECTORIES" import_std_not_in_export_cps::import_std_not_in_export)
check_property("<UNDEF>" "IMPORTED_CXX_MODULES_COMPILE_DEFINITIONS" import_std_not_in_export_cps::import_std_not_in_export)
check_property("<UNDEF>" "IMPORTED_CXX_MODULES_COMPILE_FEATURES" import_std_not_in_export_cps::import_std_not_in_export)
check_property("<UNDEF>" "IMPORTED_CXX_MODULES_LINK_LIBRARIES" import_std_not_in_export_cps::import_std_not_in_export)
check_property("<UNDEF>" "INTERFACE_LINK_LIBRARIES" import_std_not_in_export_cps::import_std_not_in_export)
@@ -0,0 +1,9 @@
CMake Warning \(experimental\) at .*/Modules/Compiler/CMakeCommonCompilerMacros\.cmake:[0-9]* \(cmake_language\):
CMake's support for `import std;` in C\+\+23 and newer is experimental\. It
is meant only for experimentation and feedback to CMake developers\.
Call Stack \(most recent call first\):
.*/Modules/CMakeDetermineCompilerSupport\.cmake:[0-9]* \(cmake_cxx_find_modules_json\)
.*/Modules/CMakeTestCXXCompiler\.cmake:[0-9]* \(CMAKE_DETERMINE_COMPILER_SUPPORT\)
CMakeLists\.txt:[0-9]* \(project\)
This warning is for project developers\. Use -Wno-author or -Wno-experimental
to suppress it\.
@@ -0,0 +1,54 @@
set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD
"25d6f6aa-be65-4692-b44e-87b23e96d4e1")
cmake_minimum_required(VERSION 3.29)
project(cxx_modules_import_std_shared CXX)
include("${CMAKE_SOURCE_DIR}/../cxx-modules-rules.cmake")
add_library(import_std_shared SHARED)
target_sources(import_std_shared
PUBLIC
FILE_SET use_std TYPE CXX_MODULES FILES
uses-std.cxx)
target_compile_features(import_std_shared PUBLIC cxx_std_23)
add_executable(main
main.cxx)
target_link_libraries(main PRIVATE import_std_shared)
install(TARGETS import_std_shared
EXPORT export
ARCHIVE DESTINATION "lib"
RUNTIME DESTINATION "bin"
FILE_SET use_std DESTINATION "lib/cxx/miu")
export(EXPORT export
NAMESPACE CXXModules::
FILE "${CMAKE_CURRENT_BINARY_DIR}/import_std_shared-targets.cmake")
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/import_std_shared-config.cmake"
"include(\"\${CMAKE_CURRENT_LIST_DIR}/import_std_shared-targets.cmake\")
set(\${CMAKE_FIND_PACKAGE_NAME}_FOUND 1)
")
add_test(NAME main COMMAND main)
set(generator
-G "${CMAKE_GENERATOR}")
if (CMAKE_GENERATOR_TOOLSET)
list(APPEND generator
-T "${CMAKE_GENERATOR_TOOLSET}")
endif ()
if (CMAKE_GENERATOR_PLATFORM)
list(APPEND generator
-A "${CMAKE_GENERATOR_PLATFORM}")
endif ()
add_test(NAME import_std_shared_build
COMMAND
"${CMAKE_COMMAND}"
"-Dexpected_dir=${CMAKE_CURRENT_SOURCE_DIR}"
"-DCMAKE_PREFIX_PATH=${CMAKE_CURRENT_BINARY_DIR}"
"-DCMAKE_CXX_STDLIB_MODULES_JSON=${CMAKE_CXX_STDLIB_MODULES_JSON}"
${generator}
-S "${CMAKE_CURRENT_SOURCE_DIR}/test"
-B "${CMAKE_CURRENT_BINARY_DIR}/test")
@@ -0,0 +1,7 @@
import uses_std;
int main(int argc, char* argv[])
{
static_cast<void>(use_chrono());
return 0;
}
@@ -0,0 +1,15 @@
set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD
"25d6f6aa-be65-4692-b44e-87b23e96d4e1")
cmake_minimum_required(VERSION 3.29)
project(cxx_modules_library CXX)
find_package(import_std_shared REQUIRED)
if (NOT TARGET CXXModules::import_std_shared)
message(FATAL_ERROR "Missing imported target")
endif ()
add_executable(main main.cxx)
target_compile_features(main PRIVATE cxx_std_23)
target_link_libraries(main PRIVATE CXXModules::import_std_shared)
@@ -0,0 +1,7 @@
import uses_std;
int main(int argc, char* argv[])
{
static_cast<void>(use_chrono());
return 0;
}
@@ -0,0 +1,16 @@
export module uses_std;
import std;
#ifdef _WIN32
export __declspec(dllexport) int dummy()
{
return 0;
}
#endif
export inline int use_chrono()
{
static_cast<void>(std::chrono::current_zone());
return 42;
}
@@ -1,5 +1,5 @@
set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD
"f35a9ac6-8463-4d38-8eec-5d6008153e7d")
"25d6f6aa-be65-4692-b44e-87b23e96d4e1")
cmake_minimum_required(VERSION 3.29)
@@ -13,11 +13,13 @@ else ()
set(package "import_std_not_in_export")
endif ()
find_package("${package}" REQUIRED)
set(CMAKE_CXX_MODULE_STD 0)
find_package("${package}_cps" REQUIRED)
add_executable(main
main.cxx)
target_link_libraries(main PRIVATE "CXXModules::${package}")
target_compile_features(main PRIVATE cxx_std_23)
target_link_libraries(main PRIVATE
"CXXModules::${package}"
"${package}_cps::${package}")
add_test(NAME main COMMAND main)
@@ -1,13 +1,11 @@
set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD
"f35a9ac6-8463-4d38-8eec-5d6008153e7d")
"25d6f6aa-be65-4692-b44e-87b23e96d4e1")
cmake_minimum_required(VERSION 3.29)
project(cxx_modules_import_std CXX)
include("${CMAKE_SOURCE_DIR}/../cxx-modules-rules.cmake")
set(CMAKE_CXX_MODULE_STD 1)
add_executable(main
main.cxx)
target_compile_features(main PRIVATE cxx_std_23)
@@ -2,6 +2,11 @@ import std;
int main(int argc, char* argv[])
{
// std::chrono::current_zone() references _Global_tzdb_list, which is
// provided by std.ixx.obj on MSVC. Ensure we get a failed link if this
// definition isn't available.
static_cast<void>(std::chrono::current_zone());
if (argc > 0 && argv[0]) {
std::string argv0 = argv[0];
std::cout << "program: " << argv0 << std::endl;
@@ -1,5 +1,5 @@
set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD
"f35a9ac6-8463-4d38-8eec-5d6008153e7d")
"25d6f6aa-be65-4692-b44e-87b23e96d4e1")
cmake_minimum_required(VERSION 3.29)
project(codemodel_v2_import_std CXX)
@@ -8,8 +8,6 @@ cmake_file_api(QUERY API_VERSION 1 CODEMODEL 2)
include("${CMAKE_CURRENT_SOURCE_DIR}/../../CXXModulesCompile/cxx-modules-rules.cmake")
set(CMAKE_CXX_MODULE_STD 1)
add_executable(main
main.cxx)
target_compile_features(main PRIVATE cxx_std_23)
@@ -17,8 +17,6 @@ set(vars
CMAKE_CXX_SIZEOF_DATA_PTR
CMAKE_CXX_BYTE_ORDER
CMAKE_CXX_COMPILER_ABI
CMAKE_CXX_COMPILER_IMPORT_STD
CMAKE_CXX_STDLIB_MODULES_JSON)
foreach (std IN ITEMS 26 23 20 17 14 11 98)
list(APPEND vars
@@ -13,7 +13,7 @@ if (NOT feature_present STREQUAL "FALSE")
endif ()
set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD
"f35a9ac6-8463-4d38-8eec-5d6008153e7d")
"25d6f6aa-be65-4692-b44e-87b23e96d4e1")
cmake_language(GET_EXPERIMENTAL_FEATURE_ENABLED
"CxxImportStd"
@@ -1,5 +1,5 @@
set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD
"f35a9ac6-8463-4d38-8eec-5d6008153e7d")
"25d6f6aa-be65-4692-b44e-87b23e96d4e1")
cmake_language(GET_EXPERIMENTAL_FEATURE_ENABLED
"CxxImportStd"
@@ -230,15 +230,6 @@ macro (add_language_properties lang std)
)
endmacro ()
set(_cmake_supported_import_std_experimental "")
cmake_language(GET_EXPERIMENTAL_FEATURE_ENABLED "CxxImportStd" _cmake_supported_import_std_experimental)
if(_cmake_supported_import_std_experimental)
list(APPEND properties
# property expected alias
"CXX_MODULE_STD" "ON" "<SAME>"
)
endif()
# Mock up knowing the standard flag. This doesn't actually build, so nothing
# should care at this point.
set(CMAKE_Cc_std_11_STANDARD_COMPILE_OPTION "-std=c11")