Merge topic 'imported-cxxmodules'

48ee946fdc cmExperimental: recycle the C++ modules API UUID
1a1806a71b gitlab-ci: declare `bmionly` support for modules where possible
457a12f3f9 Tests/RunCMake/CXXModules: add tests which use modules from imported targets
9b9ec70b54 Ninja: generate scanning and build rules for C++20 module synthetic targets
80ef50a191 CXXModules: add a variable for BMI-only compilation
80d6544398 cxxmodules: generate synthetic targets as an initial pass
3dc6676ecc cmSyntheticTargetCache: add a struct for synthetic target caching
cb356b540c cmCxxModuleUsageEffects: add a class to capture module usage effects
...

Acked-by: Kitware Robot <kwrobot@kitware.com>
Tested-by: buildbot <buildbot@kitware.com>
Merge-request: !8535
This commit is contained in:
Brad King
2023-08-21 13:49:24 +00:00
committed by Kitware Robot
76 changed files with 1680 additions and 74 deletions
@@ -1,4 +1,4 @@
set(CMake_TEST_MODULE_COMPILATION "named,compile_commands,collation,partitions,internal_partitions,export_bmi,install_bmi,shared" CACHE STRING "")
set(CMake_TEST_MODULE_COMPILATION "named,compile_commands,collation,partitions,internal_partitions,export_bmi,install_bmi,shared,bmionly" CACHE STRING "")
set(CMake_TEST_MODULE_COMPILATION_RULES "${CMAKE_CURRENT_LIST_DIR}/cxx_modules_rules_clang.cmake" CACHE STRING "")
include("${CMAKE_CURRENT_LIST_DIR}/configure_fedora38_common_clang.cmake")
@@ -1,4 +1,4 @@
set(CMake_TEST_MODULE_COMPILATION "named,compile_commands,collation,partitions,internal_partitions,export_bmi,install_bmi,shared" CACHE STRING "")
set(CMake_TEST_MODULE_COMPILATION "named,compile_commands,collation,partitions,internal_partitions,export_bmi,install_bmi,shared,bmionly" CACHE STRING "")
set(CMake_TEST_MODULE_COMPILATION_RULES "${CMAKE_CURRENT_LIST_DIR}/cxx_modules_rules_clang.cmake" CACHE STRING "")
include("${CMAKE_CURRENT_LIST_DIR}/configure_fedora38_common_clang.cmake")
@@ -1,4 +1,4 @@
set(CMake_TEST_MODULE_COMPILATION "named,compile_commands,collation,partitions,internal_partitions,export_bmi,install_bmi" CACHE STRING "")
set(CMake_TEST_MODULE_COMPILATION "named,compile_commands,collation,partitions,internal_partitions,export_bmi,install_bmi,bmionly" CACHE STRING "")
set(CMake_TEST_MODULE_COMPILATION_RULES "${CMAKE_CURRENT_LIST_DIR}/cxx_modules_rules_gcc.cmake" CACHE STRING "")
include("${CMAKE_CURRENT_LIST_DIR}/configure_external_test.cmake")
@@ -1,4 +1,4 @@
set(CMake_TEST_MODULE_COMPILATION "named,compile_commands,collation,partitions,internal_partitions,export_bmi,install_bmi" CACHE STRING "")
set(CMake_TEST_MODULE_COMPILATION "named,compile_commands,collation,partitions,internal_partitions,export_bmi,install_bmi,bmionly" CACHE STRING "")
set(CMake_TEST_MODULE_COMPILATION_RULES "${CMAKE_CURRENT_LIST_DIR}/cxx_modules_rules_gcc.cmake" CACHE STRING "")
include("${CMAKE_CURRENT_LIST_DIR}/configure_external_test.cmake")
@@ -1,5 +1,5 @@
if("$ENV{CMAKE_CI_BUILD_NAME}" MATCHES "(^|_)gnu(_|$)")
set(CMake_TEST_MODULE_COMPILATION "named,compile_commands,collation,partitions,internal_partitions,export_bmi,install_bmi,shared" CACHE STRING "")
set(CMake_TEST_MODULE_COMPILATION "named,compile_commands,collation,partitions,internal_partitions,export_bmi,install_bmi,shared,bmionly" CACHE STRING "")
set(CMake_TEST_MODULE_COMPILATION_RULES "${CMAKE_CURRENT_LIST_DIR}/cxx_modules_rules_clang.cmake" CACHE STRING "")
endif()
include("${CMAKE_CURRENT_LIST_DIR}/configure_windows_clang_common.cmake")
@@ -1,2 +1,2 @@
set(CMake_TEST_MODULE_COMPILATION "named,compile_commands,collation,partitions,internal_partitions,shared,export_bmi,install_bmi" CACHE STRING "")
set(CMake_TEST_MODULE_COMPILATION "named,compile_commands,collation,partitions,internal_partitions,shared,export_bmi,install_bmi,bmionly" CACHE STRING "")
set(CMake_TEST_MODULE_COMPILATION_RULES "${CMAKE_CURRENT_LIST_DIR}/cxx_modules_rules_msvc.cmake" CACHE STRING "")
+1
View File
@@ -17,3 +17,4 @@ string(CONCAT CMAKE_EXPERIMENTAL_CXX_MODULE_MAP_FLAG
" -fdeps-format=p1689r5"
# Force C++ as a language.
" -x c++")
set(CMAKE_EXPERIMENTAL_CXX_MODULE_BMI_ONLY_FLAG "-fmodule-only")
+7 -1
View File
@@ -18,7 +18,7 @@ C++20 Module APIs
=================
Variable: ``CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API``
Value: ``a816ed09-43d1-40e5-bc8c-1a2824ee194e``
Value: ``ac01f462-0f5f-432a-86aa-acef252918a6``
In order to support C++20 modules, there are a number of behaviors that have
CMake APIs to provide the required features to build and export them from a
@@ -99,6 +99,10 @@ dependencies to the file specified by the ``<DYNDEP_FILE>`` placeholder. The
``CMAKE_EXPERIMENTAL_CXX_SCANDEP_DEPFILE_FORMAT`` file may be set to ``msvc``
for scandep rules which use ``msvc``-style dependency reporting.
In order to support ``IMPORTED`` targets with associated C++20 module sources,
the ``CMAKE_EXPERIMENTAL_CXX_MODULE_BMI_ONLY_FLAG`` variable must be provided
to have the compiler only output a BMI instead of a BMI and an object file.
The module dependencies should be written in the format described
by the `P1689r5`_ paper.
@@ -113,6 +117,8 @@ For compilers that generate module maps, tell CMake as follows:
set(CMAKE_EXPERIMENTAL_CXX_MODULE_MAP_FORMAT "gcc")
set(CMAKE_EXPERIMENTAL_CXX_MODULE_MAP_FLAG
"${compiler_flags_for_module_map} -fmodule-mapper=<MODULE_MAP_FILE>")
set(CMAKE_EXPERIMENTAL_CXX_MODULE_BMI_ONLY_FLAG
"-fmodule-only")
Currently, the only supported formats are, ``clang``, ``gcc``, and ``msvc``.
The ``gcc`` format is described in the GCC documentation, but the relevant
+5
View File
@@ -240,6 +240,11 @@ Properties on Targets
/prop_tgt/IMPORTED
/prop_tgt/IMPORTED_COMMON_LANGUAGE_RUNTIME
/prop_tgt/IMPORTED_CONFIGURATIONS
/prop_tgt/IMPORTED_CXX_MODULES_COMPILE_DEFINITIONS
/prop_tgt/IMPORTED_CXX_MODULES_COMPILE_FEATURES
/prop_tgt/IMPORTED_CXX_MODULES_COMPILE_OPTIONS
/prop_tgt/IMPORTED_CXX_MODULES_INCLUDE_DIRECTORIES
/prop_tgt/IMPORTED_CXX_MODULES_LINK_LIBRARIES
/prop_tgt/IMPORTED_GLOBAL
/prop_tgt/IMPORTED_IMPLIB
/prop_tgt/IMPORTED_IMPLIB_CONFIG
@@ -0,0 +1,14 @@
IMPORTED_CXX_MODULES_COMPILE_DEFINITIONS
----------------------------------------
.. versionadded:: 3.28
.. note ::
Experimental. Gated by ``CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API``
Preprocessor definitions for compiling an ``IMPORTED`` target's C++ module
sources.
CMake will automatically drop some definitions that are not supported
by the native build tool.
@@ -0,0 +1,13 @@
IMPORTED_CXX_MODULES_COMPILE_FEATURES
-------------------------------------
.. versionadded:: 3.28
.. note ::
Experimental. Gated by ``CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API``
Compiler features enabled for this ``IMPORTED`` target's C++ modules.
The value of this property is used by the generators to set the include
paths for the compiler.
@@ -0,0 +1,13 @@
IMPORTED_CXX_MODULES_COMPILE_OPTIONS
------------------------------------
.. versionadded:: 3.28
.. note ::
Experimental. Gated by ``CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API``
List of options to pass to the compiler for this ``IMPORTED`` target's C++
modules.
.. include:: ../command/OPTIONS_SHELL.txt
@@ -0,0 +1,14 @@
IMPORTED_CXX_MODULES_INCLUDE_DIRECTORIES
----------------------------------------
.. versionadded:: 3.28
.. note ::
Experimental. Gated by ``CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API``
List of preprocessor include file search directories when compiling C++
modules for ``IMPORTED`` targets.
The value of this property is used by the generators to set the include
paths for the compiler.
@@ -0,0 +1,11 @@
IMPORTED_CXX_MODULES_LINK_LIBRARIES
-----------------------------------
.. versionadded:: 3.28
.. note ::
Experimental. Gated by ``CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API``
List of direct dependencies to use for usage requirements for C++ modules in
the target's C++ modules.
+1
View File
@@ -43,5 +43,6 @@ if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 16.0)
" > <DYNDEP_FILE>")
set(CMAKE_EXPERIMENTAL_CXX_MODULE_MAP_FORMAT "clang")
set(CMAKE_EXPERIMENTAL_CXX_MODULE_MAP_FLAG "@<MODULE_MAP_FILE>")
set(CMAKE_EXPERIMENTAL_CXX_MODULE_BMI_ONLY_FLAG "--precompile")
endif()
endif()
+1
View File
@@ -87,4 +87,5 @@ if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL "19.34")
set(CMAKE_EXPERIMENTAL_CXX_SCANDEP_DEPFILE_FORMAT "msvc")
set(CMAKE_EXPERIMENTAL_CXX_MODULE_MAP_FORMAT "msvc")
set(CMAKE_EXPERIMENTAL_CXX_MODULE_MAP_FLAG "@<MODULE_MAP_FILE>")
set(CMAKE_EXPERIMENTAL_CXX_MODULE_BMI_ONLY_FLAG "-ifcOnly;-ifcOutput;<OBJECT>")
endif ()
+5
View File
@@ -171,6 +171,8 @@ add_library(
cmCustomCommandTypes.h
cmCxxModuleMapper.cxx
cmCxxModuleMapper.h
cmCxxModuleUsageEffects.cxx
cmCxxModuleUsageEffects.h
cmDefinitions.cxx
cmDefinitions.h
cmDependencyProvider.h
@@ -299,6 +301,8 @@ add_library(
cmGraphAdjacencyList.h
cmGraphVizWriter.cxx
cmGraphVizWriter.h
cmImportedCxxModuleInfo.cxx
cmImportedCxxModuleInfo.h
cmInstallGenerator.h
cmInstallGenerator.cxx
cmInstallGetRuntimeDependenciesGenerator.h
@@ -424,6 +428,7 @@ add_library(
cmStateTypes.h
cmStringAlgorithms.cxx
cmStringAlgorithms.h
cmSyntheticTargetCache.h
cmSystemTools.cxx
cmSystemTools.h
cmTarget.cxx
+21
View File
@@ -0,0 +1,21 @@
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCxxModuleUsageEffects.h"
cmCxxModuleUsageEffects::cmCxxModuleUsageEffects(
cmGeneratorTarget const* /*gt*/)
: Hash("0000000000000000000000000000000000000000")
{
// TODO: collect information from the generator target as to what might
// affect module consumption.
}
void cmCxxModuleUsageEffects::ApplyToTarget(cmTarget* /*tgt*/)
{
// TODO: apply the information collected in the constructor
}
std::string const& cmCxxModuleUsageEffects::GetHash() const
{
return this->Hash;
}
+22
View File
@@ -0,0 +1,22 @@
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
#pragma once
#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
class cmGeneratorTarget;
class cmTarget;
class cmCxxModuleUsageEffects
{
public:
cmCxxModuleUsageEffects(cmGeneratorTarget const* gt);
void ApplyToTarget(cmTarget* tgt);
std::string const& GetHash() const;
private:
std::string Hash;
};
+44 -9
View File
@@ -73,20 +73,36 @@ Json::Value CollationInformationCxxModules(
gt->LocalGenerator, config, gt);
}
std::map<std::string, cmSourceFile const*> sf_map;
enum class CompileType
{
std::vector<cmSourceFile const*> objectSources;
gt->GetObjectSources(objectSources, config);
for (auto const* sf : objectSources) {
ObjectAndBmi,
BmiOnly,
};
std::map<std::string, std::pair<cmSourceFile const*, CompileType>> sf_map;
{
auto fill_sf_map = [gt, tgt, &sf_map](cmSourceFile const* sf,
CompileType type) {
auto full_path = sf->GetFullPath();
if (full_path.empty()) {
gt->Makefile->IssueMessage(
MessageType::INTERNAL_ERROR,
cmStrCat("Target \"", tgt->GetName(),
"\" has a full path-less source file."));
continue;
return;
}
sf_map[full_path] = sf;
sf_map[full_path] = std::make_pair(sf, type);
};
std::vector<cmSourceFile const*> objectSources;
gt->GetObjectSources(objectSources, config);
for (auto const* sf : objectSources) {
fill_sf_map(sf, CompileType::ObjectAndBmi);
}
std::vector<cmSourceFile const*> cxxModuleSources;
gt->GetCxxModuleSources(cxxModuleSources, config);
for (auto const* sf : cxxModuleSources) {
fill_sf_map(sf, CompileType::BmiOnly);
}
}
@@ -113,7 +129,8 @@ Json::Value CollationInformationCxxModules(
continue;
}
auto const* sf = lookup->second;
auto const* sf = lookup->second.first;
CompileType const ct = lookup->second.second;
if (!sf) {
gt->Makefile->IssueMessage(
@@ -123,11 +140,14 @@ Json::Value CollationInformationCxxModules(
continue;
}
auto obj_path = cb.ObjectFilePath(sf, config);
auto obj_path = ct == CompileType::ObjectAndBmi
? cb.ObjectFilePath(sf, config)
: cb.BmiFilePath(sf, config);
Json::Value& tdi_module_info = tdi_cxx_module_info[obj_path] =
Json::objectValue;
tdi_module_info["source"] = file;
tdi_module_info["bmi-only"] = ct == CompileType::BmiOnly;
tdi_module_info["relative-directory"] = files_per_dir.first;
tdi_module_info["name"] = file_set->GetName();
tdi_module_info["type"] = file_set->GetType();
@@ -269,10 +289,11 @@ void cmDyndepCollation::AddCollationInformation(
struct CxxModuleFileSet
{
std::string Name;
bool BmiOnly = false;
std::string RelativeDirectory;
std::string SourcePath;
std::string Type;
cmFileSetVisibility Visibility;
cmFileSetVisibility Visibility = cmFileSetVisibility::Private;
cm::optional<std::string> Destination;
};
@@ -356,6 +377,7 @@ cmDyndepCollation::ParseExportInfo(Json::Value const& tdi)
CxxModuleFileSet& fsi = export_info->ObjectToFileSet[i.key().asString()];
auto const& tdi_cxx_module_info = *i;
fsi.Name = tdi_cxx_module_info["name"].asString();
fsi.BmiOnly = tdi_cxx_module_info["bmi-only"].asBool();
fsi.RelativeDirectory =
tdi_cxx_module_info["relative-directory"].asString();
if (!fsi.RelativeDirectory.empty() &&
@@ -644,3 +666,16 @@ bool cmDyndepCollation::IsObjectPrivate(
auto const& file_set = fileset_info_itr->second;
return !cmFileSetVisibilityIsForInterface(file_set.Visibility);
}
bool cmDyndepCollation::IsBmiOnly(cmCxxModuleExportInfo const& exportInfo,
std::string const& object)
{
#ifdef _WIN32
auto object_path = object;
cmSystemTools::ConvertToUnixSlashes(object_path);
#else
auto const& object_path = object;
#endif
auto fs = exportInfo.ObjectToFileSet.find(object_path);
return (fs != exportInfo.ObjectToFileSet.end()) && fs->second.BmiOnly;
}
+5
View File
@@ -23,6 +23,8 @@ struct cmDyndepGeneratorCallbacks
{
std::function<std::string(cmSourceFile const* sf, std::string const& config)>
ObjectFilePath;
std::function<std::string(cmSourceFile const* sf, std::string const& config)>
BmiFilePath;
};
struct cmDyndepMetadataCallbacks
@@ -51,4 +53,7 @@ struct cmDyndepCollation
cmDyndepMetadataCallbacks const& cb);
static bool IsObjectPrivate(std::string const& object,
cmCxxModuleExportInfo const& export_info);
static bool IsBmiOnly(cmCxxModuleExportInfo const& exportInfo,
std::string const& object);
};
+1 -1
View File
@@ -21,7 +21,7 @@ namespace {
cmExperimental::FeatureData LookupTable[] = {
// CxxModuleCMakeApi
{ "CxxModuleCMakeApi",
"a816ed09-43d1-40e5-bc8c-1a2824ee194e",
"ac01f462-0f5f-432a-86aa-acef252918a6",
"CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API",
"CMake's C++ module support is experimental. It is meant only for "
"experimentation and feedback to CMake developers.",
+9
View File
@@ -126,6 +126,15 @@ bool cmExportBuildFileGenerator::GenerateMainFile(std::ostream& os)
properties);
std::string errorMessage;
if (!this->PopulateCxxModuleExportProperties(
gte, properties, cmGeneratorExpression::BuildInterface,
errorMessage)) {
this->LG->GetGlobalGenerator()->GetCMakeInstance()->IssueMessage(
MessageType::FATAL_ERROR, errorMessage,
this->LG->GetMakefile()->GetBacktrace());
return false;
}
if (!this->PopulateExportProperties(gte, properties, errorMessage)) {
this->LG->GetGlobalGenerator()->GetCMakeInstance()->IssueMessage(
MessageType::FATAL_ERROR, errorMessage,
+72
View File
@@ -9,6 +9,7 @@
#include <utility>
#include <cm/memory>
#include <cmext/string_view>
#include "cmsys/FStream.hxx"
@@ -1255,6 +1256,77 @@ void cmExportFileGenerator::GenerateImportedFileChecksCode(
os << ")\n\n";
}
bool cmExportFileGenerator::PopulateCxxModuleExportProperties(
cmGeneratorTarget const* gte, ImportPropertyMap& properties,
cmGeneratorExpression::PreprocessContext ctx, std::string& errorMessage)
{
if (!gte->HaveCxx20ModuleSources(&errorMessage)) {
return true;
}
const cm::static_string_view exportedDirectModuleProperties[] = {
"CXX_EXTENSIONS"_s,
};
for (auto const& propName : exportedDirectModuleProperties) {
auto const propNameStr = std::string(propName);
cmValue prop = gte->Target->GetComputedProperty(
propNameStr, *gte->Target->GetMakefile());
if (!prop) {
prop = gte->Target->GetProperty(propNameStr);
}
if (prop) {
properties[propNameStr] = cmGeneratorExpression::Preprocess(*prop, ctx);
}
}
const cm::static_string_view exportedModuleProperties[] = {
"INCLUDE_DIRECTORIES"_s,
"COMPILE_DEFINITIONS"_s,
"COMPILE_OPTIONS"_s,
"COMPILE_FEATURES"_s,
};
for (auto const& propName : exportedModuleProperties) {
auto const propNameStr = std::string(propName);
cmValue prop = gte->Target->GetComputedProperty(
propNameStr, *gte->Target->GetMakefile());
if (!prop) {
prop = gte->Target->GetProperty(propNameStr);
}
if (prop) {
auto const exportedPropName =
cmStrCat("IMPORTED_CXX_MODULES_", propName);
properties[exportedPropName] =
cmGeneratorExpression::Preprocess(*prop, ctx);
}
}
const cm::static_string_view exportedLinkModuleProperties[] = {
"LINK_LIBRARIES"_s,
};
for (auto const& propName : exportedLinkModuleProperties) {
auto const propNameStr = std::string(propName);
cmValue prop = gte->Target->GetComputedProperty(
propNameStr, *gte->Target->GetMakefile());
if (!prop) {
prop = gte->Target->GetProperty(propNameStr);
}
if (prop) {
auto const exportedPropName =
cmStrCat("IMPORTED_CXX_MODULES_", propName);
auto value = cmGeneratorExpression::Preprocess(*prop, ctx);
this->ResolveTargetsInGeneratorExpressions(
value, gte, cmExportFileGenerator::ReplaceFreeTargets);
std::vector<std::string> wrappedValues;
for (auto& item : cmList{ value }) {
wrappedValues.push_back(cmStrCat("$<COMPILE_ONLY:", item, '>'));
}
properties[exportedPropName] = cmJoin(wrappedValues, ";");
}
}
return true;
}
bool cmExportFileGenerator::PopulateExportProperties(
cmGeneratorTarget const* gte, ImportPropertyMap& properties,
std::string& errorMessage)
+3
View File
@@ -175,6 +175,9 @@ protected:
virtual void GenerateRequiredCMakeVersion(std::ostream& os,
const char* versionString);
bool PopulateCxxModuleExportProperties(
cmGeneratorTarget const* gte, ImportPropertyMap& properties,
cmGeneratorExpression::PreprocessContext ctx, std::string& errorMessage);
bool PopulateExportProperties(cmGeneratorTarget const* gte,
ImportPropertyMap& properties,
std::string& errorMessage);
+7
View File
@@ -126,6 +126,13 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os)
gt, cmGeneratorExpression::InstallInterface, properties);
std::string errorMessage;
if (!this->PopulateCxxModuleExportProperties(
gt, properties, cmGeneratorExpression::InstallInterface,
errorMessage)) {
cmSystemTools::Error(errorMessage);
return false;
}
if (!this->PopulateExportProperties(gt, properties, errorMessage)) {
cmSystemTools::Error(errorMessage);
return false;
+1
View File
@@ -1678,6 +1678,7 @@ Json::Value Target::DumpSource(cmGeneratorTarget::SourceAndKind const& sk,
}
switch (sk.Kind) {
case cmGeneratorTarget::SourceKindCxxModuleSource:
case cmGeneratorTarget::SourceKindObjectSource: {
source["compileGroupIndex"] =
this->AddSourceCompileGroup(sk.Source.Value, si);
+7
View File
@@ -7,6 +7,7 @@
#include <utility>
#include <vector>
#include <cmext/algorithm>
#include <cmext/string_view>
#include "cmsys/RegularExpression.hxx"
@@ -88,6 +89,12 @@ cmFileSet::cmFileSet(cmake& cmakeInstance, std::string name, std::string type,
{
}
void cmFileSet::CopyEntries(cmFileSet const* fs)
{
cm::append(this->DirectoryEntries, fs->DirectoryEntries);
cm::append(this->FileEntries, fs->FileEntries);
}
void cmFileSet::ClearDirectoryEntries()
{
this->DirectoryEntries.clear();
+2
View File
@@ -41,6 +41,8 @@ public:
const std::string& GetType() const { return this->Type; }
cmFileSetVisibility GetVisibility() const { return this->Visibility; }
void CopyEntries(cmFileSet const* fs);
void ClearDirectoryEntries();
void AddDirectoryEntry(BT<std::string> directories);
const std::vector<BT<std::string>>& GetDirectoryEntries() const
+132 -16
View File
@@ -27,7 +27,9 @@
#include "cmAlgorithms.h"
#include "cmComputeLinkInformation.h"
#include "cmCryptoHash.h"
#include "cmCustomCommandGenerator.h"
#include "cmCxxModuleUsageEffects.h"
#include "cmEvaluatedTargetProperty.h"
#include "cmExperimental.h"
#include "cmFileSet.h"
@@ -52,6 +54,7 @@
#include "cmStandardLevelResolver.h"
#include "cmState.h"
#include "cmStringAlgorithms.h"
#include "cmSyntheticTargetCache.h"
#include "cmSystemTools.h"
#include "cmTarget.h"
#include "cmTargetLinkLibraryType.h"
@@ -1071,6 +1074,12 @@ void cmGeneratorTarget::GetHeaderSources(
IMPLEMENT_VISIT(SourceKindHeader);
}
void cmGeneratorTarget::GetCxxModuleSources(
std::vector<cmSourceFile const*>& data, const std::string& config) const
{
IMPLEMENT_VISIT(SourceKindCxxModuleSource);
}
void cmGeneratorTarget::GetExtraSources(std::vector<cmSourceFile const*>& data,
const std::string& config) const
{
@@ -1953,8 +1962,12 @@ void cmGeneratorTarget::ComputeKindedSources(KindedSources& files,
// Compute the kind (classification) of this source file.
SourceKind kind;
std::string ext = cmSystemTools::LowerCase(sf->GetExtension());
cmFileSet const* fs = this->GetFileSetForSource(config, sf);
if (sf->GetCustomCommand()) {
kind = SourceKindCustomCommand;
} else if (!this->Target->IsNormal() && !this->Target->IsImported() &&
fs && (fs->GetType() == "CXX_MODULES"_s)) {
kind = SourceKindCxxModuleSource;
} else if (this->Target->GetType() == cmStateEnums::UTILITY ||
this->Target->GetType() == cmStateEnums::INTERFACE_LIBRARY
// XXX(clang-tidy): https://bugs.llvm.org/show_bug.cgi?id=44165
@@ -8220,6 +8233,96 @@ void ComputeLinkImplTransitive(cmGeneratorTarget const* self,
}
}
bool cmGeneratorTarget::DiscoverSyntheticTargets(cmSyntheticTargetCache& cache,
std::string const& config)
{
cmOptionalLinkImplementation impl;
this->ComputeLinkImplementationLibraries(config, impl, this,
LinkInterfaceFor::Link);
cmCxxModuleUsageEffects usage(this);
auto& SyntheticDeps = this->Configs[config].SyntheticDeps;
for (auto const& entry : impl.Libraries) {
auto const* gt = entry.Target;
if (!gt || !gt->IsImported()) {
continue;
}
if (gt->HaveCxx20ModuleSources()) {
auto hasher = cmCryptoHash::New("SHA3_512");
constexpr size_t HASH_TRUNCATION = 12;
auto dirhash = hasher->HashString(
gt->GetLocalGenerator()->GetCurrentBinaryDirectory());
std::string safeName = gt->GetName();
cmSystemTools::ReplaceString(safeName, ":", "_");
auto targetIdent =
hasher->HashString(cmStrCat("@d_", dirhash, "@u_", usage.GetHash()));
std::string targetName =
cmStrCat(safeName, "@synth_", targetIdent.substr(0, HASH_TRUNCATION));
// Check the cache to see if this instance of the imported target has
// already been created.
auto cached = cache.CxxModuleTargets.find(targetName);
cmGeneratorTarget const* synthDep = nullptr;
if (cached == cache.CxxModuleTargets.end()) {
auto const* model = gt->Target;
auto* mf = gt->Makefile;
auto* lg = gt->GetLocalGenerator();
auto* tgt = mf->AddSynthesizedTarget(cmStateEnums::INTERFACE_LIBRARY,
targetName);
// Copy relevant information from the existing IMPORTED target.
// Copy policies to the target.
tgt->CopyPolicyStatuses(model);
// Copy file sets.
{
auto fsNames = model->GetAllFileSetNames();
for (auto const& fsName : fsNames) {
auto const* fs = model->GetFileSet(fsName);
if (!fs) {
mf->IssueMessage(MessageType::INTERNAL_ERROR,
cmStrCat("Failed to find file set named '",
fsName, "' on target '",
tgt->GetName(), '\''));
continue;
}
auto* newFs = tgt
->GetOrCreateFileSet(fs->GetName(), fs->GetType(),
fs->GetVisibility())
.first;
newFs->CopyEntries(fs);
}
}
// Copy imported C++ module properties.
tgt->CopyImportedCxxModulesEntries(model);
// Copy other properties which may affect the C++ module BMI
// generation.
tgt->CopyImportedCxxModulesProperties(model);
// Apply usage requirements to the target.
usage.ApplyToTarget(tgt);
// Create the generator target and attach it to the local generator.
auto gtp = cm::make_unique<cmGeneratorTarget>(tgt, lg);
synthDep = gtp.get();
lg->AddGeneratorTarget(std::move(gtp));
} else {
synthDep = cached->second;
}
SyntheticDeps[gt].push_back(synthDep);
}
}
return true;
}
void cmGeneratorTarget::ComputeLinkImplementationLibraries(
const std::string& config, cmOptionalLinkImplementation& impl,
cmGeneratorTarget const* head, LinkInterfaceFor implFor) const
@@ -8227,6 +8330,7 @@ void cmGeneratorTarget::ComputeLinkImplementationLibraries(
cmLocalGenerator const* lg = this->LocalGenerator;
cmMakefile const* mf = lg->GetMakefile();
cmBTStringRange entryRange = this->Target->GetLinkImplementationEntries();
auto const& synthTargetsForConfig = this->Configs[config].SyntheticDeps;
// Collect libraries directly linked in this configuration.
for (auto const& entry : entryRange) {
// Keep this logic in sync with ExpandLinkItems.
@@ -8316,7 +8420,15 @@ void cmGeneratorTarget::ComputeLinkImplementationLibraries(
// The entry is meant for this configuration.
cmLinkItem item =
this->ResolveLinkItem(BT<std::string>(name, entry.Backtrace), lg);
if (!item.Target) {
if (item.Target) {
auto depsForTarget = synthTargetsForConfig.find(item.Target);
if (depsForTarget != synthTargetsForConfig.end()) {
for (auto const* depForTarget : depsForTarget->second) {
cmLinkItem synthItem(depForTarget, item.Cross, item.Backtrace);
impl.Libraries.emplace_back(std::move(synthItem), false);
}
}
} else {
// Report explicitly linked object files separately.
std::string const& maybeObj = item.AsStr();
if (cmSystemTools::FileIsFullPath(maybeObj)) {
@@ -8930,24 +9042,28 @@ bool cmGeneratorTarget::HaveFortranSources(std::string const& config) const
});
}
bool cmGeneratorTarget::HaveCxx20ModuleSources() const
bool cmGeneratorTarget::HaveCxx20ModuleSources(std::string* errorMessage) const
{
auto const& fs_names = this->Target->GetAllFileSetNames();
return std::any_of(fs_names.begin(), fs_names.end(),
[this](std::string const& name) -> bool {
auto const* file_set = this->Target->GetFileSet(name);
if (!file_set) {
this->Makefile->IssueMessage(
MessageType::INTERNAL_ERROR,
cmStrCat("Target \"", this->Target->GetName(),
"\" is tracked to have file set \"", name,
"\", but it was not found."));
return false;
}
return std::any_of(
fs_names.begin(), fs_names.end(),
[this, errorMessage](std::string const& name) -> bool {
auto const* file_set = this->Target->GetFileSet(name);
if (!file_set) {
auto message = cmStrCat("Target \"", this->Target->GetName(),
"\" is tracked to have file set \"", name,
"\", but it was not found.");
if (errorMessage) {
*errorMessage = std::move(message);
} else {
this->Makefile->IssueMessage(MessageType::INTERNAL_ERROR, message);
}
return false;
}
auto const& fs_type = file_set->GetType();
return fs_type == "CXX_MODULES"_s;
});
auto const& fs_type = file_set->GetType();
return fs_type == "CXX_MODULES"_s;
});
}
cmGeneratorTarget::Cxx20SupportLevel cmGeneratorTarget::HaveCxxModuleSupport(
+13 -1
View File
@@ -31,6 +31,7 @@ class cmGlobalGenerator;
class cmLocalGenerator;
class cmMakefile;
class cmSourceFile;
struct cmSyntheticTargetCache;
class cmTarget;
struct cmGeneratorExpressionContext;
@@ -116,6 +117,7 @@ public:
SourceKindCertificate,
SourceKindCustomCommand,
SourceKindExternalObject,
SourceKindCxxModuleSource,
SourceKindExtra,
SourceKindHeader,
SourceKindIDL,
@@ -186,6 +188,8 @@ public:
const std::string& config) const;
void GetHeaderSources(std::vector<cmSourceFile const*>&,
const std::string& config) const;
void GetCxxModuleSources(std::vector<cmSourceFile const*>&,
const std::string& config) const;
void GetExtraSources(std::vector<cmSourceFile const*>&,
const std::string& config) const;
void GetCustomCommands(std::vector<cmSourceFile const*>&,
@@ -929,6 +933,9 @@ public:
std::string GetImportedXcFrameworkPath(const std::string& config) const;
bool DiscoverSyntheticTargets(cmSyntheticTargetCache& cache,
std::string const& config);
private:
void AddSourceCommon(const std::string& src, bool before = false);
@@ -1264,8 +1271,11 @@ public:
*
* This will inspect the target itself to see if C++20 module
* support is expected to work based on its sources.
*
* If `errorMessage` is given a non-`nullptr`, any error message will be
* stored in it, otherwise the error will be reported directly.
*/
bool HaveCxx20ModuleSources() const;
bool HaveCxx20ModuleSources(std::string* errorMessage = nullptr) const;
enum class Cxx20SupportLevel
{
@@ -1301,6 +1311,8 @@ private:
{
bool BuiltFileSetCache = false;
std::map<std::string, cmFileSet const*> FileSetCache;
std::map<cmGeneratorTarget const*, std::vector<cmGeneratorTarget const*>>
SyntheticDeps;
};
mutable std::map<std::string, InfoByConfig> Configs;
};
+40
View File
@@ -55,6 +55,7 @@
#include "cmStateDirectory.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmSyntheticTargetCache.h"
#include "cmSystemTools.h"
#include "cmValue.h"
#include "cmVersion.h"
@@ -1560,6 +1561,17 @@ bool cmGlobalGenerator::Compute()
}
#endif
// 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?
// Maybe INTERFACE libraries with modules files should just do BMI-only?
// Make `add_dependencies(imported_target
// $<$<TARGET_NAME_IF_EXISTS:uses_imported>:synth1>
// $<$<TARGET_NAME_IF_EXISTS:other_uses_imported>:synth2>)`
if (!this->DiscoverSyntheticTargets()) {
return false;
}
// Add generator specific helper commands
for (const auto& localGen : this->LocalGenerators) {
localGen->AddHelperCommands();
@@ -1784,6 +1796,34 @@ void cmGlobalGenerator::ComputeTargetOrder(cmGeneratorTarget const* gt,
entry->second = index++;
}
bool cmGlobalGenerator::DiscoverSyntheticTargets()
{
cmSyntheticTargetCache cache;
for (auto const& gen : this->LocalGenerators) {
// Because DiscoverSyntheticTargets() adds generator targets, we need to
// cache the existing list of generator targets before starting.
std::vector<cmGeneratorTarget*> genTargets;
genTargets.reserve(gen->GetGeneratorTargets().size());
for (auto const& tgt : gen->GetGeneratorTargets()) {
genTargets.push_back(tgt.get());
}
for (auto* tgt : genTargets) {
std::vector<std::string> const& configs =
tgt->Makefile->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig);
for (auto const& config : configs) {
if (!tgt->DiscoverSyntheticTargets(cache, config)) {
return false;
}
}
}
}
return true;
}
bool cmGlobalGenerator::AddHeaderSetVerification()
{
for (auto const& gen : this->LocalGenerators) {
+2
View File
@@ -662,6 +662,8 @@ protected:
virtual bool CheckALLOW_DUPLICATE_CUSTOM_TARGETS() const;
bool DiscoverSyntheticTargets();
bool AddHeaderSetVerification();
bool AddAutomaticSources();
+9 -3
View File
@@ -2643,7 +2643,9 @@ bool cmGlobalNinjaGenerator::WriteDyndepFile(
for (cmScanDepInfo const& object : objects) {
for (auto const& p : object.Provides) {
std::string mod;
if (!p.CompiledModulePath.empty()) {
if (cmDyndepCollation::IsBmiOnly(export_info, object.PrimaryOutput)) {
mod = object.PrimaryOutput;
} else if (!p.CompiledModulePath.empty()) {
// The scanner provided the path to the module file.
mod = p.CompiledModulePath;
if (!cmSystemTools::FileIsFullPath(mod)) {
@@ -2714,8 +2716,12 @@ bool cmGlobalNinjaGenerator::WriteDyndepFile(
build.Outputs[0] = this->ConvertToNinjaPath(object.PrimaryOutput);
build.ImplicitOuts.clear();
for (auto const& p : object.Provides) {
build.ImplicitOuts.push_back(
this->ConvertToNinjaPath(mod_files[p.LogicalName].BmiPath));
auto const implicitOut =
this->ConvertToNinjaPath(mod_files[p.LogicalName].BmiPath);
// Ignore the `provides` when the BMI is the output.
if (implicitOut != build.Outputs[0]) {
build.ImplicitOuts.emplace_back(implicitOut);
}
}
build.ImplicitDeps.clear();
for (auto const& r : object.Requires) {
+76
View File
@@ -0,0 +1,76 @@
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmImportedCxxModuleInfo.h"
#include <cstddef>
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include "cmCryptoHash.h"
#include "cmList.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
bool ImportedCxxModuleLookup::Initialized() const
{
return this->DoneInit;
}
void ImportedCxxModuleLookup::Initialize(std::string const& importedModules)
{
for (auto const& entry : cmList{ importedModules }) {
auto nameSep = entry.find('=');
if (nameSep == std::string::npos) {
// Invalid entry; ignore.
continue;
}
auto name = entry.substr(0, nameSep);
auto sourceSep = entry.find(',', nameSep);
std::string source;
if (sourceSep == std::string::npos) {
source = entry.substr(nameSep + 1);
} else {
source = entry.substr(nameSep + 1, sourceSep - nameSep - 1);
}
std::vector<std::string> bmis;
if (sourceSep != std::string::npos) {
auto bmiPaths = entry.substr(sourceSep + 1);
bmis = cmSystemTools::SplitString(bmiPaths, ',');
}
this->ImportedInfo.emplace(source,
ImportedCxxModuleInfo{ name, std::move(bmis) });
}
this->DoneInit = true;
}
std::string ImportedCxxModuleLookup::BmiNameForSource(std::string const& path)
{
auto genit = this->GeneratorInfo.find(path);
if (genit != this->GeneratorInfo.end()) {
return genit->second.BmiName;
}
auto importit = this->ImportedInfo.find(path);
std::string bmiName;
auto hasher = cmCryptoHash::New("SHA3_512");
constexpr size_t HASH_TRUNCATION = 12;
if (importit != this->ImportedInfo.end()) {
auto safename = hasher->HashString(importit->second.Name);
bmiName = cmStrCat(safename.substr(0, HASH_TRUNCATION), ".bmi");
} else {
auto dirhash = hasher->HashString(path);
bmiName = cmStrCat(dirhash.substr(0, HASH_TRUNCATION), ".bmi");
}
this->GeneratorInfo.emplace(
path, ImportedCxxModuleGeneratorInfo{ &importit->second, bmiName });
return bmiName;
}
+37
View File
@@ -0,0 +1,37 @@
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
#pragma once
#include "cmConfigure.h" // IWYU pragma: keep
#include <map>
#include <string>
#include <vector>
struct ImportedCxxModuleInfo
{
std::string const Name;
std::vector<std::string> const AvailableBmis;
};
struct ImportedCxxModuleGeneratorInfo
{
ImportedCxxModuleInfo const* ImportedInfo;
std::string const BmiName;
};
struct ImportedCxxModuleLookup
{
ImportedCxxModuleLookup() = default;
~ImportedCxxModuleLookup() = default;
bool Initialized() const;
void Initialize(std::string const& importedModules);
std::string BmiNameForSource(std::string const& path);
private:
bool DoneInit = false;
std::map<std::string, ImportedCxxModuleInfo> ImportedInfo;
std::map<std::string, ImportedCxxModuleGeneratorInfo> GeneratorInfo;
};
+85 -12
View File
@@ -62,12 +62,15 @@ cmNinjaNormalTargetGenerator::~cmNinjaNormalTargetGenerator() = default;
void cmNinjaNormalTargetGenerator::Generate(const std::string& config)
{
std::string lang = this->GeneratorTarget->GetLinkerLanguage(config);
if (this->TargetLinkLanguage(config).empty()) {
cmSystemTools::Error(
cmStrCat("CMake can not determine linker language for target: ",
this->GetGeneratorTarget()->GetName()));
return;
if (this->GetGeneratorTarget()->GetType() !=
cmStateEnums::INTERFACE_LIBRARY) {
std::string lang = this->GeneratorTarget->GetLinkerLanguage(config);
if (this->TargetLinkLanguage(config).empty()) {
cmSystemTools::Error(
cmStrCat("CMake can not determine linker language for target: ",
this->GetGeneratorTarget()->GetName()));
return;
}
}
// Write the rules for each language.
@@ -87,6 +90,34 @@ void cmNinjaNormalTargetGenerator::Generate(const std::string& config)
if (this->GetGeneratorTarget()->GetType() == cmStateEnums::OBJECT_LIBRARY) {
this->WriteObjectLibStatement(config);
} else if (this->GetGeneratorTarget()->GetType() ==
cmStateEnums::INTERFACE_LIBRARY) {
bool haveCxxModuleSources = false;
if (this->GetGeneratorTarget()->HaveCxx20ModuleSources()) {
haveCxxModuleSources = true;
}
if (!haveCxxModuleSources) {
cmSystemTools::Error(cmStrCat(
"Ninja does not support INTERFACE libraries without C++ module "
"sources as a normal target: ",
this->GetGeneratorTarget()->GetName()));
return;
}
firstForConfig = true;
for (auto const& fileConfig : this->GetConfigNames()) {
if (!this->GetGlobalGenerator()
->GetCrossConfigs(fileConfig)
.count(config)) {
continue;
}
if (haveCxxModuleSources) {
this->WriteCxxModuleLibraryStatement(config, fileConfig,
firstForConfig);
}
firstForConfig = false;
}
} else {
firstForConfig = true;
for (auto const& fileConfig : this->GetConfigNames()) {
@@ -123,12 +154,26 @@ void cmNinjaNormalTargetGenerator::WriteLanguagesRules(
#endif
// Write rules for languages compiled in this target.
std::set<std::string> languages;
std::vector<cmSourceFile const*> sourceFiles;
this->GetGeneratorTarget()->GetObjectSources(sourceFiles, config);
if (this->HaveRequiredLanguages(sourceFiles, languages)) {
for (std::string const& language : languages) {
this->WriteLanguageRules(language, config);
{
std::set<std::string> languages;
std::vector<cmSourceFile const*> sourceFiles;
this->GetGeneratorTarget()->GetObjectSources(sourceFiles, config);
if (this->HaveRequiredLanguages(sourceFiles, languages)) {
for (std::string const& language : languages) {
this->WriteLanguageRules(language, config);
}
}
}
// Write rules for languages in BMI-only rules.
{
std::set<std::string> languages;
std::vector<cmSourceFile const*> sourceFiles;
this->GetGeneratorTarget()->GetCxxModuleSources(sourceFiles, config);
if (this->HaveRequiredLanguages(sourceFiles, languages)) {
for (std::string const& language : languages) {
this->WriteLanguageRules(language, config);
}
}
}
}
@@ -1637,6 +1682,34 @@ void cmNinjaNormalTargetGenerator::WriteObjectLibStatement(
this->GetTargetName(), this->GetGeneratorTarget(), config);
}
void cmNinjaNormalTargetGenerator::WriteCxxModuleLibraryStatement(
const std::string& config, const std::string& /*fileConfig*/,
bool firstForConfig)
{
// TODO: How to use `fileConfig` properly?
// Write a phony output that depends on the scanning output.
{
cmNinjaBuild build("phony");
build.Comment =
cmStrCat("Imported C++ module library ", this->GetTargetName());
this->GetLocalGenerator()->AppendTargetOutputs(this->GetGeneratorTarget(),
build.Outputs, config);
if (firstForConfig) {
this->GetLocalGenerator()->AppendTargetOutputs(
this->GetGeneratorTarget(),
this->GetGlobalGenerator()->GetByproductsForCleanTarget(config),
config);
}
build.ExplicitDeps.emplace_back(this->GetDyndepFilePath("CXX", config));
this->GetGlobalGenerator()->WriteBuild(this->GetCommonFileStream(), build);
}
// Add aliases for the target name.
this->GetGlobalGenerator()->AddTargetAlias(
this->GetTargetName(), this->GetGeneratorTarget(), config);
}
cmGeneratorTarget::Names cmNinjaNormalTargetGenerator::TargetNames(
const std::string& config) const
{
+3
View File
@@ -49,6 +49,9 @@ private:
const std::string& output);
void WriteObjectLibStatement(const std::string& config);
void WriteCxxModuleLibraryStatement(const std::string& config,
const std::string& fileConfig,
bool firstForConfig);
std::vector<std::string> ComputeLinkCmd(const std::string& config);
std::vector<std::string> ComputeDeviceLinkCmd();
+214 -8
View File
@@ -28,6 +28,7 @@
#include "cmGeneratedFileStream.h"
#include "cmGeneratorExpression.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalCommonGenerator.h"
#include "cmGlobalNinjaGenerator.h"
#include "cmList.h"
#include "cmLocalGenerator.h"
@@ -59,8 +60,13 @@ std::unique_ptr<cmNinjaTargetGenerator> cmNinjaTargetGenerator::New(
case cmStateEnums::OBJECT_LIBRARY:
return cm::make_unique<cmNinjaNormalTargetGenerator>(target);
case cmStateEnums::UTILITY:
case cmStateEnums::INTERFACE_LIBRARY:
if (target->HaveCxx20ModuleSources()) {
return cm::make_unique<cmNinjaNormalTargetGenerator>(target);
}
CM_FALLTHROUGH;
case cmStateEnums::UTILITY:
case cmStateEnums::GLOBAL_TARGET:
return cm::make_unique<cmNinjaUtilityTargetGenerator>(target);
@@ -167,7 +173,7 @@ std::string cmNinjaTargetGenerator::OrderDependsTargetForTarget(
// Refactor it.
std::string cmNinjaTargetGenerator::ComputeFlagsForObject(
cmSourceFile const* source, const std::string& language,
const std::string& config)
const std::string& config, const std::string& objectFileName)
{
std::unordered_map<std::string, std::string> pchSources;
std::vector<std::string> architectures =
@@ -247,6 +253,18 @@ std::string cmNinjaTargetGenerator::ComputeFlagsForObject(
"\nin a file set of type \"", fs->GetType(),
R"(" but the source is not classified as a "CXX" source.)"));
}
if (!this->GeneratorTarget->Target->IsNormal()) {
auto flag = this->GetMakefile()->GetSafeDefinition(
"CMAKE_EXPERIMENTAL_CXX_MODULE_BMI_ONLY_FLAG");
cmRulePlaceholderExpander::RuleVariables compileObjectVars;
compileObjectVars.Object = objectFileName.c_str();
auto rulePlaceholderExpander =
this->GetLocalGenerator()->CreateRulePlaceholderExpander();
rulePlaceholderExpander->ExpandRuleVariables(this->GetLocalGenerator(),
flag, compileObjectVars);
this->LocalGenerator->AppendCompileOptions(flags, flag);
}
}
return flags;
@@ -394,6 +412,31 @@ std::string cmNinjaTargetGenerator::GetObjectFilePath(
return path;
}
std::string cmNinjaTargetGenerator::GetBmiFilePath(
cmSourceFile const* source, const std::string& config) const
{
std::string path = this->LocalGenerator->GetHomeRelativeOutputPath();
if (!path.empty()) {
path += '/';
}
auto& importedConfigInfo = this->Configs.at(config).ImportedCxxModules;
if (!importedConfigInfo.Initialized()) {
std::string configUpper = cmSystemTools::UpperCase(config);
std::string propName = cmStrCat("IMPORTED_CXX_MODULES_", configUpper);
auto value = this->GeneratorTarget->GetSafeProperty(propName);
importedConfigInfo.Initialize(value);
}
std::string bmiName =
importedConfigInfo.BmiNameForSource(source->GetFullPath());
path += cmStrCat(
this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget),
this->GetGlobalGenerator()->ConfigDirectory(config), '/', bmiName);
return path;
}
std::string cmNinjaTargetGenerator::GetClangTidyReplacementsFilePath(
std::string const& directory, cmSourceFile const& source,
std::string const& config) const
@@ -1027,6 +1070,16 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatements(
}
}
{
std::vector<cmSourceFile const*> bmiOnlySources;
this->GeneratorTarget->GetCxxModuleSources(bmiOnlySources, config);
for (cmSourceFile const* sf : bmiOnlySources) {
this->WriteCxxModuleBmiBuildStatement(sf, config, fileConfig,
firstForConfig);
}
}
for (auto const& langScanningFiles : this->Configs[config].ScanningInfo) {
std::string const& language = langScanningFiles.first;
std::vector<ScanningFiles> const& scanningFiles = langScanningFiles.second;
@@ -1149,22 +1202,22 @@ cmNinjaBuild GetScanBuildStatement(const std::string& ruleName,
scanBuild.Variables["OBJ_FILE"] = objectFileName;
// Tell dependency scanner where to store dyndep intermediate results.
std::string const& ddiFile = cmStrCat(objectFileName, ".ddi");
scanBuild.Variables["DYNDEP_INTERMEDIATE_FILE"] = ddiFile;
std::string ddiFileName = cmStrCat(objectFileName, ".ddi");
scanBuild.Variables["DYNDEP_INTERMEDIATE_FILE"] = ddiFileName;
// Outputs of the scan/preprocessor build statement.
if (compilePP) {
scanBuild.Outputs.push_back(ppFileName);
scanBuild.ImplicitOuts.push_back(ddiFile);
scanBuild.ImplicitOuts.push_back(ddiFileName);
} else {
scanBuild.Outputs.push_back(ddiFile);
scanBuild.Outputs.push_back(ddiFileName);
scanBuild.Variables["PREPROCESSED_OUTPUT_FILE"] = ppFileName;
if (!compilationPreprocesses) {
// Compilation does not preprocess and we are not compiling an
// already-preprocessed source. Make compilation depend on the scan
// results to honor implicit dependencies discovered during scanning
// (such as Fortran INCLUDE directives).
objBuild.ImplicitDeps.emplace_back(ddiFile);
objBuild.ImplicitDeps.emplace_back(ddiFileName);
}
}
@@ -1214,7 +1267,8 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement(
cmNinjaBuild objBuild(this->LanguageCompilerRule(
language, config, needDyndep ? WithScanning::Yes : WithScanning::No));
cmNinjaVars& vars = objBuild.Variables;
vars["FLAGS"] = this->ComputeFlagsForObject(source, language, config);
vars["FLAGS"] =
this->ComputeFlagsForObject(source, language, config, objectFileName);
vars["DEFINES"] = this->ComputeDefines(source, language, config);
vars["INCLUDES"] = this->ComputeIncludes(source, language, config);
@@ -1545,6 +1599,155 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement(
}
}
void cmNinjaTargetGenerator::WriteCxxModuleBmiBuildStatement(
cmSourceFile const* source, const std::string& config,
const std::string& fileConfig, bool firstForConfig)
{
std::string const language = source->GetLanguage();
if (language != "CXX"_s) {
this->GetMakefile()->IssueMessage(
MessageType::FATAL_ERROR,
cmStrCat("Source file '", source->GetFullPath(), "' of target '",
this->GetTargetName(), "' is a '", language,
"' source but must be 'CXX' in order to have a BMI build "
"statement generated."));
return;
}
std::string const sourceFilePath = this->GetCompiledSourceNinjaPath(source);
std::string const bmiDir = this->ConvertToNinjaPath(
cmStrCat(this->GeneratorTarget->GetSupportDirectory(),
this->GetGlobalGenerator()->ConfigDirectory(config)));
std::string const bmiFileName =
this->ConvertToNinjaPath(this->GetBmiFilePath(source, config));
std::string const bmiFileDir = cmSystemTools::GetFilenamePath(bmiFileName);
int const commandLineLengthLimit = this->ForceResponseFile() ? -1 : 0;
cmNinjaBuild bmiBuild(
this->LanguageCompilerRule(language, config, WithScanning::Yes));
cmNinjaVars& vars = bmiBuild.Variables;
vars["FLAGS"] =
this->ComputeFlagsForObject(source, language, config, bmiFileName);
vars["DEFINES"] = this->ComputeDefines(source, language, config);
vars["INCLUDES"] = this->ComputeIncludes(source, language, config);
if (this->GetMakefile()->GetSafeDefinition(
cmStrCat("CMAKE_", language, "_DEPFILE_FORMAT")) != "msvc"_s) {
bool replaceExt(false);
if (!language.empty()) {
std::string repVar =
cmStrCat("CMAKE_", language, "_DEPFILE_EXTENSION_REPLACE");
replaceExt = this->Makefile->IsOn(repVar);
}
if (!replaceExt) {
// use original code
vars["DEP_FILE"] = this->GetLocalGenerator()->ConvertToOutputFormat(
cmStrCat(bmiFileName, ".d"), cmOutputConverter::SHELL);
} else {
// Replace the original source file extension with the
// depend file extension.
std::string dependFileName = cmStrCat(
cmSystemTools::GetFilenameWithoutLastExtension(bmiFileName), ".d");
vars["DEP_FILE"] = this->GetLocalGenerator()->ConvertToOutputFormat(
cmStrCat(bmiFileDir, '/', dependFileName), cmOutputConverter::SHELL);
}
}
std::string d =
this->GeneratorTarget->GetClangTidyExportFixesDirectory(language);
if (!d.empty()) {
this->GlobalCommonGenerator->AddClangTidyExportFixesDir(d);
std::string fixesFile =
this->GetClangTidyReplacementsFilePath(d, *source, config);
this->GlobalCommonGenerator->AddClangTidyExportFixesFile(fixesFile);
cmSystemTools::MakeDirectory(cmSystemTools::GetFilenamePath(fixesFile));
fixesFile = this->ConvertToNinjaPath(fixesFile);
vars["CLANG_TIDY_EXPORT_FIXES"] = fixesFile;
}
if (firstForConfig) {
this->ExportObjectCompileCommand(
language, sourceFilePath, bmiDir, bmiFileName, bmiFileDir, vars["FLAGS"],
vars["DEFINES"], vars["INCLUDES"], config);
}
bmiBuild.Outputs.push_back(bmiFileName);
bmiBuild.ExplicitDeps.push_back(sourceFilePath);
std::vector<std::string> depList;
std::vector<std::string> architectures =
this->GeneratorTarget->GetAppleArchs(config, language);
if (architectures.empty()) {
architectures.emplace_back();
}
bmiBuild.OrderOnlyDeps.push_back(this->OrderDependsTargetForTarget(config));
// For some cases we scan to dynamically discover dependencies.
std::string modmapFormat;
if (true) {
std::string const modmapFormatVar =
cmStrCat("CMAKE_EXPERIMENTAL_", language, "_MODULE_MAP_FORMAT");
modmapFormat = this->Makefile->GetSafeDefinition(modmapFormatVar);
}
{
bool const compilePPWithDefines = this->CompileWithDefines(language);
std::string scanRuleName = this->LanguageScanRule(language, config);
std::string ppFileName = cmStrCat(bmiFileName, ".ddi.i");
cmNinjaBuild ppBuild = GetScanBuildStatement(
scanRuleName, ppFileName, false, compilePPWithDefines, true, bmiBuild,
vars, bmiFileName, this->LocalGenerator);
ScanningFiles scanningFiles;
if (firstForConfig) {
scanningFiles.ScanningOutput = cmStrCat(bmiFileName, ".ddi");
}
this->addPoolNinjaVariable("JOB_POOL_COMPILE", this->GetGeneratorTarget(),
ppBuild.Variables);
this->GetGlobalGenerator()->WriteBuild(this->GetImplFileStream(fileConfig),
ppBuild, commandLineLengthLimit);
std::string const dyndep = this->GetDyndepFilePath(language, config);
bmiBuild.OrderOnlyDeps.push_back(dyndep);
vars["dyndep"] = dyndep;
if (!modmapFormat.empty()) {
std::string ddModmapFile = cmStrCat(bmiFileName, ".modmap");
vars["DYNDEP_MODULE_MAP_FILE"] = ddModmapFile;
scanningFiles.ModuleMapFile = std::move(ddModmapFile);
}
if (!scanningFiles.IsEmpty()) {
this->Configs[config].ScanningInfo[language].emplace_back(scanningFiles);
}
}
this->EnsureParentDirectoryExists(bmiFileName);
vars["OBJECT_DIR"] = this->GetLocalGenerator()->ConvertToOutputFormat(
bmiDir, cmOutputConverter::SHELL);
vars["OBJECT_FILE_DIR"] = this->GetLocalGenerator()->ConvertToOutputFormat(
bmiFileDir, cmOutputConverter::SHELL);
this->addPoolNinjaVariable("JOB_POOL_COMPILE", this->GetGeneratorTarget(),
vars);
this->SetMsvcTargetPdbVariable(vars, config);
bmiBuild.RspFile = cmStrCat(bmiFileName, ".rsp");
this->GetGlobalGenerator()->WriteBuild(this->GetImplFileStream(fileConfig),
bmiBuild, commandLineLengthLimit);
}
void cmNinjaTargetGenerator::WriteTargetDependInfo(std::string const& lang,
const std::string& config)
{
@@ -1605,6 +1808,9 @@ void cmNinjaTargetGenerator::WriteTargetDependInfo(std::string const& lang,
cb.ObjectFilePath = [this](cmSourceFile const* sf, std::string const& cnf) {
return this->GetObjectFilePath(sf, cnf);
};
cb.BmiFilePath = [this](cmSourceFile const* sf, std::string const& cnf) {
return this->GetBmiFilePath(sf, cnf);
};
#if !defined(CMAKE_BOOTSTRAP)
cmDyndepCollation::AddCollationInformation(tdi, this->GeneratorTarget,
+11 -1
View File
@@ -15,6 +15,7 @@
#include "cmCommonTargetGenerator.h"
#include "cmGlobalNinjaGenerator.h"
#include "cmImportedCxxModuleInfo.h"
#include "cmNinjaTypes.h"
#include "cmOSXBundleGenerator.h"
@@ -91,7 +92,8 @@ protected:
*/
std::string ComputeFlagsForObject(cmSourceFile const* source,
const std::string& language,
const std::string& config);
const std::string& config,
const std::string& objectFileName);
void AddIncludeFlags(std::string& flags, std::string const& lang,
const std::string& config) override;
@@ -129,6 +131,8 @@ protected:
/// @return the object file path for the given @a source.
std::string GetObjectFilePath(cmSourceFile const* source,
const std::string& config) const;
std::string GetBmiFilePath(cmSourceFile const* source,
const std::string& config) const;
/// @return the preprocessed source file path for the given @a source.
std::string GetPreprocessedFilePath(cmSourceFile const* source,
@@ -163,6 +167,10 @@ protected:
void WriteObjectBuildStatements(const std::string& config,
const std::string& fileConfig,
bool firstForConfig);
void WriteCxxModuleBmiBuildStatement(cmSourceFile const* source,
const std::string& config,
const std::string& fileConfig,
bool firstForConfig);
void WriteObjectBuildStatement(cmSourceFile const* source,
const std::string& config,
const std::string& fileConfig,
@@ -239,6 +247,8 @@ private:
cmNinjaDeps Objects;
// Dyndep Support
std::map<std::string, std::vector<ScanningFiles>> ScanningInfo;
// Imported C++ module info.
mutable ImportedCxxModuleLookup ImportedCxxModules;
// Swift Support
Json::Value SwiftOutputMap;
std::vector<cmCustomCommand const*> CustomCommands;
+15
View File
@@ -0,0 +1,15 @@
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
#pragma once
#include "cmConfigure.h" // IWYU pragma: keep
#include <map>
#include <string>
class cmGeneratorTarget;
struct cmSyntheticTargetCache
{
std::map<std::string, cmGeneratorTarget const*> CxxModuleTargets;
};
+227 -6
View File
@@ -246,9 +246,9 @@ struct UsageRequirementProperty
{
}
void CopyFromDirectory(cmBTStringRange directoryEntries)
void CopyFromEntries(cmBTStringRange entries)
{
return cm::append(this->Entries, directoryEntries);
return cm::append(this->Entries, entries);
}
enum class Action
@@ -673,6 +673,11 @@ public:
UsageRequirementProperty InterfaceLinkLibraries;
UsageRequirementProperty InterfaceLinkLibrariesDirect;
UsageRequirementProperty InterfaceLinkLibrariesDirectExclude;
UsageRequirementProperty ImportedCxxModulesIncludeDirectories;
UsageRequirementProperty ImportedCxxModulesCompileDefinitions;
UsageRequirementProperty ImportedCxxModulesCompileFeatures;
UsageRequirementProperty ImportedCxxModulesCompileOptions;
UsageRequirementProperty ImportedCxxModulesLinkLibraries;
FileSetType HeadersFileSets;
FileSetType CxxModulesFileSets;
@@ -723,6 +728,14 @@ cmTargetInternals::cmTargetInternals()
, InterfaceLinkLibrariesDirect("INTERFACE_LINK_LIBRARIES_DIRECT"_s)
, InterfaceLinkLibrariesDirectExclude(
"INTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE"_s)
, ImportedCxxModulesIncludeDirectories(
"IMPORTED_CXX_MODULES_INCLUDE_DIRECTORIES"_s)
, ImportedCxxModulesCompileDefinitions(
"IMPORTED_CXX_MODULES_COMPILE_DEFINITIONS"_s)
, ImportedCxxModulesCompileFeatures(
"IMPORTED_CXX_MODULES_COMPILE_FEATURES"_s)
, ImportedCxxModulesCompileOptions("IMPORTED_CXX_MODULES_COMPILE_OPTIONS"_s)
, ImportedCxxModulesLinkLibraries("IMPORTED_CXX_MODULES_LINK_LIBRARIES"_s)
, HeadersFileSets("HEADERS"_s, "HEADER_DIRS"_s, "HEADER_SET"_s,
"HEADER_DIRS_"_s, "HEADER_SET_"_s, "Header"_s,
"The default header set"_s, "Header set"_s,
@@ -951,7 +964,7 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type,
if (this->IsNormal()) {
// Initialize the INCLUDE_DIRECTORIES property based on the current value
// of the same directory property:
this->impl->IncludeDirectories.CopyFromDirectory(
this->impl->IncludeDirectories.CopyFromEntries(
this->impl->Makefile->GetIncludeDirectoriesEntries());
{
@@ -960,11 +973,11 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type,
sysInc.end());
}
this->impl->CompileOptions.CopyFromDirectory(
this->impl->CompileOptions.CopyFromEntries(
this->impl->Makefile->GetCompileOptionsEntries());
this->impl->LinkOptions.CopyFromDirectory(
this->impl->LinkOptions.CopyFromEntries(
this->impl->Makefile->GetLinkOptionsEntries());
this->impl->LinkDirectories.CopyFromDirectory(
this->impl->LinkDirectories.CopyFromEntries(
this->impl->Makefile->GetLinkDirectoriesEntries());
}
@@ -1735,6 +1748,186 @@ cmBTStringRange cmTarget::GetLinkInterfaceDirectExcludeEntries() const
return cmMakeRange(this->impl->InterfaceLinkLibrariesDirectExclude.Entries);
}
void cmTarget::CopyPolicyStatuses(cmTarget const* tgt)
{
// Normal targets cannot be the target of a copy.
assert(!this->IsNormal());
// Imported targets cannot be the target of a copy.
assert(!this->IsImported());
// Only imported targets can be the source of a copy.
assert(tgt->IsImported());
this->impl->PolicyMap = tgt->impl->PolicyMap;
}
void cmTarget::CopyImportedCxxModulesEntries(cmTarget const* tgt)
{
// Normal targets cannot be the target of a copy.
assert(!this->IsNormal());
// Imported targets cannot be the target of a copy.
assert(!this->IsImported());
// Only imported targets can be the source of a copy.
assert(tgt->IsImported());
this->impl->IncludeDirectories.Entries.clear();
this->impl->IncludeDirectories.CopyFromEntries(
cmMakeRange(tgt->impl->ImportedCxxModulesIncludeDirectories.Entries));
this->impl->CompileDefinitions.Entries.clear();
this->impl->CompileDefinitions.CopyFromEntries(
cmMakeRange(tgt->impl->ImportedCxxModulesCompileDefinitions.Entries));
this->impl->CompileFeatures.Entries.clear();
this->impl->CompileFeatures.CopyFromEntries(
cmMakeRange(tgt->impl->ImportedCxxModulesCompileFeatures.Entries));
this->impl->CompileOptions.Entries.clear();
this->impl->CompileOptions.CopyFromEntries(
cmMakeRange(tgt->impl->ImportedCxxModulesCompileOptions.Entries));
this->impl->LinkLibraries.Entries.clear();
this->impl->LinkLibraries.CopyFromEntries(
cmMakeRange(tgt->impl->LinkLibraries.Entries));
// Copy the C++ module fileset entries from `tgt`'s `INTERFACE` to this
// target's `PRIVATE`.
this->impl->CxxModulesFileSets.SelfEntries.Entries.clear();
this->impl->CxxModulesFileSets.SelfEntries.Entries =
tgt->impl->CxxModulesFileSets.InterfaceEntries.Entries;
}
void cmTarget::CopyImportedCxxModulesProperties(cmTarget const* tgt)
{
// Normal targets cannot be the target of a copy.
assert(!this->IsNormal());
// Imported targets cannot be the target of a copy.
assert(!this->IsImported());
// Only imported targets can be the source of a copy.
assert(tgt->IsImported());
// The list of properties that are relevant here include:
// - compilation-specific properties for any language or platform
// - compilation-specific properties for C++
// - build graph-specific properties that affect compilation
// - IDE metadata properties
// - static analysis properties
static const std::string propertiesToCopy[] = {
// Compilation properties
"DEFINE_SYMBOL",
"DEPRECATION",
"NO_SYSTEM_FROM_IMPORTED",
"POSITION_INDEPENDENT_CODE",
"VISIBILITY_INLINES_HIDDEN",
// -- Platforms
// ---- Android
"ANDROID_API",
"ANDROID_API_MIN",
"ANDROID_ARCH",
"ANDROID_STL_TYPE",
// ---- macOS
"OSX_ARCHITECTURES",
// ---- Windows
"MSVC_DEBUG_INFORMATION_FORMAT",
"MSVC_RUNTIME_LIBRARY",
"VS_PLATFORM_TOOLSET",
// ---- OpenWatcom
"WATCOM_RUNTIME_LIBRARY",
// -- Language
// ---- C++
"CXX_COMPILER_LAUNCHER",
"CXX_STANDARD",
"CXX_STANDARD_REQUIRED",
"CXX_EXTENSIONS",
"CXX_VISIBILITY_PRESET",
// Static analysis
"CXX_CLANG_TIDY",
"CXX_CLANG_TIDY_EXPORT_FIXES_DIR",
"CXX_CPPLINT",
"CXX_CPPCHECK",
"CXX_INCLUDE_WHAT_YOU_USE",
// Build graph properties
"EXCLUDE_FROM_ALL",
"EXCLUDE_FROM_DEFAULT_BUILD",
"OPTIMIZE_DEPENDENCIES",
// -- Ninja
"JOB_POOL_COMPILE",
// -- Visual Studio
"VS_NO_COMPILE_BATCHING",
"VS_PROJECT_IMPORT",
// Metadata
"EchoString",
"EXPORT_COMPILE_COMMANDS",
"FOLDER",
"LABELS",
"PROJECT_LABEL",
"SYSTEM",
};
auto copyProperty = [this, tgt](std::string const& prop) -> cmValue {
cmValue value = tgt->GetProperty(prop);
// Always set the property; it may have been explicitly unset.
this->SetProperty(prop, value);
return value;
};
for (auto const& prop : propertiesToCopy) {
copyProperty(prop);
}
static const cm::static_string_view perConfigPropertiesToCopy[] = {
"EXCLUDE_FROM_DEFAULT_BUILD_"_s,
"IMPORTED_CXX_MODULES_"_s,
"MAP_IMPORTED_CONFIG_"_s,
"OSX_ARCHITECTURES_"_s,
};
std::vector<std::string> configNames =
this->impl->Makefile->GetGeneratorConfigs(cmMakefile::ExcludeEmptyConfig);
for (std::string const& configName : configNames) {
std::string configUpper = cmSystemTools::UpperCase(configName);
for (auto const& perConfigProp : perConfigPropertiesToCopy) {
copyProperty(cmStrCat(perConfigProp, configUpper));
}
}
if (this->GetGlobalGenerator()->IsXcode()) {
cmValue xcodeGenerateScheme = copyProperty("XCODE_GENERATE_SCHEME");
// TODO: Make sure these show up on the imported target in the first place
// XCODE_ATTRIBUTE_???
if (xcodeGenerateScheme.IsOn()) {
#ifdef __APPLE__
static const std::string xcodeSchemePropertiesToCopy[] = {
// FIXME: Do all of these apply? Do they matter?
"XCODE_SCHEME_ADDRESS_SANITIZER",
"XCODE_SCHEME_ADDRESS_SANITIZER_USE_AFTER_RETURN",
"XCODE_SCHEME_DISABLE_MAIN_THREAD_CHECKER",
"XCODE_SCHEME_DYNAMIC_LIBRARY_LOADS",
"XCODE_SCHEME_DYNAMIC_LINKER_API_USAGE",
"XCODE_SCHEME_ENABLE_GPU_API_VALIDATION",
"XCODE_SCHEME_ENABLE_GPU_SHADER_VALIDATION",
"XCODE_SCHEME_GUARD_MALLOC",
"XCODE_SCHEME_LAUNCH_CONFIGURATION",
"XCODE_SCHEME_MAIN_THREAD_CHECKER_STOP",
"XCODE_SCHEME_MALLOC_GUARD_EDGES",
"XCODE_SCHEME_MALLOC_SCRIBBLE",
"XCODE_SCHEME_MALLOC_STACK",
"XCODE_SCHEME_THREAD_SANITIZER",
"XCODE_SCHEME_THREAD_SANITIZER_STOP",
"XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER",
"XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER_STOP",
"XCODE_SCHEME_ZOMBIE_OBJECTS",
};
for (auto const& xcodeProperty : xcodeSchemePropertiesToCopy) {
copyProperty(xcodeProperty);
}
#endif
}
}
}
cmBTStringRange cmTarget::GetHeaderSetsEntries() const
{
return cmMakeRange(this->impl->HeadersFileSets.SelfEntries.Entries);
@@ -1777,6 +1970,11 @@ MAKE_PROP(IMPORTED);
MAKE_PROP(IMPORTED_GLOBAL);
MAKE_PROP(INCLUDE_DIRECTORIES);
MAKE_PROP(LINK_OPTIONS);
MAKE_PROP(IMPORTED_CXX_MODULES_INCLUDE_DIRECTORIES);
MAKE_PROP(IMPORTED_CXX_MODULES_COMPILE_DEFINITIONS);
MAKE_PROP(IMPORTED_CXX_MODULES_COMPILE_FEATURES);
MAKE_PROP(IMPORTED_CXX_MODULES_COMPILE_OPTIONS);
MAKE_PROP(IMPORTED_CXX_MODULES_LINK_LIBRARIES);
MAKE_PROP(LINK_DIRECTORIES);
MAKE_PROP(LINK_LIBRARIES);
MAKE_PROP(MANUALLY_ADDED_DEPENDENCIES);
@@ -1846,6 +2044,11 @@ void cmTarget::SetProperty(const std::string& prop, cmValue value)
&this->impl->InterfaceLinkLibraries,
&this->impl->InterfaceLinkLibrariesDirect,
&this->impl->InterfaceLinkLibrariesDirectExclude,
&this->impl->ImportedCxxModulesIncludeDirectories,
&this->impl->ImportedCxxModulesCompileDefinitions,
&this->impl->ImportedCxxModulesCompileFeatures,
&this->impl->ImportedCxxModulesCompileOptions,
&this->impl->ImportedCxxModulesLinkLibraries,
};
for (auto* usageRequirement : usageRequirements) {
@@ -2019,6 +2222,11 @@ void cmTarget::AppendProperty(const std::string& prop,
&this->impl->InterfaceLinkLibraries,
&this->impl->InterfaceLinkLibrariesDirect,
&this->impl->InterfaceLinkLibrariesDirectExclude,
&this->impl->ImportedCxxModulesIncludeDirectories,
&this->impl->ImportedCxxModulesCompileDefinitions,
&this->impl->ImportedCxxModulesCompileFeatures,
&this->impl->ImportedCxxModulesCompileOptions,
&this->impl->ImportedCxxModulesLinkLibraries,
};
for (auto* usageRequirement : usageRequirements) {
@@ -2445,6 +2653,11 @@ cmValue cmTarget::GetProperty(const std::string& prop) const
propINTERFACE_LINK_LIBRARIES,
propINTERFACE_LINK_LIBRARIES_DIRECT,
propINTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE,
propIMPORTED_CXX_MODULES_INCLUDE_DIRECTORIES,
propIMPORTED_CXX_MODULES_COMPILE_DEFINITIONS,
propIMPORTED_CXX_MODULES_COMPILE_FEATURES,
propIMPORTED_CXX_MODULES_COMPILE_OPTIONS,
propIMPORTED_CXX_MODULES_LINK_LIBRARIES,
};
if (specialProps.count(prop)) {
if (prop == propC_STANDARD || prop == propCXX_STANDARD ||
@@ -2470,6 +2683,11 @@ cmValue cmTarget::GetProperty(const std::string& prop) const
&this->impl->InterfaceLinkLibraries,
&this->impl->InterfaceLinkLibrariesDirect,
&this->impl->InterfaceLinkLibrariesDirectExclude,
&this->impl->ImportedCxxModulesIncludeDirectories,
&this->impl->ImportedCxxModulesCompileDefinitions,
&this->impl->ImportedCxxModulesCompileFeatures,
&this->impl->ImportedCxxModulesCompileOptions,
&this->impl->ImportedCxxModulesLinkLibraries,
};
for (auto const* usageRequirement : usageRequirements) {
@@ -2675,6 +2893,9 @@ bool cmTarget::CanCompileSources() const
if (this->IsImported()) {
return false;
}
if (this->IsSynthetic()) {
return true;
}
switch (this->GetType()) {
case cmStateEnums::EXECUTABLE:
case cmStateEnums::STATIC_LIBRARY:
+4
View File
@@ -291,6 +291,10 @@ public:
cmBTStringRange GetLinkInterfaceDirectEntries() const;
cmBTStringRange GetLinkInterfaceDirectExcludeEntries() const;
void CopyPolicyStatuses(cmTarget const* tgt);
void CopyImportedCxxModulesEntries(cmTarget const* tgt);
void CopyImportedCxxModulesProperties(cmTarget const* tgt);
cmBTStringRange GetHeaderSetsEntries() const;
cmBTStringRange GetCxxModuleSetsEntries() const;
@@ -2517,6 +2517,7 @@ void cmVisualStudio10TargetGenerator::WriteAllSources(Elem& e0)
case cmGeneratorTarget::SourceKindModuleDefinition:
tool = "None";
break;
case cmGeneratorTarget::SourceKindCxxModuleSource:
case cmGeneratorTarget::SourceKindUnityBatched:
case cmGeneratorTarget::SourceKindObjectSource: {
const std::string& lang = si.Source->GetLanguage();
+1 -1
View File
@@ -1,6 +1,6 @@
cmake_minimum_required(VERSION 3.23)
project(${RunCMake_TEST} NONE)
set(CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API "a816ed09-43d1-40e5-bc8c-1a2824ee194e")
set(CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API "ac01f462-0f5f-432a-86aa-acef252918a6")
include(${RunCMake_TEST}.cmake)
@@ -187,7 +187,20 @@ endif ()
if ("export_bmi" IN_LIST CMake_TEST_MODULE_COMPILATION)
run_cxx_module_test(export-interface-no-properties-build)
run_cxx_module_test(export-interface-build)
run_cxx_module_test(export-usage-build)
run_cxx_module_test(export-bmi-and-interface-build)
if ("collation" IN_LIST CMake_TEST_MODULE_COMPILATION AND
"bmionly" IN_LIST CMake_TEST_MODULE_COMPILATION)
set(test_suffix export-interface-build)
run_cxx_module_test(import-modules "import-modules-${test_suffix}" "-DCMAKE_PREFIX_PATH=${RunCMake_BINARY_DIR}/examples/${test_suffix}-build")
set(test_suffix export-interface-no-properties-build)
run_cxx_module_test(import-modules "import-modules-${test_suffix}" "-DCMAKE_PREFIX_PATH=${RunCMake_BINARY_DIR}/examples/${test_suffix}-build" -DNO_PROPERTIES=1)
set(test_suffix export-bmi-and-interface-build)
run_cxx_module_test(import-modules "import-modules-${test_suffix}" "-DCMAKE_PREFIX_PATH=${RunCMake_BINARY_DIR}/examples/${test_suffix}-build" -DWITH_BMIS=1)
endif ()
endif ()
# All of the following tests perform installation.
@@ -201,6 +214,21 @@ if ("install_bmi" IN_LIST CMake_TEST_MODULE_COMPILATION)
if ("export_bmi" IN_LIST CMake_TEST_MODULE_COMPILATION)
run_cxx_module_test(export-interface-no-properties-install)
run_cxx_module_test(export-interface-install)
run_cxx_module_test(export-usage-install)
run_cxx_module_test(export-bmi-and-interface-install)
if ("collation" IN_LIST CMake_TEST_MODULE_COMPILATION AND
"bmionly" IN_LIST CMake_TEST_MODULE_COMPILATION)
set(RunCMake_CXXModules_INSTALL 0)
set(test_suffix export-interface-install)
run_cxx_module_test(import-modules "import-modules-${test_suffix}" "-DCMAKE_PREFIX_PATH=${RunCMake_BINARY_DIR}/examples/${test_suffix}-install")
set(test_suffix export-interface-no-properties-install)
run_cxx_module_test(import-modules "import-modules-${test_suffix}" "-DCMAKE_PREFIX_PATH=${RunCMake_BINARY_DIR}/examples/${test_suffix}-install" -DNO_PROPERTIES=1)
set(test_suffix export-bmi-and-interface-install)
run_cxx_module_test(import-modules "import-modules-${test_suffix}" "-DCMAKE_PREFIX_PATH=${RunCMake_BINARY_DIR}/examples/${test_suffix}-install" -DWITH_BMIS=1)
set(RunCMake_CXXModules_INSTALL 1)
endif ()
endif ()
endif ()
@@ -1,4 +1,4 @@
set(CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API "a816ed09-43d1-40e5-bc8c-1a2824ee194e")
set(CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API "ac01f462-0f5f-432a-86aa-acef252918a6")
if (NOT EXISTS "${CMake_TEST_MODULE_COMPILATION_RULES}")
message(FATAL_ERROR
@@ -1,7 +1,7 @@
cmake_minimum_required(VERSION 3.24)
project(cxx_modules_library NONE)
set(CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API "a816ed09-43d1-40e5-bc8c-1a2824ee194e")
set(CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API "ac01f462-0f5f-432a-86aa-acef252918a6")
find_package(export_bmi_and_interfaces REQUIRED)
@@ -1,7 +1,7 @@
cmake_minimum_required(VERSION 3.24)
project(cxx_modules_library NONE)
set(CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API "a816ed09-43d1-40e5-bc8c-1a2824ee194e")
set(CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API "ac01f462-0f5f-432a-86aa-acef252918a6")
find_package(export_bmi_and_interfaces REQUIRED)
@@ -1,7 +1,7 @@
cmake_minimum_required(VERSION 3.24)
project(cxx_modules_library NONE)
set(CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API "a816ed09-43d1-40e5-bc8c-1a2824ee194e")
set(CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API "ac01f462-0f5f-432a-86aa-acef252918a6")
find_package(export_interfaces REQUIRED)
@@ -1,7 +1,7 @@
cmake_minimum_required(VERSION 3.24)
project(cxx_modules_library NONE)
set(CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API "a816ed09-43d1-40e5-bc8c-1a2824ee194e")
set(CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API "ac01f462-0f5f-432a-86aa-acef252918a6")
find_package(export_interfaces REQUIRED)
@@ -1,7 +1,7 @@
cmake_minimum_required(VERSION 3.24)
project(cxx_modules_library NONE)
set(CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API "a816ed09-43d1-40e5-bc8c-1a2824ee194e")
set(CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API "ac01f462-0f5f-432a-86aa-acef252918a6")
find_package(export_interfaces_no_properties REQUIRED)
@@ -1,7 +1,7 @@
cmake_minimum_required(VERSION 3.24)
project(cxx_modules_library NONE)
set(CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API "a816ed09-43d1-40e5-bc8c-1a2824ee194e")
set(CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API "ac01f462-0f5f-432a-86aa-acef252918a6")
find_package(export_interfaces_no_properties REQUIRED)
@@ -0,0 +1,4 @@
CMake Warning \(dev\) at CMakeLists.txt:7 \(target_sources\):
CMake's C\+\+ module support is experimental. It is meant only for
experimentation and feedback to CMake developers.
This warning is for project developers. Use -Wno-dev to suppress it.
@@ -0,0 +1,110 @@
cmake_minimum_required(VERSION 3.24)
project(cxx_modules_export_usage CXX)
include("${CMAKE_SOURCE_DIR}/../cxx-modules-rules.cmake")
add_library(export_usage STATIC)
target_sources(export_usage
PRIVATE
forward.cxx
PRIVATE
FILE_SET modules_private TYPE CXX_MODULES
BASE_DIRS
"${CMAKE_CURRENT_SOURCE_DIR}"
FILES
private.cxx
PUBLIC
FILE_SET modules TYPE CXX_MODULES
BASE_DIRS
"${CMAKE_CURRENT_SOURCE_DIR}"
FILES
importable.cxx)
target_compile_features(export_usage PUBLIC cxx_std_20)
list(APPEND CMAKE_CXX_KNOWN_FEATURES
exported
buildiface
installiface
buildlocaliface)
target_include_directories(export_usage
PRIVATE
"/usr/exported"
"$<BUILD_INTERFACE:/usr/buildiface>"
"$<INSTALL_INTERFACE:/usr/installiface>"
"$<BUILD_LOCAL_INTERFACE:/usr/buildlocaliface>")
target_compile_definitions(export_usage
PRIVATE
"exported"
"$<BUILD_INTERFACE:buildiface>"
"$<INSTALL_INTERFACE:installiface>"
"$<BUILD_LOCAL_INTERFACE:buildlocaliface>")
target_compile_features(export_usage
PRIVATE
"cxx_std_11"
"$<BUILD_INTERFACE:cxx_std_14>"
"$<INSTALL_INTERFACE:cxx_std_17>"
"$<BUILD_LOCAL_INTERFACE:cxx_std_20>")
if (MSVC)
set(variable_flag "-constexpr:depth")
else ()
set(variable_flag "-fconstexpr-depth=")
endif ()
target_compile_options(export_usage
PRIVATE
"${variable_flag}100"
"$<BUILD_INTERFACE:${variable_flag}200>"
"$<INSTALL_INTERFACE:${variable_flag}300>"
"$<BUILD_LOCAL_INTERFACE:${variable_flag}400>")
add_library(export_used INTERFACE)
add_library(export_build INTERFACE)
add_library(export_install INTERFACE)
add_library(export_never INTERFACE)
target_link_libraries(export_usage
PRIVATE
"export_used"
"$<BUILD_INTERFACE:export_build>"
"$<INSTALL_INTERFACE:export_install>"
"$<BUILD_LOCAL_INTERFACE:export_never>")
install(TARGETS export_usage
EXPORT CXXModules
FILE_SET modules DESTINATION "lib/cxx/miu")
export(EXPORT CXXModules
NAMESPACE CXXModules::
FILE "${CMAKE_CURRENT_BINARY_DIR}/export_usage-targets.cmake")
install(TARGETS export_used export_build export_install
EXPORT CXXModulesDeps)
export(EXPORT CXXModulesDeps
NAMESPACE CXXModules::
FILE "${CMAKE_CURRENT_BINARY_DIR}/export_usage-dep-targets.cmake")
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/export_usage-config.cmake"
"include(\"\${CMAKE_CURRENT_LIST_DIR}/export_usage-dep-targets.cmake\")
include(\"\${CMAKE_CURRENT_LIST_DIR}/export_usage-targets.cmake\")
set(\${CMAKE_FIND_PACKAGE_NAME}_FOUND 1)
")
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 export_usage_build
COMMAND
"${CMAKE_COMMAND}"
"-Dexpected_dir=${CMAKE_CURRENT_SOURCE_DIR}"
"-Dexport_interfaces_flag=${variable_flag}"
"-Dexport_usage_DIR=${CMAKE_CURRENT_BINARY_DIR}"
${generator}
-S "${CMAKE_CURRENT_SOURCE_DIR}/test"
-B "${CMAKE_CURRENT_BINARY_DIR}/test")
@@ -0,0 +1,6 @@
import priv;
int forwarding()
{
return from_private();
}
@@ -0,0 +1,10 @@
export module importable;
extern "C++" {
int forwarding();
}
export int from_import()
{
return forwarding();
}
@@ -0,0 +1,6 @@
export module priv;
export int from_private()
{
return 0;
}
@@ -0,0 +1,69 @@
cmake_minimum_required(VERSION 3.24)
project(cxx_modules_library NONE)
set(CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API "ac01f462-0f5f-432a-86aa-acef252918a6")
find_package(export_usage REQUIRED)
if (NOT TARGET CXXModules::export_usage)
message(FATAL_ERROR
"Missing imported target")
endif ()
if (NOT TARGET CXXModules::export_used)
message(FATAL_ERROR
"Missing imported target")
endif ()
if (NOT TARGET CXXModules::export_build)
message(FATAL_ERROR
"Missing imported target")
endif ()
if (NOT TARGET CXXModules::export_install)
message(FATAL_ERROR
"Missing imported target")
endif ()
if (TARGET CXXModules::export_never)
message(FATAL_ERROR
"Extra imported target")
endif ()
function (check_property expected property)
get_property(actual TARGET CXXModules::export_usage
PROPERTY "${property}")
if (NOT actual STREQUAL expected)
message(SEND_ERROR
"Mismatch for ${property}:\n expected: ${expected}\n actual: ${actual}")
endif ()
endfunction ()
check_property("/usr/exported;/usr/buildiface" "IMPORTED_CXX_MODULES_INCLUDE_DIRECTORIES")
check_property("exported;buildiface" "IMPORTED_CXX_MODULES_COMPILE_DEFINITIONS")
check_property("cxx_std_20;cxx_std_11;cxx_std_14" "IMPORTED_CXX_MODULES_COMPILE_FEATURES")
check_property("${export_interfaces_flag}100;${export_interfaces_flag}200" "IMPORTED_CXX_MODULES_COMPILE_OPTIONS")
check_property("$<COMPILE_ONLY:CXXModules::export_used>;$<COMPILE_ONLY:CXXModules::export_build>" "IMPORTED_CXX_MODULES_LINK_LIBRARIES")
# Extract the export-dependent targets from the export file.
file(STRINGS "${export_usage_DIR}/export_usage-targets.cmake" usage_dependent_targets
REGEX "foreach._target ")
# Rudimentary argument splitting.
string(REPLACE " " ";" usage_dependent_targets "${usage_dependent_targets}")
# Keep only "target" names.
list(FILTER usage_dependent_targets INCLUDE REGEX "CXXModules::")
# Strip quotes.
string(REPLACE "\"" "" usage_dependent_targets "${usage_dependent_targets}")
if (NOT "CXXModules::export_used" IN_LIST usage_dependent_targets)
message(SEND_ERROR
"The main export does not require the 'CXXModules::export_used' target")
endif ()
if (NOT "CXXModules::export_build" IN_LIST usage_dependent_targets)
message(SEND_ERROR
"The main export does not require the 'CXXModules::export_build' target")
endif ()
if ("CXXModules::export_install" IN_LIST usage_dependent_targets)
message(SEND_ERROR
"The main export requires the 'CXXModules::export_install' target")
endif ()
@@ -0,0 +1,4 @@
CMake Warning \(dev\) at CMakeLists.txt:7 \(target_sources\):
CMake's C\+\+ module support is experimental. It is meant only for
experimentation and feedback to CMake developers.
This warning is for project developers. Use -Wno-dev to suppress it.
@@ -0,0 +1,114 @@
cmake_minimum_required(VERSION 3.24)
project(cxx_modules_export_usage CXX)
include("${CMAKE_SOURCE_DIR}/../cxx-modules-rules.cmake")
add_library(export_usage STATIC)
target_sources(export_usage
PRIVATE
forward.cxx
PRIVATE
FILE_SET modules_private TYPE CXX_MODULES
BASE_DIRS
"${CMAKE_CURRENT_SOURCE_DIR}"
FILES
private.cxx
PUBLIC
FILE_SET modules TYPE CXX_MODULES
BASE_DIRS
"${CMAKE_CURRENT_SOURCE_DIR}"
FILES
importable.cxx)
target_compile_features(export_usage PUBLIC cxx_std_20)
list(APPEND CMAKE_CXX_KNOWN_FEATURES
exported
buildiface
installiface
buildlocaliface)
target_include_directories(export_usage
PRIVATE
"/usr/exported"
"$<BUILD_INTERFACE:/usr/buildiface>"
"$<INSTALL_INTERFACE:/usr/installiface>"
"$<BUILD_LOCAL_INTERFACE:/usr/buildlocaliface>")
target_compile_definitions(export_usage
PRIVATE
"exported"
"$<BUILD_INTERFACE:buildiface>"
"$<INSTALL_INTERFACE:installiface>"
"$<BUILD_LOCAL_INTERFACE:buildlocaliface>")
target_compile_features(export_usage
PRIVATE
"cxx_std_11"
"$<BUILD_INTERFACE:cxx_std_14>"
"$<INSTALL_INTERFACE:cxx_std_17>"
"$<BUILD_LOCAL_INTERFACE:cxx_std_20>")
if (MSVC)
set(variable_flag "-constexpr:depth")
else ()
set(variable_flag "-fconstexpr-depth=")
endif ()
target_compile_options(export_usage
PRIVATE
"${variable_flag}100"
"$<BUILD_INTERFACE:${variable_flag}200>"
"$<INSTALL_INTERFACE:${variable_flag}300>"
"$<BUILD_LOCAL_INTERFACE:${variable_flag}400>")
add_library(export_used INTERFACE)
add_library(export_build INTERFACE)
add_library(export_install INTERFACE)
add_library(export_never INTERFACE)
target_link_libraries(export_usage
PRIVATE
"export_used"
"$<BUILD_INTERFACE:export_build>"
"$<INSTALL_INTERFACE:export_install>"
"$<BUILD_LOCAL_INTERFACE:export_never>")
install(TARGETS export_usage
EXPORT CXXModules
FILE_SET modules DESTINATION "lib/cxx/miu")
install(EXPORT CXXModules
NAMESPACE CXXModules::
DESTINATION "lib/cmake/export_usage"
FILE "export_usage-targets.cmake")
install(TARGETS export_used export_build export_install
EXPORT CXXModulesDeps)
install(EXPORT CXXModulesDeps
NAMESPACE CXXModules::
DESTINATION "lib/cmake/export_usage"
FILE "export_usage-dep-targets.cmake")
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/export_usage-config.cmake"
"include(\"\${CMAKE_CURRENT_LIST_DIR}/export_usage-dep-targets.cmake\")
include(\"\${CMAKE_CURRENT_LIST_DIR}/export_usage-targets.cmake\")
set(\${CMAKE_FIND_PACKAGE_NAME}_FOUND 1)
")
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/export_usage-config.cmake"
DESTINATION "lib/cmake/export_usage")
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 export_usage_build
COMMAND
"${CMAKE_COMMAND}"
"-Dexpected_dir=${CMAKE_INSTALL_PREFIX}/lib/cxx/miu"
"-Dexport_interfaces_flag=${variable_flag}"
"-Dexport_usage_DIR=${CMAKE_INSTALL_PREFIX}/lib/cmake/export_usage"
${generator}
-S "${CMAKE_CURRENT_SOURCE_DIR}/test"
-B "${CMAKE_CURRENT_BINARY_DIR}/test")
@@ -0,0 +1,6 @@
import priv;
int forwarding()
{
return from_private();
}
@@ -0,0 +1,10 @@
export module importable;
extern "C++" {
int forwarding();
}
export int from_import()
{
return forwarding();
}
@@ -0,0 +1,6 @@
export module priv;
export int from_private()
{
return 0;
}
@@ -0,0 +1,69 @@
cmake_minimum_required(VERSION 3.24)
project(cxx_modules_library NONE)
set(CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API "ac01f462-0f5f-432a-86aa-acef252918a6")
find_package(export_usage REQUIRED)
if (NOT TARGET CXXModules::export_usage)
message(FATAL_ERROR
"Missing imported target")
endif ()
if (NOT TARGET CXXModules::export_used)
message(FATAL_ERROR
"Missing imported target")
endif ()
if (NOT TARGET CXXModules::export_build)
message(FATAL_ERROR
"Missing imported target")
endif ()
if (NOT TARGET CXXModules::export_install)
message(FATAL_ERROR
"Missing imported target")
endif ()
if (TARGET CXXModules::export_never)
message(FATAL_ERROR
"Extra imported target")
endif ()
function (check_property expected property)
get_property(actual TARGET CXXModules::export_usage
PROPERTY "${property}")
if (NOT actual STREQUAL expected)
message(SEND_ERROR
"Mismatch for ${property}:\n expected: ${expected}\n actual : ${actual}")
endif ()
endfunction ()
check_property("/usr/exported;/usr/installiface" "IMPORTED_CXX_MODULES_INCLUDE_DIRECTORIES")
check_property("exported;installiface" "IMPORTED_CXX_MODULES_COMPILE_DEFINITIONS")
check_property("cxx_std_20;cxx_std_11;cxx_std_17" "IMPORTED_CXX_MODULES_COMPILE_FEATURES")
check_property("${export_interfaces_flag}100;${export_interfaces_flag}300" "IMPORTED_CXX_MODULES_COMPILE_OPTIONS")
check_property("$<COMPILE_ONLY:CXXModules::export_used>;$<COMPILE_ONLY:CXXModules::export_install>" "IMPORTED_CXX_MODULES_LINK_LIBRARIES")
# Extract the export-dependent targets from the export file.
file(STRINGS "${export_usage_DIR}/export_usage-targets.cmake" usage_dependent_targets
REGEX "foreach._target ")
# Rudimentary argument splitting.
string(REPLACE " " ";" usage_dependent_targets "${usage_dependent_targets}")
# Keep only "target" names.
list(FILTER usage_dependent_targets INCLUDE REGEX "CXXModules::")
# Strip quotes.
string(REPLACE "\"" "" usage_dependent_targets "${usage_dependent_targets}")
if (NOT "CXXModules::export_used" IN_LIST usage_dependent_targets)
message(SEND_ERROR
"The main export does not require the 'CXXModules::export_used' target")
endif ()
if ("CXXModules::export_build" IN_LIST usage_dependent_targets)
message(SEND_ERROR
"The main export requires the 'CXXModules::export_build' target")
endif ()
if (NOT "CXXModules::export_install" IN_LIST usage_dependent_targets)
message(SEND_ERROR
"The main export does not require the 'CXXModules::export_install' target")
endif ()
@@ -0,0 +1,7 @@
CMake Warning \(dev\) at .*/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-build-build/export_bmi_and_interfaces-targets.cmake:[0-9]* \(target_sources\):
CMake's C\+\+ module support is experimental. It is meant only for
experimentation and feedback to CMake developers.
Call Stack \(most recent call first\):
.*/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-build-build/export_bmi_and_interfaces-config.cmake:1 \(include\)
CMakeLists.txt:15 \(find_package\)
This warning is for project developers. Use -Wno-dev to suppress it.
@@ -0,0 +1,7 @@
CMake Warning \(dev\) at .*/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-install-install/lib/cmake/export_bmi_and_interfaces/export_bmi_and_interfaces-targets.cmake:[0-9]* \(target_sources\):
CMake's C\+\+ module support is experimental. It is meant only for
experimentation and feedback to CMake developers.
Call Stack \(most recent call first\):
.*/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-install-install/lib/cmake/export_bmi_and_interfaces/export_bmi_and_interfaces-config.cmake:1 \(include\)
CMakeLists.txt:15 \(find_package\)
This warning is for project developers. Use -Wno-dev to suppress it.
@@ -0,0 +1,7 @@
CMake Warning \(dev\) at .*/Tests/RunCMake/CXXModules/examples/export-interface-build-build/export_interfaces-targets.cmake:[0-9]* \(target_sources\):
CMake's C\+\+ module support is experimental. It is meant only for
experimentation and feedback to CMake developers.
Call Stack \(most recent call first\):
.*/Tests/RunCMake/CXXModules/examples/export-interface-build-build/export_interfaces-config.cmake:1 \(include\)
CMakeLists.txt:15 \(find_package\)
This warning is for project developers. Use -Wno-dev to suppress it.
@@ -0,0 +1,7 @@
CMake Warning \(dev\) at .*/Tests/RunCMake/CXXModules/examples/export-interface-install-install/lib/cmake/export_interfaces/export_interfaces-targets.cmake:[0-9]* \(target_sources\):
CMake's C\+\+ module support is experimental. It is meant only for
experimentation and feedback to CMake developers.
Call Stack \(most recent call first\):
.*/Tests/RunCMake/CXXModules/examples/export-interface-install-install/lib/cmake/export_interfaces/export_interfaces-config.cmake:1 \(include\)
CMakeLists.txt:15 \(find_package\)
This warning is for project developers. Use -Wno-dev to suppress it.
@@ -0,0 +1,7 @@
CMake Warning \(dev\) at .*/Tests/RunCMake/CXXModules/examples/export-interface-no-properties-build-build/export_interfaces_no_properties-targets.cmake:[0-9]* \(target_sources\):
CMake's C\+\+ module support is experimental. It is meant only for
experimentation and feedback to CMake developers.
Call Stack \(most recent call first\):
.*/Tests/RunCMake/CXXModules/examples/export-interface-no-properties-build-build/export_interfaces_no_properties-config.cmake:1 \(include\)
CMakeLists.txt:15 \(find_package\)
This warning is for project developers. Use -Wno-dev to suppress it.
@@ -0,0 +1,7 @@
CMake Warning \(dev\) at .*/Tests/RunCMake/CXXModules/examples/export-interface-no-properties-install-install/lib/cmake/export_interfaces_no_properties/export_interfaces_no_properties-targets.cmake:[0-9]* \(target_sources\):
CMake's C\+\+ module support is experimental. It is meant only for
experimentation and feedback to CMake developers.
Call Stack \(most recent call first\):
.*/Tests/RunCMake/CXXModules/examples/export-interface-no-properties-install-install/lib/cmake/export_interfaces_no_properties/export_interfaces_no_properties-config.cmake:1 \(include\)
CMakeLists.txt:15 \(find_package\)
This warning is for project developers. Use -Wno-dev to suppress it.
@@ -0,0 +1,24 @@
cmake_minimum_required(VERSION 3.24)
project(cxx_modules_import_interfaces CXX)
include("${CMAKE_SOURCE_DIR}/../cxx-modules-rules.cmake")
if (NO_PROPERTIES)
set(package_name "export_interfaces_no_properties")
elseif (WITH_BMIS)
set(package_name "export_bmi_and_interfaces")
else ()
set(package_name "export_interfaces")
endif ()
set(target_name "CXXModules::${package_name}")
find_package("${package_name}" REQUIRED)
add_executable(use_import_interfaces)
target_sources(use_import_interfaces
PRIVATE
use.cxx)
target_compile_features(use_import_interfaces PRIVATE cxx_std_20)
target_link_libraries(use_import_interfaces PRIVATE "${target_name}")
add_test(NAME use_import_interfaces COMMAND use_import_interfaces)
@@ -0,0 +1,6 @@
import importable;
int main(int argc, char* argv[])
{
return from_import();
}
@@ -1,6 +1,6 @@
enable_language(C)
set(CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API "a816ed09-43d1-40e5-bc8c-1a2824ee194e")
set(CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API "ac01f462-0f5f-432a-86aa-acef252918a6")
add_library(lib1 STATIC empty.c)
target_sources(lib1 PRIVATE FILE_SET UNKNOWN)
@@ -1,6 +1,6 @@
enable_language(C)
set(CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API "a816ed09-43d1-40e5-bc8c-1a2824ee194e")
set(CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API "ac01f462-0f5f-432a-86aa-acef252918a6")
add_library(lib1 STATIC empty.c)
target_sources(lib1 PRIVATE FILE_SET a TYPE UNKNOWN)
+2
View File
@@ -333,6 +333,7 @@ CMAKE_CXX_SOURCES="\
cmCustomCommandGenerator \
cmCustomCommandLines \
cmCxxModuleMapper \
cmCxxModuleUsageEffects \
cmDefinePropertyCommand \
cmDefinitions \
cmDocumentationFormatter \
@@ -392,6 +393,7 @@ CMAKE_CXX_SOURCES="\
cmGlobVerificationManager \
cmHexFileConverter \
cmIfCommand \
cmImportedCxxModuleInfo \
cmIncludeCommand \
cmIncludeGuardCommand \
cmIncludeDirectoryCommand \